Browser extension: making messages available externally

Hello!
I’m playing around with Clockify browser extension code that lives here.

Here the extension is setting up some message handlers using runtime.onMessage.addListener which receive messages from other parts of the extension.

I have an idea about building an extension that is using Clockify. I need start timer/stop timer capabilities but I don’t want to maintain the implementation on my own. Instead I would prefer using what’s already done in the Clockify browser extension.

I could just send messages to the Clockify extesion using something like this:

   browser.runtime.sendMessage({
     extensionId: 'pmjeegjhjdlccodhacdgbgfagbpmccpe',
     eventName: 'startWithDescription',
     timeEntryOptions: timeEntryOptionsInvoked
   }, () => {...});

However this requires the original Clockify extension to accept the messages extrenally, so beside runtime.onMessage.addListener we would also need to set the same handler as runtime.onExternalMessage.addListener.

This way operations from the Clockify extensions like startWithDescription, endInProgress and submitTime could be available to other extensions and I could build some custom business logic that is sending messages to the Clockify extension and thus using this messages as an API.

@clockify do you think this is something acceptable from your side: adding support for external messages from other extensions? Would you accept a PR with such change?

1 Like

That’s interesting, thanks for the suggestion! It sounds simple and doesn’t introduce complications, so there shouldn’t issues with accepting the PR.

Just send us the PR on Github, and out development team will take it from there.

1 Like

Very soon we are going to deploy latest version of ‘clockify/browser-extension’ at

We are going to enable Cross-extension messaging, exposing a public API that other extensions can take advantage of.

Here is example of ussage:

chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id == blocklistedExtension)
return; // don’t allow this extension access
else if (request.getTargetData)
sendResponse({targetData: targetData});
});

1 Like

We enabled Cross-extension messaging, exposing a public API that other extensions can take advantage of.
Here is the example of how your Extension can Start new Time Entry, or Stop it:

// Clockify Time Tracker / Cross-extension messaging.
// External Extensions use Authentication and Settings of Clockify Time Tracker Extension.

const aBrowser = (isChrome || isEdge) ? chrome : browser;
// Clockify Time Tracker Extension ID
const extensionID = (isChrome || isEdge) 
        ? 'pmjeegjhjdlccodhacdgbgfagbpmccpe'
        : '{1262fc44-5ec9-4088-a7a7-4cd42f3f548d}';

// start new Time Entry
aBrowser.runtime.sendMessage(
    extensionID, 
    {
        eventName: 'startNewEntry',
        data: {
            description: 'studying',
            project: { name: '' || 'abc' || null },
            task: { name: '' || 'ttt' || null },
            billable: false || true || null,
            tags: ['media', 'social']
        }
    },
    (response) => {
        if (response) {
            const { entry, message } = response;
            console.log(entry, message);
        }
    }
);

// stop Entry in progress
aBrowser.runtime.sendMessage(
    extensionID, 
    {
        eventName: 'endInProgress'
    },
    (response) => {
        if (response) {
            const { entry, message } = response;
            console.log(entry, message);
        }
    }
);
1 Like