MozillaZine


Need Help Locating a JavaScript Code Module

Talk about add-ons and extension development.
AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 17th, 2020, 8:29 am

Greetings!

Here's the scoop: I'm trying to call "browser.management" in an autoconfig script, and can't identify the correct Code Module to bring into context. "ReferenceError: browser is not defined" at the Browser Console is getting quite tiresome...

The listing of potential candidates (per https://developer.mozilla.org/en-US/doc ... de_modules ) includes:

AddonManager.jsm
AddonRepository.jsm
Assert.jsm
BookmarkHTMLUtils.jsm
ctypes.jsm
CustomizableUI.jsm
DeferredTask.jsm
Dict.jsm
DownloadLastDir.jsm
Downloads.jsm
FileUtils.jsm
Geometry.jsm
HTTP.jsm
JNI.jsm
ISO8601DateUtils.jsm
Log.jsm (formerly log4moz)
NetUtil.jsm
openLocationLastURL.jsm
OSFile.jsm
PerfMeasurement.jsm
PluralForm.jsm
PopupNotifications.jsm
Promise.jsm
PromiseWorker.jsm
Services.jsm
source-editor.jsm
Sqlite.jsm
Task.jsm
Timer.jsm
Webapps.jsm
WebRequest.jsm
XPCOMUtils.jsm

In light of the foregoing, which of these many candidates might allow me to successfully scope "browser" in my script?

And, for the record, is there some place to look which has a complete listing of the contents of these modules (and "@mozilla.org/..." of "Components.classes" fame)???

Thanks! :)

morat
 
Posts: 4855
Joined: February 3rd, 2009, 6:29 pm

Post Posted July 17th, 2020, 11:08 am

You need to use legacy code, not WebExtension code.

WebExtension browser.management
http://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/management

Reference
http://searchfox.org/mozilla-release/so ... ement.json
http://searchfox.org/mozilla-release/so ... agement.js

The window.AddonManager object is already available in the browser.xhtml window. (no need to import)

Similar thread...

Accessing WebExtensions world from chrome
http://forums.mozillazine.org/viewtopic.php?f=19&t=3058430
Last edited by morat on July 17th, 2020, 12:42 pm, edited 1 time in total.

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 17th, 2020, 11:45 am

morat to the rescue, again ;)

Thanks for unraveling a bit more of this puzzle here...

That said, what might the correct syntax look like for a successful import?

This:
Code: Select all
Components.utils.import("resource://gre/modules/management.jsm");

& this:
Code: Select all
Components.classes["@mozilla.org/management;1"].getService(Components.interfaces.nsISomeBranch);

aren't going to work.:(

Can't help but wish there was a well-cataloged online repository for this kind of info!

morat
 
Posts: 4855
Joined: February 3rd, 2009, 6:29 pm

Post Posted July 17th, 2020, 2:24 pm

If you want to use the browser.tabs.create function in a script, then you need to examine the create function in the source to see how it works, then produce a legacy equivalent.

Code: Select all
// WebExtension code

(function () {
  browser.tabs.create({
    "url": "http://www.mozillazine.org/",
  });
})();

Code: Select all
// legacy code

(function () {
  gBrowser.addTab("http://www.mozillazine.org/", {
    triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
  });
})();

WebExtension browser.tabs
http://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/tabs

Reference
http://searchfox.org/mozilla-release/so ... /tabs.json
http://searchfox.org/mozilla-release/so ... xt-tabs.js
http://searchfox.org/mozilla-release/so ... xt-tabs.js

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 17th, 2020, 4:53 pm

Thanks so much, morat, but this is what I want to import into my autoconfig script scheme:

https://developer.mozilla.org/en-US/doc ... management

I want to explore/use the functions which the "management" API provides:
With the management API you can:
    *get information about installed add-ons
    *enable/disable add-ons
    *uninstall add-ons
    *find out which permission warnings are given for particular add-ons or manifests
    *get notifications of add-ons being installed, uninstalled, enabled, or disabled.

And this way of doing the "import" into my autoconfig script,
Code: Select all
Components.utils.import("resource://gre/modules/management.jsm");
...doesn't work (of course); and I can't seem to be able to figure the situation out by rummaging through everything in omni.ja :(

Just need to know what the formatting/syntax would look like to bring this to life :)

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 18th, 2020, 9:24 am

morat,

Looking over this thread again, it seems as though I missed some of what you were getting across. Overtired, I guess...

If I now understand the gist of this all correctly, it appears that a generic import for overall "management" functionality into an autoconfig script is not really possible. And, parsing the "management.json" and "ext-management.js" code into intelligible chunks per function is well beyond the pale for my level of mastery at this stage :)

I'll rummage about and see if there's a more "accessible" way of achieving my purposes; and get back if another question arises ;)

Have a great weekend --

morat
 
Posts: 4855
Joined: February 3rd, 2009, 6:29 pm

Post Posted July 18th, 2020, 9:58 am

You need to know how to do asynchronous programming to use the AddonManager object.

These code snippets work in the browser console.

Instructions:

* open about:config page
* set devtools.chrome.enabled preference to true
* open browser console i.e. tools > web developer > browser console
* copy and paste code into browser console command line
* press enter to run

Code: Select all
(function () {
  function resolveAfter2Seconds() {
    return new Promise(function (resolve) {
      setTimeout(function () { resolve("resolved"); }, 2000);
    });
  }
  async function example() {
    console.log("calling");
    var result = await resolveAfter2Seconds();
    console.log(result);
  }
  example();
})();

Code: Select all
(function () {
  async function test() {
    var addons = await AddonManager.getAddonsByTypes(["extension"]);
    addons.forEach(function (addon) {
      if (addon.hidden == false && addon.isSystem == false) {
        console.log("Name: " + addon.name + ", Id: " + addon.id + ", Disabled: " + addon.userDisabled);
        console.log(addon);
      }
    });
  }
  test();
})();

Async function
http://developer.mozilla.org/docs/Web/J ... c_function

AddonManager
http://developer.mozilla.org/docs/Mozil ... donManager
http://developer.mozilla.org/docs/Mozil ... ager/Addon

You can use the addon.userDisabled property to disable addons.

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 18th, 2020, 12:36 pm

Thank you, morat, once again for your generous assistance. I guess I'll wind up getting a knack for this after all :)

Duties call me away for a bit now, but I will dig into this with purpose soon...

Until next time,
Cheers!

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 20th, 2020, 9:55 am

Hi there, morat. Back again after digging in to the syntax for a bit :)

In that venture, I wanted to start by running and experimenting with your code samples.

So, I took this first example from your last post and just ran it:

Code: Select all
(function () {
  function resolveAfter2Seconds() {
    return new Promise(function (resolve) {
      setTimeout(function () { resolve("resolved"); }, 2000);
    });
  }
  async function example() {
    console.log("calling");
    var result = await resolveAfter2Seconds();
    console.log(result);
  }
  example();
})();


Looks like it did what it was supposed to, with a few errors. Here's what the console returned:

IndexedDB UnknownErr: ActorsParent.cpp:4588
IndexedDB UnknownErr: ActorsParent.cpp:13188
uncaught exception: Error in asyncStorage.setItem():
calling debugger eval code:8:13
undefined
resolved debugger eval code:10:13


Upon running your next example,

Code: Select all
(function () {
  async function test() {
    var addons = await AddonManager.getAddonsByTypes(["extension"]);
    addons.forEach(function (addon) {
      if (addon.hidden == false && addon.isSystem == false) {
        console.log("Name: " + addon.name + ", Id: " + addon.id + ", Disabled: " + addon.userDisabled);
        console.log(addon);
      }
    });
  }
  test();
})();


The console returned:

IndexedDB UnknownErr: ActorsParent.cpp:4588
IndexedDB UnknownErr: ActorsParent.cpp:13188
uncaught exception: Error in asyncStorage.setItem():
undefined
Name: {extension 1}, Id: {id 1}, Disabled: true debugger eval code:6:17
Object { }
debugger eval code:7:17
Name: {extension 2}, Id: {id 2}, Disabled: false debugger eval code:6:17
Object { }
debugger eval code:7:17
Name: {extension 3}, Id: {id 3}, Disabled: false debugger eval code:6:17
Object { }
debugger eval code:7:17
Name: {extension 4}, Id: {id 4}, Disabled: false debugger eval code:6:17
Object { }
debugger eval code:7:17


Similar errors, but ran OK!

Since you mentioned the the addon.userDisabled property, I thought I'd give this a quick run to do something practical. Here's what I came up with:

Code: Select all
(function () {
  async function test() {
    var addons = await AddonManager.getAddonsByTypes(["extension"]);
    addons.forEach(function (addon) {
      if (addon.hidden == false && addon.isSystem == false) {
   addon.userDisabled = true;
        console.log("Name: " + addon.name + ", Id: " + addon.id + ", Disabled: " + addon.userDisabled);
        console.log(addon);
      }
    });
  }
  test();
})();


It's just your previous (working) example with a sandwiched "userDisabled" call ;)

No dice with "userDisabled". The console burped back:

IndexedDB UnknownErr: ActorsParent.cpp:4588
IndexedDB UnknownErr: ActorsParent.cpp:13188
IndexedDB UnknownErr: ActorsParent.cpp:4588
uncaught exception: Error in asyncStorage.setItem():
undefined
Name: {extension 1}, Id: {id 1}, Disabled: false debugger eval code:7:17
Object { }
debugger eval code:8:17
Name: {extension 2}, Id: {id 2}, Disabled: false debugger eval code:7:17
Object { }
debugger eval code:8:17
Name: {extension 3}, Id: {id 3}, Disabled: false debugger eval code:7:17
Object { }
debugger eval code:8:17
Name: {extension 4}, Id: {id 4}, Disabled: false debugger eval code:7:17
Object { }


Not to be dissuaded from another go, I scratched my head a couple of times, dug around, and came up with this variant -- not expecting too much:

Code: Select all
(function () {
  async function test() {
    let addons = AddonManager.getAddonsByTypes();
    addons.forEach((addon) => { AddonManager.addon.userDisabled(addon.id, true); });
  }
  test();
})();


And I got what I expected! Here's the console's eulogy:

IndexedDB UnknownErr: ActorsParent.cpp:4588
IndexedDB UnknownErr: ActorsParent.cpp:13188
undefined
uncaught exception: Error in asyncStorage.setItem():
TypeError: addons.forEach is not a function
debugger eval code:4:12


Seeing how that wasn't bearing the fruit generally hoped for, I decided to look about and find pre-fabbed operational code with "userDisabled" functionality here-and-there.

This looked nifty:

Code: Select all
Cu.import('resource://gre/modules/AddonManager.jsm');
AddonManager.getAddonByID('{extension id 4}', function(addon) {
  if (addon.userDisabled) {
       //enable it
       addon.userDisabled = false;
  } else {
       //disable it
       addon.userDisabled = true;
  }
});


The console disgreed:

IndexedDB UnknownErr: ActorsParent.cpp:4588
IndexedDB UnknownErr: ActorsParent.cpp:13188
Promise { <state>: "pending" }

uncaught exception: Error in asyncStorage.setItem():


( source: https://stackoverflow.com/questions/266 ... fox-addons )

One more try, this one from MDN directly:

Code: Select all
Components.utils.import("resource://gre/modules/AddonManager.jsm");

let addonIDs = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_DISABLED);
if (addonIDs.length > 0) {
  // addonIDs is now an array of the add-on IDs that have been disabled
alert("Note: " + addonIDs.length + " add-ons have been disabled.");
}


Console:

IndexedDB UnknownErr: ActorsParent.cpp:4588
IndexedDB UnknownErr: ActorsParent.cpp:13188
IndexedDB UnknownErr: ActorsParent.cpp:4588
NonSyntacticVariablesObject { gStrictCompatibility: false, gFinalShutdownBarrier: {…}, gCheckCompatibility: true, EXPORTED_SYMBOLS: (3) […], formatter: {…}, gUpdateEnabled: false, gBeforeShutdownBarrier: {…}, PREF_EM_CHECK_COMPATIBILITY: "extensions.checkCompatibility.68.10", gStartupComplete: true, AddonManagerInternal: {…}, … }

uncaught exception: Error in asyncStorage.setItem():


( source: https://developer.mozilla.org/en-US/doc ... on_Manager )

Now I'm totally confused: It seems as though anything which runs, throws numerous errors; and, that which should certainly run (public code from MDN and stackoverflow), does nothing but tank completely out...

:?: :?:

Thanks again --

EDIT: Code transcription error...

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 20th, 2020, 1:27 pm

One more from the mother wit, just for luck:
Code: Select all
(function () {
    var addons = AddonManager.getAllAddons();
    addons.forEach(function () { addon.userDisabled(true); } );
})();

Output:
IndexedDB UnknownErr: ActorsParent.cpp:4588
IndexedDB UnknownErr: ActorsParent.cpp:13188
TypeError: addons.forEach is not a function
debugger eval code:3:12
uncaught exception: Error in asyncStorage.setItem():


???

Edit: Syntax...

morat
 
Posts: 4855
Joined: February 3rd, 2009, 6:29 pm

Post Posted July 20th, 2020, 7:16 pm

I'm not seeing those errors. The problem may be a corrupted profile.

IndexedDB UnknownErr: ActorsParent.cpp
http://bugzilla.mozilla.org/show_bug.cgi?id=1362878
http://bugzilla.mozilla.org/show_bug.cgi?id=1362878#c18

The getAllAddons is an asynchronous method that returns a Promise object.

Code: Select all
(async function () {
  var addons = await AddonManager.getAllAddons();
  addons.forEach(function (addon) {
    console.log(addon.id, addon.type, addon.hidden, addon.isSystem);
  });
})();

Code: Select all
(function () {
  AddonManager.getAllAddons().then(function (addons) {
    addons.forEach(function (addon) {
      console.log(addon.id, addon.type, addon.hidden, addon.isSystem);
    });
  });
})();

Promise
http://developer.mozilla.org/docs/Web/J ... ts/Promise

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 21st, 2020, 8:37 am

Thanks, morat, for coming back...

Ran everything on another identity, and some of the issues seemed to clear.

However, the console returns,
NS_NOINTERFACE: Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsISupports.QueryInterface] stack-trace-collector.js:84
Promise { <state>: "pending" }
-- or --
uncaught exception: Error in asyncStorage.setItem():
Promise { <state>: "pending" }

...when running this directly in the console:
Code: Select all
(async function ()
{
   var addons = await AddonManager.getAllAddons();
   addons.forEach(function (addon)
         {
                if (addon.hidden == false && addon.isSystem == false)
               {
                  addon.userDisabled = true;
               }
         });
})();

Of course, the code does nothing :(

Finally, when attempting to import AddonManager.jsm within an autoconfig setup,
Code: Select all
Components.utils.import("resource://gre/modules/AddonManager.jsm");

...the console returns at browser startup:
NS_ERROR_NOT_INITIALIZED: AddonManager is not initialized AddonManager.jsm:2912

Is this all essentially hopeless?

Thanks again --

morat
 
Posts: 4855
Joined: February 3rd, 2009, 6:29 pm

Post Posted July 21st, 2020, 10:23 am

Well I think you should give up. The userChrome.js hacks are for advanced users and legacy docs are not updated since legacy extensions are obsolete.

morat wrote:You can use the addon.userDisabled property to disable addons.

Sorry, that's wrong. I tested all the code I posted, but I didn't test the userDisabled property. I had to examine the source to figure out the legacy code.

Code: Select all
// disable all non-hidden non-system extensions
// open about:addons to see status change

(async function () {
  var addons = await AddonManager.getAddonsByTypes(["extension"]);
  addons.forEach(function (addon) {
    if (addon.hidden == false && addon.isSystem == false) {
      console.log("Name: " + addon.name + ", Id: " + addon.id);
   // addon.userDisabled = true; // fails
      addon.disable();
    }
  });
})();
Last edited by morat on July 23rd, 2020, 8:44 am, edited 1 time in total.

AlbertG
 
Posts: 57
Joined: April 12th, 2006, 2:44 pm

Post Posted July 21st, 2020, 11:55 am

Well, nuts...

For the record, your new code did run as anticipated from the console. And, calling "addon.enable();" has the expected inverse effect on the installed Add-on collection.

However, running the code from an auticonfig setting with
Code: Select all
Components.utils.import("resource://gre/modules/AddonManager.jsm");

returns the inescapable
NS_ERROR_NOT_INITIALIZED: AddonManager is not initialized AddonManager.jsm:2912

...so I guess this type of thing has been essentially removed from the roster of goodies for this type of scripting.

Here's hoping some of the foregoing will be of use to others in their efforts :)

Thanks again, and have a great day!

morat
 
Posts: 4855
Joined: February 3rd, 2009, 6:29 pm

Post Posted July 21st, 2020, 2:18 pm

morat wrote:The window.AddonManager object is already available in the browser.xhtml window. (no need to import)

Here is a toggle addons button. First click disable addons. Second click enable addons.

* <profile directory>\chrome\ToggleAddonsFirefoxButton_Movable.uc.js

Code: Select all
(function () {
  if (location != "chrome://browser/content/browser.xul" &&
      location != "chrome://browser/content/browser.xhtml") return;

  /* CustomizableUI
     http://developer.mozilla.org/docs/Mozilla/JavaScript_code_modules/CustomizableUI.jsm
     http://developer.mozilla.org/docs/Mozilla/JavaScript_code_modules/CustomizableUI.jsm/API-provided_widgets
  */

  try {
    CustomizableUI.createWidget({
      id: "__unique_identifier_toggle_addons_button", // should match id below
      type: "button",
      defaultArea: CustomizableUI.AREA_MENUBAR,
   // defaultArea: CustomizableUI.AREA_NAVBAR,
      label: "Toggle Addons",
      tooltiptext: "Toggle Addons" + "\n" + "\n" +
        "L: enable or disable addons" + "\n" + "R: open button context popup",
      onCommand: function (aEvent) {
        var win = aEvent.target.ownerDocument.defaultView;
        var uid = "__unique_identifier_toggle_addons_boolean";
        if (typeof win[uid] == "undefined") win[uid] = true;
        else delete win[uid];
        async function toggleAddons() {
          var addons = await AddonManager.getAddonsByTypes(["extension"]);
          addons.forEach(function (addon) {
            if (addon.hidden == false && addon.isSystem == false) {
              if (win[uid]) addon.disable();
              else addon.enable();
            }
          });
        }
        toggleAddons();
      },
    });
  } catch (e) {
    Components.utils.reportError(e); // [check] Show Content Messages
  };

  var ios = Components.classes["@mozilla.org/network/io-service;1"].
    getService(Components.interfaces.nsIIOService);
  var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"].
    getService(Components.interfaces.nsIStyleSheetService);
  var dataUrl = "chrome://mozapps/skin/extensions/extension.svg";
  var css = "#__unique_identifier_toggle_addons_button {";
  css += 'list-style-image: url("' + dataUrl + '") !important;';
  css += "-moz-image-region: auto !important;";
  css += "fill: #0a84ff !important;";
  css += "}";
  var uri = ios.newURI("data:text/css," + encodeURIComponent(css), null, null);
  if (!sss.sheetRegistered(uri, sss.USER_SHEET)) {
    sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
  }
})();

Okay. I'm done here.

AlbertG wrote:Thanks again, and have a great day!

You're welcome.

Return to Extension Development


Who is online

Users browsing this forum: No registered users and 2 guests