Before someone marks this post as a duplicate of another post, such as this: SecurityError: Blocked a frame with origin from accessing a cross-origin frame this post is different because it is about avoiding this error in the context of a Chrome web extension, which means there may be unique solutions.
I am porting a Firefox Quantum extension to Chrome. The extension injects an iFrame into the user's current web page. Right now, the extension works without problems in Firefox Quantum, you can find it here: https://addons.mozilla.org/en-US/firefox/addon/tl-dr-auto-summarizer/?src=search
The source of the iFrame is a HTML file called "inject.html" that is bundled within the extension.
Here is the shortened (to avoid making the post excessively long) code that injects the iFrame. This code is within a content script in the user's current tab:
var iFrame = document.createElement("iFrame");
iFrame.id = "contentFrame";
iFrame.classList.add("cleanslate");
iFrame.style.cssText = "width: 100% !important; height: 100% !important; border: none !important;";
iFrame.src = browser.extension.getURL("inject-content/inject.html");
document.body.appendChild(iFrame);
Here is the manifest.json
{
"manifest_version": 2,
"name": "TL;DR - Summarizer",
"version": "3.0",
"description": "Summarizes webpages",
"permissions": [
"activeTab",
"tabs",
"*://*.smmry.com/*"
],
"icons":
{
"48": "icons/border-48.png"
},
"browser_action":
{
"browser_style": true,
"default_popup": "popup/choose_length_page.html",
"default_icon":
{
"16": "icons/summarizer-icon-16.png",
"32": "icons/summarizer-icon-32.png"
}
},
"web_accessible_resources": [
"inject-content/inject.html",
"inject-content/cleanslate.css"
],
"content_security_policy": "script-src 'self' 'sha256-AeZmmPP/9ueCrodQPplotiV3Pw0YW4QqifjUL7NE248='; object-src 'self'"
}
After injecting the iFrame, I set the "click" listeners for the buttons within the iFrame, once the iFrame has loaded. I do this using the following code sample. However, while the following code works in Firefox Quantum, it throws an exception in Chrome.
iFrame.onload = () => {
//The error occurs on the following line.
var closeButton = iFrame.contentWindow.document.getElementById("close-btn");
closeButton.addEventListener("click", () => {
//Do Stuff
});
var copyButton = iFrame.contentWindow.document.getElementById("copy-btn");
copyButton.addEventListener("click", () => {
//Do stuff
});
}
I get the following exception:
Uncaught DOMException: Blocked a frame with origin "http://example.com" from accessing a cross-origin frame. at HTMLIFrameElement.iFrame.onload (file:///C:/Users/vroy1/Documents/Programming/web-extension-summarizer/src/inject-content/inject.js:58:56)
How can I avoid this error?
In case anyone is wondering, the reason I am able to use the Promise
API and the browser
namespace inside of a Chrome extension is because I am using a polyfill provided by Mozilla that allows me to use promises and the browser
namespace.
Here is the code for the popup that the extension displays when its toolbar icon is clicked:
//Enable the polyfill for the content script and execute it in the current tab
browser.tabs.executeScript({ file: "/polyfills/browser-polyfill.js" }).then(loadContentScript).catch((error) => logError(error));
function loadContentScript() {
browser.tabs.executeScript({ file: "/inject-content/inject.js" }).then(listenForClicks).catch((error) => logError(error));
}
function listenForClicks() {
document.addEventListener('click', e => {
if (!e.target.classList.contains('btn')) {
return;
} else {
browser.tabs.query({ active: true, currentWindow: true })
.then(tabs => {
browser.tabs.sendMessage(tabs[0].id, { summaryLength: e.target.id, targetURL: tabs[0].url });
});
}
});
}
function logError(error) {
console.log(error);
}
Lastly, here is the full code of the content script:
https://pastebin.com/Yrs68zAB