[SOLVED]Firefox and autoconfig

Discussion of general topics about Mozilla Firefox
Post Reply
dweller
Posts: 6
Joined: January 4th, 2018, 7:16 am

[SOLVED]Firefox and autoconfig

Post by dweller »

Prior to release of Firefox Quantum, i used source code of Mike Kaply's CCK wizard to build custom autoconfig as part of customized installer, with some additional code examples from net i adapted for personal use.

Problem is that i downloaded FF version 69.0 and some functions no longer work or are not recognized.

Are there API docs that are up to date, as most examples on MXR, developer.mozilla.org and StackOverflow appear to be obsolete ?

Note that this may be of interest to people dealing with enterprise deployment (as autoconfig is originally intended for them).
Last edited by dweller on September 20th, 2019, 1:46 pm, edited 1 time in total.
morat
Posts: 6405
Joined: February 3rd, 2009, 6:29 pm

Re: Firefox and autoconfig

Post by morat »

Can you post the code? Perhaps, someone can offer fixes.

The problem is AFAIK Firefox devs don't document changes for legacy addon devs anymore.

Firefox developer release notes
http://developer.mozilla.org/docs/Mozil ... x/Releases

I have found that the Thunderbird addons guide to be useful in updating my Fx userChrome.js hacks.

Addons Guide for Thunderbird 57 to Thunderbird 60
http://wiki.mozilla.org/Thunderbird/Add-ons_Guide_57

Addons Guide for Thunderbird 63 and beyond
http://wiki.mozilla.org/Thunderbird/Add-ons_Guide_63

Changes in Thunderbird 61-68
http://developer.thunderbird.net/add-ons/updates/tb68

Changes in Thunderbird 69-70
http://developer.thunderbird.net/add-ons/updates/tb76

In Firefox 69, I had the following problems with my Fx userChrome.js hacks.

Firefox 68 uses the chrome://browser/content/browser.xul url.
Firefox 69 uses the chrome://browser/content/browser.xhtml url.

I fixed a button with the following substitute.

Find what: createElement(
Replace with: createXULElement(

I fixed another button using the Services.prompt.select method by removing the array length param.

nsIPromptService
http://dxr.mozilla.org/mozilla-release/ ... ervice.idl
http://dxr.mozilla.org/mozilla-release/ ... ersion.txt
dweller
Posts: 6
Joined: January 4th, 2018, 7:16 am

Re: Firefox and autoconfig

Post by dweller »

Here is the code i'm trying to port from older pre-Quantum releases :

bootstrap for main setup "\Mozilla Firefox\browser\defaults\preferences\autoconfig.js" :

Code: Select all

//
pref("general.config.obscure_value", 0);
pref("general.config.filename", "firefox_setup.js");
pref("general.config.sandbox_enabled", false);
main setup file in install root (this is supposed to be the final structure) "\Mozilla Firefox\firefox_setup.js" :

Code: Select all

//
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import ("resource:///modules/CustomizableUI.jsm");
Cu.import ("resource://gre/modules/FileUtils.jsm");
Cu.import ("resource://gre/modules/Sqlite.jsm");
Cu.import ("resource://gre/modules/Services.jsm");
Cu.import ("resource://gre/modules/PlacesUtils.jsm");
Cu.import ("resource://gre/modules/Bookmarks.jsm");

const alert = Services.prompt.alert;
const prefs = Services.prefs;

var NavigationBookmarks = Cc ["@mozilla.org/browser/nav-bookmarks-service;1"].getService (Ci.nsINavBookmarksService);
var History = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
var FileOutStream = Cc ["@mozilla.org/network/file-output-stream;1"].createInstance (Ci.nsIFileOutputStream);
var HandlerService = Cc ["@mozilla.org/uriloader/handler-service;1"].getService (Ci.nsIHandlerService);
var MimeService = Cc ["@mozilla.org/mime;1"].getService (Ci.nsIMIMEService);
var pdfMIMEInfo = MimeService.getFromTypeAndExtension ("application/pdf", "");
var ObserverService = Cc ["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);

pdfMIMEInfo.alwaysAskBeforeHandling = true;
HandlerService.store (pdfMIMEInfo);

async function removeAllTrustedSites()
{
  var conn = await Sqlite.openConnection ({ path: "permissions.sqlite", sharedMemoryCache: false });
  await conn.execute ("UPDATE moz_perms SET permission = 0 WHERE type = \"install\"");
  await conn.execute ("UPDATE moz_perms SET permission = 0 WHERE type = \"install\"");
  await conn.close();
}

removeAllTrustedSites();

prefs.setIntPref ("browser.link.open_newwindow.restriction", 0);
prefs.setIntPref ("browser.link.open_newwindow", 3);
prefs.setBoolPref ("browser.search.geoSpecificDefaults", false);
prefs.setCharPref ("browser.search.defaultenginename", "Google");
prefs.setCharPref ("browser.search.defaultenginename.US", "Google");
prefs.setBoolPref ("browser.download.useDownloadDir", false);
prefs.setIntPref ("browser.startup.page", 3);
prefs.setBoolPref ("browser.tabs.warnOnClose" , false);
prefs.setBoolPref ("browser.tabs.closeWindowWithLastTab", false);
prefs.setBoolPref ("browser.tabs.animate", false);
prefs.setBoolPref ("browser.panorama.animate_zoom", false);
prefs.setBoolPref ("browser.fullscreen.animateUp", false);
prefs.setBoolPref ("browser.search.openintab", true);
prefs.setIntPref ("layout.spellcheckDefault", 0);
prefs.setBoolPref ("media.peerconnection.enabled", false);
prefs.setBoolPref ("browser.search.showOneOffButtons", false);
prefs.setBoolPref ("dom.disable_window_move_resize", false);
prefs.setBoolPref ("dom.disable_window_flip", true);
prefs.setBoolPref ("dom.event.contextmenu.enabled", true);
prefs.setBoolPref ("browser.tabs.drawInTitlebar", false);
prefs.setBoolPref ("browser.download.autohideButton", false);

var autoconfigFile = FileUtils.getFile ("CurProcD", ["defaults","preferences", "autoconfig.js"], false, false);
var setupFirefoxFile = FileUtils.getDir ("CurProcD", [""], false, false).parent;
setupFirefoxFile.append ("firefox_setup.js");

function ClearAllWidgetsFromArea (targetArea)
{
  var i = 0;
  do
    {
    var widgets = CustomizableUI.getWidgetIdsInArea (targetArea);
    if (CustomizableUI.isWidgetRemovable (widgets [i]))
      {
        CustomizableUI.removeWidgetFromArea (widgets [i]);
        i = 0;
      }
    else i ++;
    }
  while (i < CustomizableUI.getWidgetIdsInArea (targetArea).length);
}

function AddWidgetsToArea (targetArea, widgets)
{
  for (var i = 0; i < widgets.length; i ++)
    CustomizableUI.addWidgetToArea (widgets [i], targetArea);
}

var observer =
  {
   observe: function (subject, topic, data)
     {
      if (topic == "chrome-document-global-created")
        {
         var win = subject.QueryInterface (Ci.nsIDOMWindow);
         win.addEventListener ("load", function (event)
           {
            win.removeEventListener ("load", arguments.callee, false);
            var doc = event.target;
            var url = doc.location.href.split ("?")[0].split ("#")[0];
            if (url == "chrome://browser/content/browser.xul")
              {
                var domwin = subject.QueryInterface (Ci.nsIInterfaceRequestor).getInterface (Ci.nsIDOMWindow);
                var menubarHidden = domwin.document.getElementById ("toolbar-menubar").getAttribute ("autohide");
                if (menubarHidden == "true") CustomizableUI.setToolbarVisibility ("toolbar-menubar", "true");
                var personalbarHidden = domwin.document.getElementById ("PersonalToolbar").getAttribute ("collapsed");
                if (personalbarHidden == "true") CustomizableUI.setToolbarVisibility ("PersonalToolbar", "true");
                NavigationBookmarks.removeFolderChildren (NavigationBookmarks.toolbarFolder);
                var bookmarksToAdd = [["about:permissions","Permissions"],
                                      ["about:config","Configuration"],
                                      ["about:support","Support"]];
                for (var i = 0; i < bookmarksToAdd.length; i ++)
                  NavigationBookmarks.insertBookmark (NavigationBookmarks.toolbarFolder,
                    Services.io.newURI (bookmarksToAdd [i][0], null, null),
                    NavigationBookmarks.DEFAULT_INDEX, bookmarksToAdd [i][1]);
                ClearAllWidgetsFromArea ("PersonalToolbar");
                AddWidgetsToArea ("PersonalToolbar",["_nonexistent_button_"]);
                AddWidgetsToArea ("PersonalToolbar",
                  ["personal-bookmarks", //bookmarks
                  "home-button", // home button
                   "downloads-button", // downloads
                   "bookmarks-menu-button", // bookmarks menu
                   ]);
                CustomizableUI.removeWidgetFromArea (widgets [0]);
                ClearAllWidgetsFromArea ("nav-bar");
                AddWidgetsToArea ("nav-bar",
                  ["stop-reload-button",
                   "zoom-controls",
                   "search-container"
                   ]);
                FileOutStream.init (autoconfigFile, -1, -1, false);
                FileOutStream.write ("", 0);
                FileOutStream.close ();
                FileOutStream.init (setupFirefoxFile, -1, -1, false);
                FileOutStream.write ("", 0);
                FileOutStream.close ();
              }//if url == chrome browser ...
           }, false);//addEventListener
        }//if topic == chrome document ...
     }//observe()
  }//var observer 
ObserverService.addObserver (observer, "chrome-document-global-created", false);
Note that :
- debugging is performed by running FF and watching for errors in browser console
- i tried importing Task.jsm but that is no longer available, luckily i was able to replace it with async/await
- FF complains that "removeFolderChildren is not a function" and similar for history service query SetFolders() (example taken from mozilla guides/docs)
- observer function is kind of working but the DOM url "chrome://browser/content/browser.xul" is no longer detected, i could only find "chrome://browser/content/commonDialog.xul", so all UI customizations can't be executed
- this setup is intended for one-time customization (look near the end of code, it removes itself leaving user in full control)
- since i added extensions to setup i also added widgets for each extension. before, names of widgets could be found using DOM inspector but that package appears to be dead
- since apparently API docs lag badly behind releases and examples do not cover all topics, i was heavily relying on Mike Kaply's CCK wizard to build my code, but that is no longer current
morat
Posts: 6405
Joined: February 3rd, 2009, 6:29 pm

Re: Firefox and autoconfig

Post by morat »

Are you running the script in Linux?

Windows uses the \Mozilla Firefox\defaults\pref\autoconfig.js path.
Linux uses the \Mozilla Firefox\browser\defaults\preferences\autoconfig.js path, AFAIK.

Deploying Firefox in an enterprise environment (before Firefox 60 ESR)
http://developer.mozilla.org/docs/Mozil ... _before_60

Maybe you can use the PlacesUtils.bookmarks.eraseEverything method instead of the nsINavBookmarksService.removeFolderChildren method, then recreate the default bookmarks in the "Mozilla Firefox" folder.

Code: Select all

- NavigationBookmarks.removeFolderChildren(NavigationBookmarks.toolbarFolder);
+ async function eraseEverything() {
+   await PlacesUtils.bookmarks.eraseEverything();
+   ...
+ }
+ eraseEverything();
nsINavBookmarksService
http://developer.mozilla.org/docs/Mozil ... rksService

removeFolderChildren and eraseEverything
http://dxr.mozilla.org/mozilla-esr52/se ... LUtils.jsm
http://dxr.mozilla.org/mozilla-release/ ... LUtils.jsm
http://dxr.mozilla.org/mozilla-release/ ... kmarks.jsm

I got the script working with Firefox Portable 69 in Windows.

* C:\FirefoxPortable\App\Firefox\defaults\pref\autoconfig.js

Code: Select all

// autoconfig.js file needs to start with a comment line

pref("general.config.sandbox_enabled", false);
pref("general.config.filename", "mozilla.cfg");
pref("general.config.obscure_value", 0);
* C:\FirefoxPortable\App\Firefox\mozilla.cfg

Code: Select all

// mozilla.cfg file needs to start with a comment line

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import ("resource:///modules/CustomizableUI.jsm");
Cu.import ("resource://gre/modules/FileUtils.jsm");
Cu.import ("resource://gre/modules/Sqlite.jsm");
Cu.import ("resource://gre/modules/Services.jsm");
Cu.import ("resource://gre/modules/PlacesUtils.jsm");
Cu.import ("resource://gre/modules/Bookmarks.jsm");

const alert = Services.prompt.alert;
const prefs = Services.prefs;

var NavigationBookmarks = Cc ["@mozilla.org/browser/nav-bookmarks-service;1"].getService (Ci.nsINavBookmarksService);
var History = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
var FileOutStream = Cc ["@mozilla.org/network/file-output-stream;1"].createInstance (Ci.nsIFileOutputStream);
var HandlerService = Cc ["@mozilla.org/uriloader/handler-service;1"].getService (Ci.nsIHandlerService);
var MimeService = Cc ["@mozilla.org/mime;1"].getService (Ci.nsIMIMEService);
var pdfMIMEInfo = MimeService.getFromTypeAndExtension ("application/pdf", "");
var ObserverService = Cc ["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);

pdfMIMEInfo.alwaysAskBeforeHandling = true;
HandlerService.store (pdfMIMEInfo);

async function removeAllTrustedSites()
{
  var conn = await Sqlite.openConnection ({ path: "permissions.sqlite", sharedMemoryCache: false });
  await conn.execute ("UPDATE moz_perms SET permission = 0 WHERE type = \"install\"");
  await conn.execute ("UPDATE moz_perms SET permission = 0 WHERE type = \"install\"");
  await conn.close();
}
removeAllTrustedSites();

prefs.setIntPref ("browser.link.open_newwindow.restriction", 0);
prefs.setIntPref ("browser.link.open_newwindow", 3);
prefs.setBoolPref ("browser.search.geoSpecificDefaults", false);
prefs.setCharPref ("browser.search.defaultenginename", "Google");
prefs.setCharPref ("browser.search.defaultenginename.US", "Google");
prefs.setBoolPref ("browser.download.useDownloadDir", false);
prefs.setIntPref ("browser.startup.page", 3);
prefs.setBoolPref ("browser.tabs.warnOnClose" , false);
prefs.setBoolPref ("browser.tabs.closeWindowWithLastTab", false);
prefs.setBoolPref ("browser.tabs.animate", false);
prefs.setBoolPref ("browser.panorama.animate_zoom", false);
prefs.setBoolPref ("browser.fullscreen.animateUp", false);
prefs.setBoolPref ("browser.search.openintab", true);
prefs.setIntPref ("layout.spellcheckDefault", 0);
prefs.setBoolPref ("media.peerconnection.enabled", false);
prefs.setBoolPref ("browser.search.showOneOffButtons", false);
prefs.setBoolPref ("dom.disable_window_move_resize", false);
prefs.setBoolPref ("dom.disable_window_flip", true);
prefs.setBoolPref ("dom.event.contextmenu.enabled", true);
prefs.setBoolPref ("browser.tabs.drawInTitlebar", false);
prefs.setBoolPref ("browser.download.autohideButton", false);

var autoconfigFile = FileUtils.getFile ("PrfDef", ["autoconfig.js"], false, false);
var setupFirefoxFile = FileUtils.getFile ("GreD", ["mozilla.cfg"], false, false);

function ClearAllWidgetsFromArea (targetArea)
{
  var i = 0;
  do
    {
    var widgets = CustomizableUI.getWidgetIdsInArea (targetArea);
    if (CustomizableUI.isWidgetRemovable (widgets [i]))
      {
        CustomizableUI.removeWidgetFromArea (widgets [i]);
        i = 0;
      }
    else i ++;
    }
  while (i < CustomizableUI.getWidgetIdsInArea (targetArea).length);
}

function AddWidgetsToArea (targetArea, widgets)
{
  for (var i = 0; i < widgets.length; i ++)
    CustomizableUI.addWidgetToArea (widgets [i], targetArea);
}

var observer =
  {
   observe: function (subject, topic, data)
     {
      if (topic == "chrome-document-global-created")
        {
         var win = subject.QueryInterface (Ci.nsIDOMWindow);
         win.addEventListener ("load", function (event)
           {
            win.removeEventListener ("load", arguments.callee, false);
            var doc = event.target;
            var url = doc.location.href.split ("?")[0].split ("#")[0];
            if (url == "chrome://browser/content/browser.xul" || // fx 68 uses browser.xul
                url == "chrome://browser/content/browser.xhtml") // fx 69 uses browser.xhtml
              {
                var domwin = subject.QueryInterface (Ci.nsIInterfaceRequestor).getInterface (Ci.nsIDOMWindow);
                var menubarHidden = domwin.document.getElementById ("toolbar-menubar").getAttribute ("autohide");
                if (menubarHidden == "true") CustomizableUI.setToolbarVisibility ("toolbar-menubar", "true");
                var personalbarHidden = domwin.document.getElementById ("PersonalToolbar").getAttribute ("collapsed");
                if (personalbarHidden == "true") CustomizableUI.setToolbarVisibility ("PersonalToolbar", "true");
             // NavigationBookmarks.removeFolderChildren (NavigationBookmarks.toolbarFolder); // removeFolderChildren obsolete
                win.setTimeout(function () {
                  async function eraseEverything()
                  {
                    await PlacesUtils.bookmarks.eraseEverything();
                    var bookmarksToAdd = [["about:permissions","Permissions"],
                                          ["about:config","Configuration"],
                                          ["about:support","Support"]];
                    for (var i = 0; i < bookmarksToAdd.length; i ++)
                      NavigationBookmarks.insertBookmark (NavigationBookmarks.toolbarFolder,
                        Services.io.newURI (bookmarksToAdd [i][0], null, null),
                        NavigationBookmarks.DEFAULT_INDEX, bookmarksToAdd [i][1]);
                    ClearAllWidgetsFromArea ("PersonalToolbar");
                 // AddWidgetsToArea ("PersonalToolbar",["_nonexistent_button_"]); // button does not exist
                    AddWidgetsToArea ("PersonalToolbar",
                      ["personal-bookmarks", // personal bookmarks item
                       "home-button", // home button
                       "downloads-button", // downloads button
                       "bookmarks-menu-button", // bookmarks menu button
                       ]);
                 // CustomizableUI.removeWidgetFromArea (widgets [0]); // widgets is not defined
                    ClearAllWidgetsFromArea ("nav-bar");
                    AddWidgetsToArea ("nav-bar",
                      ["stop-reload-button",
                       "zoom-controls",
                       "search-container",
                       ]);
                    FileOutStream.init (autoconfigFile, -1, -1, false);
                    FileOutStream.write ("", 0);
                    FileOutStream.close ();
                    FileOutStream.init (setupFirefoxFile, -1, -1, false);
                    FileOutStream.write ("", 0);
                    FileOutStream.close ();
                  }
                  eraseEverything();
                }, 3000);
              }//if url == chrome browser ...
           }, false);//addEventListener
        }//if topic == chrome document ...
     }//observe()
  }//var observer
ObserverService.addObserver (observer, "chrome-document-global-created", false);
Try using the Browser Toolbox instead of DOM inspector.

* set devtools.chrome.enabled pref to true
* set devtools.debugger.remote-enabled pref to true

Browser Toolbox
http://developer.mozilla.org/docs/Tools/Browser_Toolbox

How do we get DOM info for userChrome in 57+
http://forums.mozillazine.org/viewtopic.php?p=14772138

P.S.

I like using the "browser-delayed-startup-finished" topic instead of the "chrome-document-global-created" topic.

Code: Select all

// mozilla.cfg file needs to start with a comment line

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

Services.obs.addObserver(function (aSubject, aTopic, aData) {
  Services.obs.removeObserver(arguments.callee, "browser-delayed-startup-finished");
  Services.console.logStringMessage("example");
  var chromeWindow = aSubject;
  chromeWindow.setTimeout(function () {
    Services.prompt.alert(chromeWindow, "example", "test");
  }, 1000);
}, "browser-delayed-startup-finished", false);
Observer Notifications
http://developer.mozilla.org/docs/Mozil ... ifications
dweller
Posts: 6
Joined: January 4th, 2018, 7:16 am

Re: Firefox and autoconfig

Post by dweller »

Huge thanks !

I'm using this on Windows machine. I wasn't aware of above mentioned docs / addons. Javascript can be unforgiving if there are no proper docs.
Indeed i too managed later to capture DOM url "chrome://browser/content/browser.xhtml" so it is confirmed from my side.
Also i followed a Browser Toolbox guide on how to enable new DOM inspector and it worked only because of keyboard shortcut (i haven't found any menus described on that page).
The Browser Console helped also with some sort of code-completion (first ever i saw for FF-related javascript), pitty it has no in / out parameter help (even though i can click on error line and open function in relevant .js file).
I'll post more info as i dig around API.
morat
Posts: 6405
Joined: February 3rd, 2009, 6:29 pm

Re: Firefox and autoconfig

Post by morat »

morat wrote:recreate the default bookmarks in the "Mozilla Firefox" folder
Here is a simple way to import bookmarks from a personal bookmarks.html file. (test code in console)

Code: Select all

(function () {
  var { BookmarkHTMLUtils } = ChromeUtils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
  BookmarkHTMLUtils.importFromURL("file:///C:/bookmarks.html");
})();
Browser Console command line
http://developer.mozilla.org/docs/Tools ... mmand_line

Default bookmarks
view-source:chrome://browser/locale/bookmarks.html
dweller
Posts: 6
Joined: January 4th, 2018, 7:16 am

Re: Firefox and autoconfig

Post by dweller »

Ok more data.

I tried to use PlacesUtils.bookmarks.eraseEverything() but it runs asynchronously, so after it starts, all bookmarks that are added after calling the function are erased as well (i could see on FF startup bookmarks being added and then blink out of existence). Even "await" wasn't able to sequentially execute the function.

I'd be thankful if a promise/then() example wrapper for PlacesUtils.bookmarks.eraseEverything() is provided.

As for importing bookmarks, i want to keep customization in smallest number of files, so i'm trying to avoid adding yet another file just for bookmarks.

As for adding observer with topic "browser-delayed-startup-finished", it worked great ! I was able to remove event listener since topic itself guaranteed all UI elements are present before manipulating them.

I'm able to run much simpler code :

Code: Select all

var win = subject.QueryInterface (Ci.nsIDOMWindow);
win.document.getElementById ("PersonalToolbar").setAttribute ("collapsed", false);
win.document.getElementById ("toolbar-menubar").setAttribute ("autohide", false);
Also, no "subject.QueryInterface (Ci.nsIInterfaceRequestor).getInterface (Ci.nsIDOMWindow)" shenanigans needed. :)
morat
Posts: 6405
Joined: February 3rd, 2009, 6:29 pm

Re: Firefox and autoconfig

Post by morat »

You could run code similar to the WebExtensions browser.bookmarks.getChildren method and WebExtensions browser.bookmarks.remove method to remove the children in the bookmarks toolbar folder. (test code in console)

Code: Select all

(function () {

  // begin code from ext-bookmarks.js

  const { TYPE_BOOKMARK, TYPE_FOLDER, TYPE_SEPARATOR } = PlacesUtils.bookmarks;

  const BOOKMARKS_TYPES_TO_API_TYPES_MAP = new Map([
    [TYPE_BOOKMARK, "bookmark"],
    [TYPE_FOLDER, "folder"],
    [TYPE_SEPARATOR, "separator"],
  ]);

  const BOOKMARK_SEPERATOR_URL = "data:";

  function getUrl(type, url) {
    switch (type) {
      case TYPE_BOOKMARK:
        return url;
      case TYPE_SEPARATOR:
        return BOOKMARK_SEPERATOR_URL;
      default:
        return undefined;
    }
  }

  const getTree = (rootGuid, onlyChildren) => {
    function convert(node, parent) {
      let treenode = {
        id: node.guid,
        title: PlacesUtils.bookmarks.getLocalizedTitle(node) || "",
        index: node.index,
        dateAdded: node.dateAdded / 1000,
        type: BOOKMARKS_TYPES_TO_API_TYPES_MAP.get(node.typeCode),
        url: getUrl(node.typeCode, node.uri),
      };

      if (parent && node.guid != PlacesUtils.bookmarks.rootGuid) {
        treenode.parentId = parent.guid;
      }

      if (node.typeCode == TYPE_FOLDER) {
        treenode.dateGroupModified = node.lastModified / 1000;

        if (!onlyChildren) {
          treenode.children = node.children
            ? node.children.map(child => convert(child, node))
            : [];
        }
      }

      return treenode;
    }

    return PlacesUtils.promiseBookmarksTree(rootGuid)
      .then(root => {
        if (onlyChildren) {
          let children = root.children || [];
          return children.map(child => convert(child, root));
        }
        let treenode = convert(root, null);
        treenode.parentId = root.parentGuid;
        // It seems like the array always just contains the root node.
        return [treenode];
      })
      .catch(e => Promise.reject({ message: e.message }));
  };

  // end code from ext-bookmarks.js

  var placesRoot = PlacesUtils.bookmarks.rootGuid;
  var bookmarksMenuFolder = PlacesUtils.bookmarks.menuGuid;
  var unfiledBookmarksFolder = PlacesUtils.bookmarks.unfiledGuid;
  var toolbarFolder = PlacesUtils.bookmarks.toolbarGuid;

  // similar to WebExtensions browser.bookmarks.getChildren method
  getTree(toolbarFolder, true).then(function (children) {
    for (child of children) {
      console.log(child);
      // similar to WebExtensions browser.bookmarks.remove method
      PlacesUtils.bookmarks.remove({guid: child.id});
    }   
  });

})();
note: read code from bottom to top, top is a big snippet from ext-bookmarks.js

WebExtensions browser.bookmarks
http://developer.mozilla.org/docs/Mozil ... /bookmarks
http://dxr.mozilla.org/mozilla-release/ ... okmarks.js

WebExtensions browser.bookmarks.getChildren
http://developer.mozilla.org/docs/Mozil ... etChildren
http://dxr.mozilla.org/mozilla-release/ ... okmarks.js

WebExtensions browser.bookmarks.remove
http://developer.mozilla.org/docs/Mozil ... rks/remove
http://dxr.mozilla.org/mozilla-release/ ... okmarks.js
dweller
Posts: 6
Joined: January 4th, 2018, 7:16 am

Re: [SOLVED]Firefox and autoconfig

Post by dweller »

I finally found an example to utilise Promise and fortunately code required to run it is simple for my use-case, which is to remove all existing bookmarks after fresh FF install and then adding my own. It is sufficient for my intended one-time setup. Program flow is preserved.
Code copied from https://developer.mozilla.org/en-US/doc ... ts/Promise .

Code: Select all

const Cu = Components.utils;
const Ci = Components.interfaces;
const Cc = Components.classes;
Cu.import ("resource://gre/modules/PlacesUtils.jsm");
var NavigationBookmarks = Cc ["@mozilla.org/browser/nav-bookmarks-service;1"].getService (Ci.nsINavBookmarksService);
//here it is !
          var doErase = Promise.resolve(PlacesUtils.bookmarks.eraseEverything());
          doErase.then(function(value)
          {
            var bookmarksToAdd =
              [
                ["about:permissions","Permissions"],
                ["about:config","Configuration"],
                ["about:support","Support"]
              ];
            for (var i = 0; i < bookmarksToAdd.length; i ++)
              NavigationBookmarks.insertBookmark (NavigationBookmarks.toolbarFolder,
                Services.io.newURI (bookmarksToAdd [i][0], null, null),
                NavigationBookmarks.DEFAULT_INDEX, bookmarksToAdd [i][1]);
          });
Post Reply