Converting a legacy extension to a bootstrapped extension

Talk about add-ons and extension development.
Post Reply
mozray
Posts: 76
Joined: March 10th, 2017, 3:48 pm

Converting a legacy extension to a bootstrapped extension

Post by mozray »

I've been running Firefox Unbranded so I can still run some legacy extensions.

However, with each release, Firefox is removing some APIs that are breaking some of the legacy extensions that I still use.

In Firefox 60, Auto Focus URL Bar no longer works:
https://addons.mozilla.org/en-US/firefo ... s-url-bar/

If you view the source for that addon, it's very simplistic, so I'm hoping if it is possible to port this over somehow to a bootstrapped addon. It's not possible to port this to a WebExtension due to a lack of APIs.

Can any XUL gurus help me out? I'm familiar with other languages, but XUL escapes me.
mozray
Posts: 76
Joined: March 10th, 2017, 3:48 pm

Re: Converting a legacy extension to a bootstrapped extensio

Post by mozray »

I'm dumb. The Auto Focus URL Bar addon is already a bootstrapped addon. Guess there's nothing I can do here to keep support for this other than go back to Firefox 59.
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Converting a legacy extension to a bootstrapped extensio

Post by morat »

Are all bootstrapped extensions dead in Firefox 60?

I got the bootstrap.js code working in scratchpad browser environment in Firefox 60.

Code: Select all

(function() {

  if (location != "chrome://browser/content/browser.xul") return;

  const {classes: Cc, interfaces: Ci, utils: Cu} = Components;

  Cu.import("resource://gre/modules/Services.jsm");

  var AutoFocusUrlbar = {
    cs: Services.console, // nsIConsoleService
    ww: Services.ww,      // nsIWindowWatcher
    wm: Services.wm,      // nsIWindowMediator
    ps: Services.prefs,

    get doc() {
      return this.wm.getMostRecentWindow("navigator:browser").document;
    },

    get eres() {
      return this.ps.getCharPref('extensions.AutoFocusUrlbar.excludeChar');
    },

    handleEvent: function(e) {
      var document = this.doc;
      var elm = document.activeElement;
      while (1) {
        if (elm == null) return;
        if (elm.localName == "browser" || elm.localName == "iframe" ||
          elm.localName == "frame") {
          elm = elm.contentDocument.activeElement;
          continue;
        }
        break;
      }
      if (elm.ownerDocument.designMode == 'on' ||
        elm.localName == "input" || elm.localName == "textarea" ||
        elm.localName == "select" ||
        elm.isContentEditable) return;
      var mod = e.ctrlKey || e.metaKey || e.altKey;
      if (mod) return;
      var c = String.fromCharCode(e.charCode);
      var excludePattern;
      try {
        var excludeRegExpString = this.eres;
        excludePattern = new RegExp(excludeRegExpString);
      } catch (err) {
        excludePattern = /[^a-zA-Z]/;
      }
      if (excludePattern.test(c)) return;
      var urlbar = document.getElementById("urlbar");
      if (!urlbar) return;
      e.preventDefault();
      urlbar.focus();
      try {
        urlbar.value = '';
        var evt = document.createEvent("KeyboardEvent");
        evt.initKeyEvent('keypress', false, true, null,
          false, false, false, false, 0, e.charCode);
        var input = urlbar.inputField;
        input.dispatchEvent(evt);
      } catch (err) {
        urlbar.value = c;
      }
    },

    aListener: {
      onOpenWindow: function(aWindow) {
        var win = aWindow.docShell.QueryInterface(Ci
          .nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
        win.addEventListener("load", function() {
          win.removeEventListener("load", arguments.callee, true);
          if (win.document.documentElement.getAttribute("windowtype") !=
            "navigator:browser") return;
          win.addEventListener("keypress", AutoFocusUrlbar, false);
        }, true);
      },
      onCloseWindow: function(aWindow) {},
      onWindowTitleChange: function(aWindow, aTitle) {},
    },

    startup: function() {
      this.wm.addListener(this.aListener);
      var cw = this.wm.getEnumerator("navigator:browser");
      while (cw.hasMoreElements()) {
        var win = cw.getNext().QueryInterface(Ci.nsIDOMWindow);
        win.addEventListener("keypress", this, false);
      }
    },
    shutdown: function() {
      this.wm.removeListener(this.aListener);
      var cw = this.wm.getEnumerator("navigator:browser");
      while (cw.hasMoreElements()) {
        var win = cw.getNext().QueryInterface(Ci.nsIDOMWindow);
        win.removeEventListener("keypress", this, false);
      }
    }
  }

  function startup(data, reason) {
    var cs = Services.console;
    AutoFocusUrlbar.startup();
  }
  startup();

  function shutdown(data, reason) {
    AutoFocusUrlbar.shutdown();
  }

  function install(data, reason) {}

  function uninstall(data, reason) {}

})();
pintassilgo
Posts: 200
Joined: August 30th, 2013, 3:50 pm

Re: Converting a legacy extension to a bootstrapped extensio

Post by pintassilgo »

Bootstrapped will be removed too:
https://bugzilla.mozilla.org/show_bug.cgi?id=1449052

I'm relying on AutoConfig, the only way I know to run unrestricted JS that doesn't have planned removal (at least for unbranbed/DevEd/Nightly: https://bugzilla.mozilla.org/show_bug.cgi?id=1455601#c8).
mozray
Posts: 76
Joined: March 10th, 2017, 3:48 pm

Re: Converting a legacy extension to a bootstrapped extensio

Post by mozray »

@morat - How do I run your code in Scratchpad?

I copied the code into Scratchpad and under Environment, I selected Browser. Then I hit Run, but that didn't seem to do anything. When Auto Focus URL Bar is active, you can start typing anywhere on the page and the typed text will be displayed in the URL bar instead of focusing the URL bar and then typing the text.

Is there an alternative to running this in Scratchpad?
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Converting a legacy extension to a bootstrapped extensio

Post by morat »

Here are the scratchpad instructions:

* open about:config
* set devtools.chrome.enabled to true
* tools > web developer > scratchpad
* environment > browser
* edit > paste (i.e. copy and paste code above)
* execute > run

Test page
http://www.mozillazine.org/

If the code fails, are you using the multiprocess windows feature?

You can see if the multiprocess windows feature is disabled in the about:support page.

* open about:config
* set browser.tabs.remote.autostart preference to false
* restart
* open about:support

P.S.

Someone got the userChrome.js file working with only the userChrome.css file. (autoconfig alternative)

Firefox Quantum compatible userChrome.js
http://github.com/Sporif/firefox-quantum-userchromejs

Restart Button
http://gist.github.com/Sporif/ad6e917d8 ... 80d3c8918c

Toggle Page Style Button
http://forums.mozillazine.org/viewtopic ... #p14795810
mozray
Posts: 76
Joined: March 10th, 2017, 3:48 pm

Re: Converting a legacy extension to a bootstrapped extensio

Post by mozray »

morat wrote:If the code fails, are you using the multiprocess windows feature?
Ahh, that was the problem! I do have e10s enabled. After disabling, the script works.

Bonus is memory usage is a little smaller as well! :)

About userChrome.js, does that rely on having e10s disabled? If not, I might give that a try as well.
Update - It's the userscript that requires e10s. I'm guessing Firefox deprecated some APIs that broke this feature in e10s.

Thanks morat!
Post Reply