How to pass a variable stored in background.js to an async function in the content script?

3,480 views
Skip to first unread message

Jaliya roshen Jayarathne

unread,
Aug 23, 2022, 9:28:58 AM8/23/22
to Chromium Extensions

I am creating an extension related to automation. In that extension, the activities we do in DOM/ Web page are captured and finally saved as a json file. A chrome extension Like this. https://sideex.io/

Therefore, My reuirement is this. The Title of the tab where I start the record should be given to the json file when saving. Since several tabs can be captured at onece, the title of the first tab has been obtained and assigned to the global variable in background.js like below.

contentScript-01.js

function getPageInformation() {
    const pageTitle = document.getElementsByTagName('title')[0].innerHTML;
    const processTitle = pageTitle
        .trim()
        .toLowerCase()
        .replace(/[^a-zA-Z ]/g, '');
    const titleToArray = processTitle.split(' ');
    const setPageTitle = titleToArray.join('-').concat('-capture.json');
    chrome.runtime.sendMessage({
            action: 'setPageTitle',
            title: setPageTitle
        },
        function(response) {
            if (response.data) {
                console.log('response received', response.data);
            }
        }
    );
    return setPageTitle;
}


async function saveRecording(contents) {
    saveFile(contents);
    return Promise.resolve();
}

function saveFile(data) {
    const blob = new Blob([data], {
        type: 'text/csv'
    });
    const elem = window.document.createElement('a');
    elem.href = window.URL.createObjectURL(blob);
    elem.download = 'data.json'; // This should replace with that pageTitle
    document.body.appendChild(elem);
    elem.click();
    document.body.removeChild(elem);
    alert('Your File has been saved');
}

background.js

var pageTitle;

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
            if (msg.action == 'setPageTitle') {
                pageTitle = msg.title;
                console.log(pageTitleRPA);
                sendResponse({
                    data: pageTitle
                });
            }
        }

Below is the second content script that starts and stops the capturing functionaly with small popup.

...
recordButton = document.getElementById('recording_button');
if (recordButton) {
    recordButton.addEventListener('click', function() {
            chrome.runtime.sendMessage({
                action: 'isRecording'
            }, function(response) {
                if (response) {
                    chrome.runtime.sendMessage({
                            action: 'stopRecording'
                        },
                        function(response) {
                            // This response means captured data in json
                            saveRecording(response).then(() => {
                                stopRecording(); // change UI button start to stop
                            });
                        }
                    );
                } else {
                    chrome.runtime.sendMessage({
                            action: 'startRecording'
                        },
                        function(response) {
                            startRecording();
                        }
                    );
                    getPageInformation();
                }
            });
        },
    }

How to use the variable in the background to the file name of this json. The background script was used to keep the ttile of the first tab. If you go to a second tab/window through the first tab, the title is saved as the title of the second page. I am using manifest version 3. background script as a service worker. Plase give some help regarding this.



Mike-O

unread,
Aug 24, 2022, 7:23:31 PM8/24/22
to Chromium Extensions, jaliya...@gmail.com
Make the content.js send a message to the service worker and then the service worker can respond on that message back to the content script. However, this may not be necessary. You can use chrome.storage APIs (either sync or local), or the far-more-difficult IndexedDB, to keep the state management that you want. Remember -- the service worker disconnects and goes idle when not used and any global variables it has will get lost until the content script or panel connect to it again, or any API call you may have in it wakes it up.

This was a hard thing for me to understand at first in my transition from MV2 to MV3 because I used global variables a great bit in my background.js before I had to move to the service worker concept where they do not work well. Then, I had to use chrome.storage APIs, which I feared would operate very slowly when in fact they do not. The only catch with the chrome.storage APIs is that you'll need to utilize either the function callback, or wrap it in a Promise so that you can utilize async/await, for reading those variables.

As far as state management per tab, you'll have to implement an array and store that with chrome.storage, where a tab ID is the index in that array. Plus, you'll have to detect removed tabs and remove those array entries from chrome.storage.
Reply all
Reply to author
Forward
0 new messages