exec85
exec85

Reputation: 487

chrome extension call specific function

I have a popup.js:

function registerButtonAction(tabId, button, action) {
    // clicking button will send a message to
    // content script in the same tab as the popup
    button.addEventListener('click', () => chrome.tabs.sendMessage(tabId, { [action]: true }));
}

function setupButtons(tabId) {
    // add click actions to each 3 buttons
    registerButtonAction(tabId, document.getElementById('start-btn'), 'startSearch');
    registerButtonAction(tabId, document.getElementById('deals-btn'), 'startDeals');
}

function injectStartSearchScript() {
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        // Injects JavaScript code into a page
        // chrome.tabs.executeScript(tabs[0].id, { file: 'main.js' });

        // dd click handlers for buttons
        setupButtons(tabs[0].id);
    });
}

injectStartSearchScript()

// document.getElementById('inject-btn').addEventListener('click', injectStartSearchScript);

Which I use to inject my script into the page with the "start-btn" inside my popup.html.

This is my main.js which includes my functions I would like to call on a page:

function pong() {
    // do something
}

function ping() {
// do something else
}

my manifest.json:

{
    "manifest_version": 2,
    "name": "test app",
    "description": "test desc",
    "version": "1.0",
    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    "permissions": ["tabs", "<all_urls>"],
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["main.js"]
        }
    ]
}

So basically my setup is that I have a popup.html which includes 3 buttons and they should call one of the functions inside my main.js dpending on what button i press.

But I can not get that working. Currently I only can make at least one function call if I directly call pong() inside main.js on load. But I would need to call one of the functions after I click on a button inside my popup.html.

EDIT: I have updated the code as far as I understood. I am very sorry but I don't understand what would be needed to be changed else to fulfill your proposal. I mean how to write it to be more correct.

EDIT 2: I have removed the line chrome.tabs.executeScript(tabs[0].id, { file: 'main.js' }); as well as document.getElementById('inject-btn').addEventListener('click', injectStartSearchScript)and added injectStartSearchScript()into the popup.js file. Is that what you meant?

Upvotes: 1

Views: 1910

Answers (1)

Neea
Neea

Reputation: 1424

Updated and complete example with explanation (you are almost there!)

manifest

You manifest looks good, no changes needed there.

This configuration says to load the content script in each tab. So before popup even opens each tab will have "main.js" injected into it (exactly once).

popup.js

Popup script looks good, no changes needed there.

The tab lookup is still necessary, since to send a message to a specific tab, must know its id. The popup looks for the currently active tab in current window (same as the popup is in) and sets up the button click actions to send a message to the tab.

main.js

Will need minor changes here

  • Make sure to register the onMessage listener, as included in the example below.
  • note the conditions: message.startSearch and message.startDeals -- these must match the messages sent from the popup, i.e. when popup sends a message with content {startDeals: true}, the if condition is startDeals. It is matching by a key in the sent message and if the key does not match any condition, the message is going to be ignored.
function pong() {
    // do something
    alert('Start!');
}

function ping() {
    // do something else
    alert('Deals!');
}

// register listener to receive messages
chrome.runtime.onMessage.addListener(message => {

    // what to do on each received message:
    if (message.startSearch) pong();
    else if (message.startDeals) ping();
});

// sanity check: content has loaded in the tab
console.log('content loaded');

One more note as it relates to debugging extensions (and perhaps a source of some of these debugging issues) when the content script has been configured to be injected in the manifest, Chrome will inject main.js into tabs, in a separate extension context. If, after this injection, the developer reloads the extension (circular arrow in chrome://extensions or other tool), this will invalidate the context of the content script in the tab. The tab has to be reloaded to reactivate the content script. This is not an issue with a real user, but it does happen during debugging, so double check this is not the cause of issues while debugging.

Upvotes: 2

Related Questions