Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access iframe URL from Chrome extension

I've got an extension that needs to load up a page with lots of redirects in its background page. Once that page gets to a known URL (https://website.com/index.php), the iframe should have its src set to about:blank.

The final page is quite large and has big images and everything that don't need to be loaded, so rather than attach to the iframe's onload event, I set the following function on a 100ms interval:

function update(){
    if(document.getElementsByTagName('iframe')[0].contentDocument.location.href == "https://website.com/index.php"){
        console.log("Done!");
        clearInterval(updateInterval);
        document.getElementsByTagName('iframe')[0].src = "about:blank";
    }
}

However, as soon as the iframe starts to load, update() throws this error:

Unsafe JavaScript attempt to access frame with URL https://website.com/index.php from frame with URL chrome-extension://hdmnoclbamhajcoblymcnloeoedkhfon/background.html. The frame requesting access has a protocol of 'chrome-extension', the frame being accessed has a protocol of 'https'. Protocols must match.

I tried catch()ing that error, but the message passed back to Javascript unsurprisingly doesn't include the URL. The page redirects multiple times, so it's important to know the exact URL. The src property of the iframe also doesn't update to reflect redirects.

like image 640
Dan Hlavenka Avatar asked Mar 26 '13 02:03

Dan Hlavenka


People also ask

Can we use iframe in Chrome extension?

If you have a web application already, and would like to build a chrome extension for it - using iframes is an amazing tool. You can just inject an iframe of that web app in any page instead of re-implementing the whole UI from ground up.

How do I find iframe URL?

Click View Frame Source. In the Chrome address bar it will display something like this: view-source:https://www.w3schools.com/ Everything after "view-source:" is the URL of the iframe.


1 Answers

After lots of Googling and nearly giving up, I came up with the following solution. It uses an injected content script to send a message back to the extension once the correct page has loaded.

manifest.json:

{
    ...
    "background": {
        "page": "background.html"
    }, "content_scripts": [
        {
            "matches": ["http://website.com/index.php"],
            "js": ["content.js"],
            "all_frames": true,
            "run_at": "document_start"
        }
    ],
    "permissions": [
        "*://*.website.com/*"
    ]
}

background.html:

<html>
    <head>
        <script type="text/javascript" src="background.js"></script>
    </head>
    <body>
        <iframe src="about:blank"></iframe>
    </body>
</html>

background.js:

var waiting = false;

function login(){ // Call this function to start
    var frame = document.getElementsByTagName('iframe')[0];
    frame.src = "https://website.com/login/";
    waiting = true;
}

function callback(){ // This gets called once the page loads
    console.log("Done!");
}

chrome.extension.onMessage.addListener(function(request, sender, sendResponse){
    if(request.loaded && waiting){
        // If you used a pattern, do extra checks here:
        // if(request.loaded == "https://website.com/index.php")
        document.getElementsByTagName('iframe')[0].src = "about:blank";
        waiting = false;
        callback();
    }
});

content.js:

chrome.extension.sendMessage({loaded: window.location.href});
like image 159
Dan Hlavenka Avatar answered Sep 27 '22 18:09

Dan Hlavenka