0

Overview of the problem

I cannot access the DOM of a window that I open programmatically in my chrome extension. I believe this may be due to origin/cross-site scripting restrictions. I have tried to give it the maximal permissions I can, including "<all_urls>", "activeTab" and "tabs"

I also played around with "content_security_policy_" settings but from the documentation I was hoping rather than expecting that to help.

I have a simple extension that runs code when the button is clicked, I want to open a few different tabs (but from different domains) and then access the DOM of each. However, it only seems to work if I'm on a tab of a domain and then I open another tab of the same of domain. Then I can access, for example, window onload of the new tab. I have no luck when it is a different domain.

e.g. if I press the button with activeTab "foo.com" then if it window.opens a new tab "foo.com/something" then I can access the document of that opened tab. But if it was "bar.com" then I wouldn't be able to access "foo.com/something"'s DOM

p.s. please note that executeScripts is used instead of manifest content scripts because it is necessary for my code to work. I must inject at least some of the files there this way, otherwise my code will not work (for reasons that are not completely apparent in the example)

my Question

What's way(s) can I get around this - I mean be able to access the DOM of any tab that I open, regardless of what site is in the active tab when the extension button is pressed in the toolbar?

Should I inject content scripts into a a tab that has been opened with window.open and somehow pass its document to Code.js? If so, how could I go about doing that? Can I somehow pass the document to the background.js? and somehow pass it to the injected Code.js?

If this will work (get around security restrictions) then can these content scripts be injected programatically (I don't know exactly what sites they will be until runtime, so I can't really specify them in the manifest)

or is there some way I can just relax the security restrictions and be able to directly access window.open's returned window's document? (which as I mentioned above currently only works on same-domain sites)

background.js

// this is the background code...

// listen for our browerAction to be clicked
chrome.browserAction.onClicked.addListener(function (tab) {

    executeScripts(null, [ // jquery can be inserted here: https://stackoverflow.com/questions/21317476/how-to-use-jquery-in-chrome-extension
        { file: "lib/jquery-3.2.1.js" },
        { file: "lib/kotlin.js" },
        { file: "Code.js" } // don't include it in manifest "content_scripts" because it gives an error about kotlin.js not present that way
    ])
});

/*
 * https://stackoverflow.com/questions/21535233/injecting-multiple-scripts-through-executescript-in-google-chrome
 */
function executeScripts(tabId, injectDetailsArray)
{
    function createCallback(tabId, injectDetails, innerCallback) {
        return function () {
            chrome.tabs.executeScript(tabId, injectDetails, innerCallback);
        };
    }

    var callback = null;

    for (var i = injectDetailsArray.length - 1; i >= 0; --i)
        callback = createCallback(tabId, injectDetailsArray[i], callback);

    if (callback !== null)
        callback();   // execute outermost function
}

code flow

  1. background.js
  2. Code.jscalls a function that starts with var w = window.open(url)
  3. then w.addEventListener("load", ...), which is the problem. It only fires if the url belongs to the same domain as the active tab. (onLoad can't be used any-which-way, it never fires that's why I use addEventListener)

notes

  • I have "manifest_version": 2
  • I need to inject this way rather than include content scripts in the manifest (I guess I could put the jquery library in the manifest but the others I can't and I prefer to keep all injections together in the "code")
ycomp
  • 8,316
  • 19
  • 57
  • 95
  • `Should I inject content scripts into a a tab that has been opened with window.open` - yes. This the only method for extensions to be able to access web page DOM as you can see in the documentation (IIRC someone already commented on your previous question). BTW it's better to open new tabs with chrome.tabs.create from the background page script, otherwise the browser might block these tabs for being js popups. – wOxxOm Jun 26 '17 at 08:07
  • @wOxxOm thanks now I have a better idea what to do, so injecting "pass-back the document" content scripts programmatically is fine for this to work? they don't have to be in the manifest? – ycomp Jun 26 '17 at 08:12
  • 1
    Instead of window.open I would send a message to background script with an URL to open. The background script would use chrome.tabs.create, then chrome.tabs.executeScript to run a content script that extracts some info, for example. P.S. Scripts injected by executeScript don't have to be declared anywhere. – wOxxOm Jun 26 '17 at 08:16
  • Yes, as wOxxOm has suggested, you are doing this the wrong way, and asking the wrong question. You are thinking about this as if it is a page script, not as you should be for writing an extension. Of course you can't access tabs opened with `window.open()` from your content script without regard to cross-domain issues. Content scripts have similar content security restrictions as page scripts. That's why you have to inject separate content scripts into tabs/frames when you would not normally be able to access them from a page script that was doing the same thing. – Makyen Jun 26 '17 at 18:12
  • I think I understand now, a master/controlling script triggered by a button is not really feasible, except to initiate by opening the required tabs... instead I should do the processing logic within each opened tab. I kinda liked the idea of seeing all the log statements on the initial tab, which is why I was trying to do it that way. – ycomp Jun 26 '17 at 18:22

0 Answers0