Search code examples
javascriptdomfirefox-addonfirefox-addon-webextensionsfirefox-developer-tools

JavaScript for Firefox Add-on/Extension: "failed to execute script: Error: Permission denied to access property "document" on cross-origin object"


I am looking forward to receive some help on this little but tedious problem of mine that seems I am not currently able to solve since a few weeks so far.

I am trying to develop a very easy/simple Extension/Add-on for the Mozilla Firefox browser.

My little project is to develop a simple extension-button that when clicked will allow the user to run an easy automated script on the current open webpage/tab. Basically, the script will try to extract some specific data from the page and present it in a new popup window created at the moment.

I am currently stuck and cannot achieve the desire result while getting the following error:

failed to execute script: Error: Permission denied to access property "document" on cross-origin object

P.S.: I am not using or working with any webpage that contains <iframe> tags.

The original script itself is a little bit elaborated but nothing complex. Trying to isolate the problem and the error I have tried to simplify the whole project in order to reproduce locally.

To summarize and recap:

  • I am trying to create a simple/easy extension/Add-on for the Mozilla Firefox web-browser (and later extend this to the Google Chrome browser also);
  • the scope of this extension is to be able to run only on a specific domain and set of pages.
  • once the user load that specific page, if desired, the user can click on the extension button and this will run the script.
  • the script will need to search and try to extract specific parts of the content of the current webpage and present this information on a new popup window created on the fly (here the user should need to know that needs to add permission for popup pages for this domain/website)
  • when the user is done with this summarized version of the page will be able to close it like a normal browser window.

How the folder/file structure of my project is currently designed:

/generic-folder/
    test-page.html
    /browser-extension/
        /icons/
            icon-48.png
            icon-96.png
        /scripts/
            script.js
        app.js
        manifest.json

Description and content of the project:

  • the file: test-page.html is a test webpage created for the purpose in order to test the behavior of the script/extension and to reproduce the behavior/error locally, the content of this file is:
<!DOCTYPE html>
<html>
    <head></head>
    <body style="color: white; background-color: black;">
        <h1>TEST NEW PAGE</h1>
        <p id="paragraph">
            This is the content of the paragraph that needs to be extracted!
        </p>
    </body>
</html>
  • the icons folder contain 2 icon files PNG format, 48 pixels and 96 pixels. (not relevant)
  • the scripts folder contain the main JavaScript script of the extension script.js, here the content:
var body = "<!DOCTYPE html>\n";
var font = "font-size: 1.25rem; font-family: Courier New, Monospace; font-style: normal; font-weight: normal;";
var id = "paragraph";

body += "<html><body style=\""+font+"\"><h1>TEST NEW PAGE</h1>\n";
body += "<p>\n";
body += document.getElementById(id).innerText;
body += "\n</p>\n";
body += "\n</body>\n</html>\n";

var newWin = window.open('','extractor','width=1024,height=750,resizable=yes,scrollbars=yes');
newWin.document.write(body);
newWin.focus();

console.log("Message: '/scripts/script.js' has been executed!");

Note: if you open in debugging-mode (SHIFT+CTRL+C) the webpage test-page.html and manually run the above script.js it should work as wanted and you should see the desire behavior of the project.

  • the file app.js contain the JavaScript for the extension:
browser.browserAction.onClicked.addListener(async (tab) => {
  try {
    let results = await browser.tabs.executeScript({
      file: "/scripts/script.js"
    });
  } catch (err) {
    console.error(`failed to execute script: ${err}`);
  }
});
{
    "manifest_version": 2,
    "name": "Page Extractor",
    "description": "Script for extracting specific data from a webpage.",
    "version": "1.0",

    "icons": {
         "48": "icons/icon-48.png",
         "96": "icons/icon-96.png"
    },

    "permissions": ["webRequest", "scripting", "activeTab", "tabs", "clipboardWrite"],

    "content_scripts": [{
      "matches": ["*://*/test-page.html*"],
      "js": ["/app.js"]
    }],

    "background":{
        "scripts":["/app.js"]
    },

    "browser_action": {
        "default_icon": {
             "48": "icons/icon-48.png",
             "96": "icons/icon-96.png"
        },
    "default_title": "Execute Page Extractor!"
    }
}

When testing the extension: (following the MDN instructions)
Firefox -> about:debugging -> load temporary extension -> etc...

I can see the the web-extension correctly loaded with the correct icon, but, after I open the test-page.html (or the desired webpage), and click on the extension button then nothing happens!

However, I can see in the test-page.html debugging/console that the script has been ran (due to some manual debugging message I've tried to place)... but no popup/new window is presented/created to the user.

Instead analyzing the "Inspection" debugging window of the extension I can see the following error message:

failed to execute script: Error: Permission denied to access property "document" on cross-origin object

I cannot find the correct work-around/solution and I hope that someone can help me out.

Thank you in advance!


Solution

  • Apparently I have found my answer the same day I have created this post and, also as the user wOxxOm suggested, this is a known Firefox bug [ https://bugzilla.mozilla.org/show_bug.cgi?id=1508687 ].

    At the moment I was able to isolate the problem (without avoiding a small "console error message") and make it work following the information found at this official page: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts

    (page, which reports:)

    In Firefox, part of the isolation between content scripts and page scripts is implemented using a feature called "Xray vision". When a script in a more-privileged scope accesses an object that's defined in a less-privileged scope it sees only the "native version" of the object. Any expando properties are invisible, and if any properties of the object have been redefined, it sees the original implementation, not the redefined version.

    Hence... Solution is:

    to change this:

    newWin.document.write(body);
    

    into this:

    newWin.wrappedJSObject.write(body);
    XPCNativeWrapper(newWin);