KevinHJ
KevinHJ

Reputation: 1104

Block script execution in Firefox extension?

Probably looking for an answer to an age-old question, but I would like to block script execution. In my use-case blocking the browser is acceptable.

Also, in my use-case I am trying to do this from a Firefox extension, which means my code is "Chrome code", running in the browser environment.

This can easily be done by using a modal window, then programmatically closing the window. So this demonstrates that there is a blocking mechanism that exists.

Is there any way to achieve modal blocking without actually creating or opening the modal window? Some way to tap into the blocking mechanism used for modal windows?

I've done a lot of searching on this subject, but to no avail.

Upvotes: 1

Views: 515

Answers (2)

Noitidart
Noitidart

Reputation: 37228

OPTION 1

There is enterModalState and leaveModalState in nsIDOMWindowUtils here: MDN :: nsIDOMWindowUtils Reference

However they don't seem to work for me. This topic might explain why: nsIDOMWindowUtils.isInModalState() not working they topic says isInModalState is marked [noscript] which I see, but enterModalState and leaveModalState are not marked [noscript] I have no idea why it's not working.

What does work for me though is suppressEventHandling:

var utils = Services.wm.getMostRecentWindow('navigator:browser').
            QueryInterface(Components.interfaces.nsIInterfaceRequestor).
            getInterface(Components.interfaces.nsIDOMWindowUtils);

utils.suppressEventHandling(true); //set arg to false to unsupress

OPTION 2

You can open a tiny window with the source window as the window you want to make modal and as dialog but open it off screen. Its dialog so it wont show a new window the OS tab bars. However hitting alt+f4 will close that win, but you can attach event listeners (or maybe use the utils.suppressEventHandling so keyboard doesnt work in it) to avoid the closing till you want it closed. Here's the code:

    var sDOMWin = Services.wm.getMostRecentWindow(null);
    var sa = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
    var wuri = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
    wuri.data = 'about:blank';
    sa.AppendElement(wuri);
    let features = "chrome,modal,width=1,height=1,left=-100";
    if (PrivateBrowsingUtils.permanentPrivateBrowsing || PrivateBrowsingUtils.isWindowPrivate(sDOMWin)) {
       features += ",private";
    } else {
       features += ",non-private";
    }
    var XULWindow = Services.ww.openWindow(sDOMWin, 'chrome://browser/content/browser.xul', null, features, sa);
/*
    XULWindow.addEventListener('load', function() {
      var DOMWindow = XULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
      DOMWindow.gBrowser.selectedTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
      DOMWindow.gBrowser.swapBrowsersAndCloseOther(DOMWindow.gBrowser.selectedTab, aTab);
      //DOMWindow.gBrowser.selectedTab = newTab;
    }, false);
*/

Upvotes: 0

KevinHJ
KevinHJ

Reputation: 1104

Using nsIProcess you can block the thread.

You can create an executable which has a sleep or usleep method or equivalent. Then run the process synchronously (nsIProcess.run) and set blocking argument to true.

Of course for portability you will need to create an executable appropriate for each platform you wish to support, and supply code for discrimination.

Basic code is something like the following. I have verified on 'nix (Mac OS X) this code to work, using a bash script with only the line sleep .03:

let testex = Components.classes["@mozilla.org/file/local;1"]
                    .createInstance(Components.interfaces.nsIFile);

testex.initWithPath("/Users/allasso/Desktop/pause.sh");

let process = Components.classes["@mozilla.org/process/util;1"]
                    .createInstance(Components.interfaces.nsIProcess);

process.init(testex);
let delay = 30;  // convert this to milliseconds in the executable
process.run(true,[delay],1);  // `run` method runs synchronously, first arg says to block thread

In an extension you probably would want to make your nsIFile file object more portable:

Components.utils.import("resource://gre/modules/FileUtils.jsm");
let testex = FileUtils.getFile("ProfD",["[email protected]","resources","pause.sh"]);

Of course keep in mind that Javascript is basically single-threaded, so unless you are blocking a thread spawned using Web Workers you will be freezing the entire UI during the sleep period (just like you would if you opened a modal window).

References:

https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIProcess

https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile

https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Getting_special_files

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/basic_usage

Upvotes: 1

Related Questions