Search code examples
ajaxsdkfirefox-addonmozillafirefox-addon-sdk

How to detach a content script with mozilla sdk?


I'm writing a password manager, and my extension creates a listener on page ready, so after a few urls navigated I have a bunch of listeners. I want to respond to a user clicking a "submit" form button without having more than one listener active at a time, so I'd like to detach the content script.

Right now it listens for form submit, then checks the next page loaded for "incorrect password" or the like, then does some other stuff. Here's the code where I attach the listener:

tabs.on("ready", function(tab) {
    fillLoginAndPass(tab);
    listenForLoginSubmit(tab);
});

function listenForLoginSubmit(tab) {
    // attach submit listener 
    worker = tab.attach({
        contentScriptFile: [data.url("jquery-1.11.1.min.js"), data.url("listener-script.js")]
    });

    worker.port.on("submittedCredentials", function (formSubmitURL, enteredLogin, loginField, enteredPassword, passwordField) {
        tab.on("ready", function() {
            checkLogin(tab, formSubmitURL, enteredLogin, loginField, enteredPassword, passwordField);
        });
    });
}

I've tried using worker.destroy(), but it has no effect - the port.on() script still executes multiple times. Is there another way to do it? Thanks in advance.

Edit

To clarify, this is what my code looks like with worker.destroy():

function listenForLoginSubmit(tab) {
    // attach submit listener 
    worker = tab.attach({
        contentScriptFile: [data.url("jquery-1.11.1.min.js"), data.url("listener-script.js")]       
    });

    worker.on("detach", function() {
        console.log("Worker detached from "+tabs.activeTab.url);
    });

    worker.port.on("submittedCredentials", function (formSubmitURL, enteredLogin, loginField, enteredPassword, passwordField) {
        tab.on("ready", function() {
            checkLogin(tab, formSubmitURL, enteredLogin, loginField, enteredPassword, passwordField);
            worker.destroy();
        });
    });
}

function checkLogin(tab, formSubmitURL, enteredLogin, loginField, enteredPassword, passwordField) {
    console.log("Hello!");
    /* code */
}

And the difference in outputs is:

// without worker.destroy()
/* Log in to wikipedia.org */
console.log: passman: Hello!

/* Log out, return to login page */
/* Log in a second time */
console.log: passman: Hello!
console.log: passman: Hello!
console.log: passman: Worker detached from https://en.wikipedia.org/w/index.php?title=Special:Search&search=&go=Go

// with worker.destroy()
/* Log in to wikipedia.org */
console.log: passman: Hello!
console.log: passman: Worker detached from https://en.wikipedia.org/w/index.php?title=Special:Search&search=&go=Go

/* Log out, return to login page */
/* Log in a second time */
console.log: passman: Hello!
console.log: passman: Worker detached from https://en.wikipedia.org/w/index.php?title=Special:Search&search=&go=Go
console.log: passman: Hello!
console.log: passman: Worker detached from https://en.wikipedia.org/w/index.php?title=Special:Search&search=&go=Go

If I do it a third time, I get 3 "Hello!"s, and so on. Again, thanks for any help you can offer.

Edit 2 The bug report Zer0 links in the comments has the answer. Here it is:

let { off } = require("sdk/event/core");
off(worker.port);

Solution

  • It's past time this question got an accepted answer, and since no one else has written it I will. The bug report Zer0 links in the comments has the answer. Here it is:

    let { off } = require("sdk/event/core");
    off(worker.port);