2

I'm implementing a Firefox plugin. In the plugin's toolbar, I capture the current page and redirect users to the UK Google when they try to go to the Netherlands Google instead. However, this code takes forever to complete. When I type "google.nl" or "google.com/nl", my browser shows the Netherlands page and takes at least 1 second before redirecting.

Is there any way to make the redirect faster? Ideally, I'd like the user to not see the Netherlands Google page at all.

function loadURL(url) {
    window._content.document.location = url;
    window.content.focus();
}

var redirected = false;

function onChange()
{

    var url = gBrowser.selectedBrowser.currentURI.spec;
    url = encodeURIComponent(url);

    if(url.indexOf("google.nl") !=-1 || url.indexOf("hl%3Dnl") !=-1){
        if (!redirected){
            redirected = true;
            loadURL("https://www.google.co.uk/");
            return;
        }
    }else{
        redirected = false;
    }
}

Note: onChange() is triggered by container.addEventListener('DOMSubtreeModified',onChange, false);

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Matt
  • 303
  • 1
  • 2
  • 16

1 Answers1

3

First observersation

Never use DOMSubtreeModified that's a MutationEvent which was supposed to have been removed. You should use MutationObserver

So in your case instead of container.addEventListener('DOMSubtreeModified, onChange, false); do this:

const gMutationConfig = {
    subtree: true,
    childList: true
};

var gMutationFunc = function(ms) {
    for (let m of ms) {
        console.log(m.type, m);
        //if (mutation.addedNodes && mutation.addedNodes.length > 0) { //this test if elements added
        onChange();
    }
};

var gMutationObserver = new this.DOMWindow.MutationObserver(container);

Second thing is

You probably should use nsIHTTPChannel for the redirect to be the fastest

const { Ci, Cu, Cc, Cr } = require('chrome'); //const {interfaces: Ci, utils: Cu, classes: Cc, results: Cr } = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/devtools/Console.jsm');

var observers = {
    'http-on-modify-request': {
        observe: function (aSubject, aTopic, aData) {
            console.info('http-on-modify-request: aSubject = ' + aSubject + ' | aTopic = ' + aTopic + ' | aData = ' + aData);
            var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
            var requestUrl = httpChannel.URI.spec
            if (requestUrl.indexOf('google.com') > -1) {
               //httpChannel.cancel(Cr.NS_BINDING_ABORTED); //this aborts the load
               httpChannel.redirectTo(Services.io.newURI('data:text,url_blocked', null, null)); //can redirect with this line, if dont want to redirect and just block, then uncomment this line and comment out line above (line 17)
            }
        },
        reg: function () {
            Services.obs.addObserver(observers['http-on-modify-request'], 'http-on-modify-request', false);
        },
        unreg: function () {
            Services.obs.removeObserver(observers['http-on-modify-request'], 'http-on-modify-request');
        }
    }
};

To start observing

To start start obseving all requests do this (for example on startup of your addon)

for (var o in observers) {
    observers[o].reg();
}

To stop observing

Its important to stop observring (make sure to run this at least on shutdown of addon, you dont want to leave the observer registered for memory reasons)

for (var o in observers) {
    observers[o].unreg();
}

Full working example of the observer service to block/redirect urls: https://github.com/Noitidart/PortableTester/tree/block-urls

Noitidart
  • 35,443
  • 37
  • 154
  • 323
  • Works overall! `redirectTo` wasn't working for me (maybe there was a bug in my code), so I just used `aSubject.cancel` and redirected to my website of choice. – Matt Aug 20 '14 at 12:39
  • Cool man, the `redirectTo` function is only avail from ff 22+ – Noitidart Aug 20 '14 at 14:42
  • 1
    in your github link when i open bootstrap file i cant find where to put the URL that i want to be redirected. lets say i want to block bbc.com and redirect to abc.com ... where do i put the "abc.com" ?? – Konstantinos Natsios Jun 21 '15 at 08:23
  • 1
    @KwnstantinosNatsios right now on line 18 it is redirecting all urls in that array from line 4 and 5 to `data;txt/html,data blocked` so you need to put a a super simple object thing there that figures out based on if abc.com then return whatever url you want to redir to. – Noitidart Jun 21 '15 at 08:35
  • @Noitidart im sorry i didnt got this, im totaly new to javascript api etc. do you want me to make a question of how to do it so you can answer it? thanks! – Konstantinos Natsios Jun 21 '15 at 08:47
  • 1
    @KwnstantinosNatsios no its too easy. here: https://github.com/Noitidart/PortableTester/tree/8dcffd8be8e0cd088d55555b3e502900a77e1140 – Noitidart Jun 21 '15 at 08:57
  • Ok i think i got it. but i have to put different URLs in `redir_obj` so if i have only google.com in `urls_block` and next in `redir_obj` if i have abc.com... whenever i try to join google.com it should redirect me to abc.com, right? – Konstantinos Natsios Jun 21 '15 at 09:02
  • 1
    @KwnstantinosNatsios with that code it will redirect you to a page saying blocked google. and when go to bbc it will say blocked bbc – Noitidart Jun 21 '15 at 09:14
  • and if i want to redirect me to a whole differen URL? – Konstantinos Natsios Jun 21 '15 at 09:19
  • @KwnstantinosNatsios Then add/change it in the key value pair here: https://github.com/Noitidart/PortableTester/blob/8dcffd8be8e0cd088d55555b3e502900a77e1140/bootstrap.js#L9 – Noitidart Jun 25 '15 at 06:07