Search code examples
google-chrome-extensiongoogle-chrome-devtoolscontent-script

How to send trigger function in injected_scripts in devtools


I have a working extension, but it the dev tool works once only, during initialization, which in manifest I have a content_script defined and that content_script injects a injected_script which relays a series of events

window.postMessage({ eventName: window.appName, ... [other details] })

and thru injected -> content -> background -> devtools, it gets to devtools.

But what if I want to re-run this injected script, say when I click a button on devtool panel, and what if I want to give some parameters for the data I expect to get back

e.g.

// devtools.js
sendToInjectedScript({params: ['appName', 'location']})

// injectedScript.js
// accepts params
window.postMessage({message: params.map((p) => window[p]})

how would I do that?


Solution

  • You can run code in the inspected window using chrome.devtools.inspectedWindow.eval or with chrome.tabs.executeScript. In your Dev Tools panel you can have a button that calls a function to execute a function call in the inspected window. I found a couple of (untested) methods for achieving this, but I'm not totally sure which is more appropriate.

    Method 1: Using chrome.devtools.inspectedWindow.eval

    Dev Tools Page:

    function sendToInjectedScript(params) {
        chrome.devtools.inspectedWindow.eval('sendWindowParamData(' + message.params + '); + ');
    }
    
    sendToInjectedScript({params: ['appName', 'location']});
    

    Injected Script:

    function sendWindowParamData(params) {
       window.postMessage({message: params.map((p) => window[p]});
    }
    

    Manifest:

    "permissions": [
      "tabs"
    ],
    

    Method 2: Using chrome.tabs.executeScript

    Dev Tools Page:

    // Create a connection to the background page
    var backgroundPageConnection = chrome.runtime.connect({
        name: "devtools-page"
    });
    
    backgroundPageConnection.onMessage.addListener(function (message) {
        // Handle responses from the background page, if any
    });
    
    function sendToInjectedScript(params) {
        // Relay the tab ID to the background page
        chrome.runtime.sendMessage({
            tabId: chrome.devtools.inspectedWindow.tabId,
            params: params
        });
    }
    
    sendToInjectedScript({params: ['appName', 'location']});
    

    Background Page:

    chrome.runtime.onConnect.addListener(function(devToolsConnection) {
        // assign the listener function to a variable so we can remove it later
        var devToolsListener = function(message, sender, sendResponse) {
            // Inject a content script into the identified tab        
            chrome.tabs.executeScript(message.tabId, {
                code: 'sendWindowParamData(' + message.params + ');'
            });
        }
        // add the listener
        devToolsConnection.onMessage.addListener(devToolsListener);
    
        devToolsConnection.onDisconnect.addListener(function() {
             devToolsConnection.onMessage.removeListener(devToolsListener);
        });
    }
    

    Injected Script:

    function sendWindowParamData(params) {
       window.postMessage({message: params.map((p) => window[p]});
    }
    

    Manifest:

    "permissions": [
      "tabs"
    ],
    

    I haven't played around with these yet, so this is just some guesswork from looking at the API.