For the life of me, I cannot get my Chrome extension to display an iframe with a remote URL.
I see the following message in the console -
Refused to frame 'https://www.example.com/' because it violates the following Content Security Policy directive: "child-src 'self'". Note that 'frame-src' was not explicitly set, so 'child-src' is used as a fallback.
I found a solution on here (Injecting iframe into page with restrictive Content Security Policy), which requires injecting a local iframe which then comatins another iframe that references the remote url. This is supposed to bypass the sontent security policy. But for some reason, it does not seem to work in my case. Am I missing something or has the chrome security policy changed?
Below are portions of my extension that pertain to this issue. Note - this code is not the prettiest as I've been hacking around trying to get this to work.
The way this works right now is background.js sends a message to inject.js. inject.js inserts the first iframe, referencing the local file infobar.html. This page is our main user interface, we want the remote html page displayed in an iframe as part of this page. Then infobar.js inserts an iframe referencing the local file frame.html. Finally, frame.html has an iframe hard coded to our remote url.
Based on the previous answer, only the first iframe should have been subject to the content security policy. However, that doesn't seem to be the case here, as the one referencing example.com is actually 3 iframes deep.
manifest.json
{
...
"content_security_policy": "script-src 'self'; object-src 'self'; frame-src https://www.example.com; child-src https://www.example.com",
"background": {
"scripts": [
"js/jquery/jquery.min.js",
"src/bg/background.min.js"
],
"persistent": true
},
...
"content_scripts": [
{
...
"css": [
...
"src/inject/inject.min.css"
],
"js": [
...
"src/inject/inject.min.js"
]
}
],
"externally_connectable": {
"matches": [
"*://localhost/*",
"*://*.example.com/*
]
},
"web_accessible_resources": [
"src/inject/inject.html",
"src/inject/infobar.html",
"src/inject/infobar.min.js",
"src/inject/frame.html"
],
"sandbox": {
"pages": [
"src/inject/infobar.html",
"src/inject/frame.html"
]
}
}
inject.js
var iframe = document.createElement("iframe");
iframe.scrolling = "no";
iframe.style.cssText = "display:none;";
...
$(iframe).load(function () {
var message = {
command: "render-frame",
context: data,
frameUrl: chrome.runtime.getURL("src/inject/frame.html")
};
iframe.contentWindow.postMessage(message, '*');
iframe.style.cssText = "border: 0px; overflow: visible; padding: 0px; right: auto; width: 100%; height: " + toolbarHeight + "px; top: 0px; left: 0px; z-index: 2147483647; box-shadow: rgba(0, 0, 0, 0.498039) 0px 3px 10px; position: fixed; display: none;";
});
...
iframe.src = chrome.runtime.getURL("src/inject/infobar.html");
...
document.documentElement.appendChild(iframe);
infobar.html
Simple HTML page. Nothing pertinent in there. References infobar.js.
infobar.js
window.addEventListener("message", function (event) {
var command = event.data.command;
switch (command) {
case "render-frame":
var frame = document.createElement("iframe");
frame.scrolling = "no";
frame.src = event.data.frameUrl;
document.getElementById("content").appendChild(frame);
...
break;
}
});
frame.html
<html>
<head>
<style>
html, body, iframe, h2 {
margin: 0;
border: 0;
padding: 0;
display: block;
width: 100vw;
height: 100vh;
background: white;
color: black;
}
</style>
</head>
<body>
<iframe src="https://www.example.com/page.html"></iframe>
</body>
</html>
No, the content scripts will NOT execute in the iframes loaded dynamically via JavaScript in the page.
iFrame is not working in Chrome but works in Firefox Google Chrome has a different set of rules when it comes to iFrame and it often blocks the content although it works fine on other browsers. You should also try clicking the shield in the URL title bar because that would also help you see the content.
We can detect if an element is inside an iframe by inspecting the element with the Chrome Developer Tools. An easier way is to perform a Right Click near the element in your browser and see if View Frame Source option is present in the context dropdown.
The proper way is to use the chrome.webRequest
API in your background script and intercept HTTP responses.
You can then override response headers to modify Content-Security-Policy header. You can also modify X-Frame-Options
header (if required).
Documentation: chrome.webRequest
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With