I'm looking for a way to display an isolated overlay on some websites using WebExtensions.
An iframe would seem like the way to go for this as it provides a whole separate scope for css, js and the DOM. And another neat thing is that the target website won't be able to read or change the content.
In Chrome extensions that seems to be possible without any problems, but with WebExtensions in Firefox, even though they share the same syntax, I get security warnings/errors and it doesn't work.
I've tried two different things:
Creating an iframe without an src attribute and inject that into the body of website. This method failed because I get CSP errors/warnings when I do
iframe.contentWindow.document.open()
.
Relevant content-script code:let html = ` <!DOCTYPE html> <html> <head></head> <body> <h1>TEST</h1> </body> </html> ` let iframe = document.createElement('iframe') document.body.appendChild(iframe) iframe.contentWindow.document.open() iframe.contentWindow.document.write(html) iframe.contentWindow.document.close()
The other thing I tried (which would make way more sense as it would disallow the website from accessing the content), was to put my iframe code into a file (
overlay.html
) in my WebExtension and make the iframe load it by setting it's src tobrowser.extension.getURL('overlay.html')
.
Relevant content-script code:let iframe = document.createElement('iframe') iframe.src = browser.extension.getURL('overlay.html') document.body.appendChild(iframe)
In the manifest I defined the overlay.html as
web_accessible_resources
for this:"web_accessible_resources": [ "overlay.html" ],
The thing about that is that the iframe simply doesn't load the overlay.html file. But it is definitely available, otherwise
location.href = browser.extension.getURL('overlay.html')
wouldn't work. It would have been extremely convenient if that would have worked, as I could have stored the whole overlay (html, css, js) as separate files in my extension. As if it would be a standalone website. And using the content-script I could have accessed it to add new data or whatever.
Edit:
At the moment I'm using the srcdoc
attribute of my iframe to set the source code it should contain (thanks to wOxxOm for that). So at least I have something that works now. But what I really dislike about this approach is that I can't interact with the iframe content from my content script. Interestingly though, I can interact with the parent page from within the iframe's js code, but again not with the content script. It's also really messy, inconvenient and hard to maintain to put all your html, css, js code into one string instead of multiple files like a normal website.
iframe.srcdoc
. As for style isolation you can use Shadow DOM instead of iframe. – Oratoryfile:///C:/
. I think it's related to the extension's own CSP. I'm still unfamiliar with the syntax, so can't offer a solution. Be cautious poking holes without fully understanding what else you might be inadvertently allowing. 2) I created then immediately appended iframe. Direct assignment does NOT work equally for all attributes, althoughiframe.src
did work for me. Try specifying ALL attributes withiframe.setAttribute( attribute, value );
Specifically, I thinkclass
is problematic. – Cerargyriteclass
attribute set on theiframe
may lead to the risk of class collision problems that the Shadow DOM technique attempts to minimize. This technique is new to me so I can't comment further without research. – Cerargyrite