1

Im making a really simple Chrome extension, what redirects pages what are on http protocol ,to https protocol, if exist. Im on debugging, and i found facebook, what has both http, and https.

The code is here:

function redirect() {    
    chrome.tabs.query({active: true}, function(tabArray) {  
        var currentURL = tabArray[0].url;               //http://facebook.com
        var httpsURL = generateSSL(currentURL);         //https://facebook.com
        if(httpsURL == currentURL){
            console.log(currentURL+" is already on HTTPS");
            chrome.browserAction.setIcon({path:"../images/padlock_green.png"});
        } else if(checkSSL(httpsURL)){                      
            chrome.tabs.update(tabArray[0].id, {url: httpsURL});
            chrome.browserAction.setIcon({path:"../images/padlock_green.png"});
            chrome.browserAction.setBadgeText({text:"SSL"});
            console.log("SSL found,"+currentURL+" redirected to"+httpsURL);
        } else {
            //donothing
            console.log(currentURL+" has no SSL");
            chrome.browserAction.setIcon({path:"../images/padlock_red.png"});
        }
    });
}

ajax call:

function checkSSL(url){
    $.support.ajax = true;
    $.ajax({
        url: url,
        type:'HEAD',
        error: function()
        {
            return false;
        },
        success: function()
        {
            return true;
        }
    });
}

The problem is, that i get in console the following error msg:

XMLHttpRequest cannot load https://www.facebook.com/. Origin chrome-extension://pgidanbjmliilmmohlphbagcapafjjpg is not allowed by Access-Control-Allow-Origin.

I dont have any ideas what could be the problem :(

Attila Kling
  • 1,717
  • 4
  • 18
  • 32
  • Seems like your extension is making an Ajax request... – Felix Kling Apr 16 '12 at 12:02
  • sry, i forget to copy ajax call, i updated my post :/ – Attila Kling Apr 16 '12 at 12:05
  • But that Ajax call is the problem... you are not allowed to do it, that's what the error message says. Besides, you cannot return a value from an Ajax callback, the whole setup won't work. You have to find an other way to test whether an HTTPS version is available. – Felix Kling Apr 16 '12 at 12:07
  • i see, then how to check whether an url is existing, or not, and return the result? – Attila Kling Apr 16 '12 at 12:09
  • Can we see your `manifest.json` file as well? – apsillers Apr 16 '12 at 15:55
  • sure: `{ "name": "Force SSL Connection", "version": "1.0", "description": "SSL", "browser_action": { "default_icon": "images/padlock.png", "default_title": "SSL" }, "background_page": "html/background.html", "permissions": [ "tabs", "http://*/*" ] }` – Attila Kling Apr 16 '12 at 20:41
  • If you're seriously interested in a Chrome application that does HTTP-to-HTTPS conversion, consider looking at [HTTPS Everywhere](https://www.eff.org/https-everywhere). Writing it yourself is always a good way to learn, but if you are serious about building a complete extension, you should look at that project (and help make it better, if you want!). – apsillers Apr 17 '12 at 21:50

2 Answers2

1

Your code has a couple of small issues:

  • Your manifest file only requests permissions for http://*/*, not https://*/*, so your request to an HTTPS site is failing. You need the permission to be *://*/*, so you can get all pages on all domains over all protocols, not just over HTTP.

  • A second issue is that you expect your $.ajax call to return a boolean, but that is not what happens. The $.ajax call has two callbacks that each return a boolean, but checkSSL terminates before the Ajax call completes, meaning that checkSSL always returns undefined.

What you want to do instead is provide checkSSL with a callback function as an argument:

function checkSSL(url, callback){
    $.ajax({
        url: url,
        type:'HEAD',
        error: function() { callback(false); },
        success: function() { callback(true); }
    });
}

Then, use that callback to run call the code after the call to checkSSL:

function redirect() {    
    chrome.tabs.query({active: true}, function(tabArray) {  
        var currentURL = tabArray[0].url;               //http://facebook.com
        var httpsURL = generateSSL(currentURL);         //https://facebook.com
        if(httpsURL == currentURL){
            console.log(currentURL+" is already on HTTPS");
            chrome.browserAction.setIcon({path:"../images/padlock_green.png"});
        } else {
            // call checkSSL and take action in an anonymous callback function!
            checkSSL(httpsURL, function(urlDoesExist) { 
                if(urlDoesExist) {                 
                    chrome.tabs.update(tabArray[0].id, {url: httpsURL});
                    chrome.browserAction.setIcon({path:"../images/padlock_green.png"});
                    chrome.browserAction.setBadgeText({text:"SSL"});
                    console.log("SSL found,"+currentURL+" redirected to"+httpsURL);
                } else {
                    //donothing
                    console.log(currentURL+" has no SSL");
                    chrome.browserAction.setIcon({path:"../images/padlock_red.png"});
                }
            });
        }
    });
}

Notice the changes to the code below the first else. We can't decide what to do until the Ajax call has resolved, so we have the Ajax success and error functions fire a callback with a boolean argument. That callback function then takes action based on the value of the boolean.

apsillers
  • 112,806
  • 17
  • 235
  • 239
0

If you package your extension, you are allowed to do cross domain requests, but not if you create it as a hosted application/extension, see:

Chrome extension Cross Domain Request

Community
  • 1
  • 1
Marius Kjeldahl
  • 6,830
  • 3
  • 33
  • 37