Search code examples
javascriptreactjsgoogle-chrome-extensionmessagingfirefox-addon-webextensions

Data from Extension to Webpage for Initial Load of the webpage - Firefox


Creating an extension for Chrome and Firefox. Based on our requirement, we need some of the information(previously stored in storage by extension) from extension to webpage at the time page load. Data needed in webpage before any XHR request trigger from webpage. This is achieved in Chrome by following code but unable to get the same for Firefox. Data not received to webpage as similar to Chrome as fast.

Note: Webpage is a react application

For Chrome (Working Code)

// Code in Webpage
chrome.runtime.sendMessage('extensionId', { messageFromWeb: 'Sample message' }, (response) =>{
    console.log('OnInit Page Details', response);
});

// Code in background.js
chrome.runtime.onMessageExternal.addListener(async function (request, sender, sendResponse) {
    sendResponse({ detail: {} });
});

For Firefox, implemented the same with window.postmessage but it is not as fast as chrome, got data in delayed(after xhr request triggered from webpage, need to get before that).

// Code in Webpage
window.postMessage({ type: 'FROM_WEB_PAGE' }, '*');

window.addEventListener('message', (event) => {
    if (event.data.type && (event.data.type === 'DATA_BACK_FROM_EXTENSION')) {
        console.log('On Init', event.data);
    }
}, false);


// Code in Content-Script
window.addEventListener("message", function(event) {
    if (event.data.type && (event.data.type === "FROM_WEB_PAGE")) {
        chrome.runtime.sendMessage('GetInitialData');
    }
}, false);


// Code in background.js
chrome.runtime.onMessage.addListener(function (response) {
    window.postMessage( { type: 'DATA_BACK_FROM_EXTENSION', detail: response }, '*');
});


Solution

  • In Firefox there's an even faster method: register a dynamically generated code as a content script that runs at document_start and then exposes the data to the web page via wrappedJSObject so the page has direct access to the data synchronously, right at the start.

    background script:

    let dataReg;
    async function exposeData(data) {
      dataReg = await browser.contentScripts.register({
        js: [{
          code: `wrappedJSObject.__extensionData =
            cloneInto(${JSON.stringify(data)}, wrappedJSObject)`,
        }],
        matches: ['https://your.web.app/*'],
        runAt: 'document_start',
      });
    }
    

    Your web app then uses window.__extensionData directly.