Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overlaying the page contents from Google Chrome extension

I am writing a very simple Google Chrome extension, but have faced such a multitude of issues that it's a bit overwhelming for a project of such a miserable scale.

The extension is a very simple one: upon arrival on any page (say, google.com) the page contents is hidden and the user is faced with a question (s)he has to answer correctly... or be redirected to some other page that provides the correct answer. In other words, the user cannot access pages on the Internet unless (s)he answers the questions correctly.

To hide the page contents I decided to go for a simple overlay using the following approaches:

Approach #1

I tried appending to the current document's body a simple opaque div with position: fixed;, z-index: 2147483647; and width/height at 100%. That worked, but:

  • The page's CSS kept interfering with the elements inside of my div.
  • Flash content occasionally appeared on top of it (at least on Windows XP). Chasing embeds all over the page and setting wmode to "transparent" didn't help, offsetting to -10000px or setting display:none; simply alleviated but didn't solve the problem. See also this question.

Approach #2

I tried sandboxing the GUI in an iframe that is created and injected into the page to behave exactly as the div in the above approach. It perfectly solves the issues of the first approach, but:

  • Apparently there's no way to access the contents of the iframe because of cross-origin policy. And that access – I need it to assign handlers to the input field where the user is typing the answer, I need to remember who's stealing the focus from my answer input field to give it back once the question is answered, etc. etc. etc.
  • Using Message Passing didn't work for me and I'm not even sure if I should make it work because messaging makes the entire thing overly complex and prohibits me from using the application as a simple webpage (i.e. not as an extension). Why even bother?

So... where am I wrong with my approaches? Is there a third or a fourth one that I'm not aware of?

I appreciate but don't really need code as an answer. A hint or a push to the right direction would be just as good.

P.S. I suppose that at some point somebody will ask if I have code to share. I do, but there's a bunch of it. Which part specifically would you like to see?

like image 367
Oleg Avatar asked Feb 17 '23 16:02

Oleg


2 Answers

Approach #2

Concern #1

Apparently there's no way to access the contents of the iframe because of cross-origin policy. And that access – I need it to assign handlers to the input field where the user is typing the answer, I need to remember who's stealing the focus from my answer input field to give it back once the question is answered, etc. etc. etc

Yes you access contents of iframe(s) for matter all the code of a Web Page, no CSP etc.

Content script injecting an iframe.

I suggest this is best approach , you can inject script to dynamic generated iframes as shown here and fetch content

Sample Implementation

manifest.json

{
    "name": "Iframe",
    "description": "",
    "version": "1",
    "manifest_version": 2,
    "content_scripts": [
        {
            "matches": [
                "<all_urls>"
            ],
            "js": [
                "myscript.js"
            ],
            "run_at": "document_end"
        },
        {
            "matches": [
                "<all_urls>"
            ],
            "js": [
                "anotherscript.js"
            ],
            "all_frames": true
        }
    ],
    "permissions": [
        "<all_urls>"
    ]
}

myscript.js

var iframe = document.createElement("iframe");
iframe.setAttribute("src", "https://www.facebook.com/plugins/like.php?href=http://allofrgb.blogspot.in/");
iframe.setAttribute("style", "border:none; width:150px; height:30px");
iframe.setAttribute("scrolling", "no");
iframe.setAttribute("frameborder", "0");
document.body.appendChild(iframe);

anotherscript.js

iframes = document.getElementsByTagName("iframe");
for (iframe in iframes){
    console.log(iframes[iframe].src);
}
console.log("In another Script");

If you observe console logged messages you observe messages are logged twice (document log + iframe log + [any number of optional iframes in pages]*)

anotherscript.js which runs during document idle states does execute in dynamic generated iframe, how ever you can re-run content script through chrome.tabs.executeScript() any time.

Concern #2

Using Message Passing didn't work for me and I'm not even sure if I should make it work because messaging makes the entire thing overly complex and prohibits me from using the application as a simple webpage (i.e. not as an extension). Why even bother?

What is you want to achieve?

like image 159
Sudarshan Avatar answered Mar 08 '23 04:03

Sudarshan


Totally forgot about this question... In the end I went with approach 2 using message passing to communicate with the iframe and it works pretty fine. Here's a repo of the extension for those who are interested in reading the code: https://github.com/olegskl/invasive-kanji

like image 28
Oleg Avatar answered Mar 08 '23 06:03

Oleg