home *** CD-ROM | disk | FTP | other *** search
/ Freelog 100 / FreelogNo100-NovembreDecembre2010.iso / Multimedia / Songbird / Songbird_1.8.0-1800_windows-i686-msvc8.exe / components / nsBrowserGlue.js < prev    next >
Text File  |  2010-08-30  |  34KB  |  868 lines

  1. /*
  2. //@line 40 "/e/builds/nightly/release-branch/sb_win32bot01_release/build/dependencies/vendor/mozbrowser/components/nsBrowserGlue.js"
  3.  */
  4.  
  5. const Ci = Components.interfaces;
  6. const Cc = Components.classes;
  7. const Cr = Components.results;
  8. const Cu = Components.utils;
  9.  
  10. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  11. // XXX Songbird: distribution file moved from its old location
  12. // Cu.import("resource:///modules/distribution.js");
  13. Cu.import("resource://app/jsmodules/Distribution.jsm");
  14.  
  15. const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
  16.  
  17. // Check to see if bookmarks need backing up once per
  18. // day on 1 hour idle.
  19. const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60;
  20.  
  21. // Backup bookmarks once every 24 hours.
  22. const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000;
  23.  
  24. // Factory object
  25. const BrowserGlueServiceFactory = {
  26.   _instance: null,
  27.   createInstance: function (outer, iid) 
  28.   {
  29.     if (outer != null)
  30.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  31.     return this._instance == null ?
  32.       this._instance = new BrowserGlue() : this._instance;
  33.   }
  34. };
  35.  
  36. // Constructor
  37.  
  38. function BrowserGlue() {
  39.   this._init();
  40. }
  41.  
  42. BrowserGlue.prototype = {
  43.   __prefs: null,
  44.   get _prefs() {
  45.     if (!this.__prefs)
  46.       this.__prefs = Cc["@mozilla.org/preferences-service;1"].
  47.                      getService(Ci.nsIPrefBranch);
  48.     return this.__prefs;
  49.   },
  50.  
  51.   _saveSession: false,
  52.  
  53.   _setPrefToSaveSession: function()
  54.   {
  55.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  56.                      getService(Ci.nsIPrefBranch);
  57.     prefBranch.setBoolPref("browser.sessionstore.resume_session_once", true);
  58.   },
  59.  
  60.   // nsIObserver implementation 
  61.   observe: function(subject, topic, data) 
  62.   {
  63.     switch(topic) {
  64.       case "xpcom-shutdown":
  65.         this._dispose();
  66.         break;
  67.       case "quit-application": 
  68.         this._onProfileShutdown();
  69.         break;
  70.       case "prefservice:after-app-defaults":
  71.         this._onAppDefaults();
  72.         break;
  73.       case "final-ui-startup":
  74.         this._onProfileStartup();
  75.         break;
  76.       case "sessionstore-windows-restored":
  77.         this._onBrowserStartup();
  78.         break;
  79.       case "browser:purge-session-history":
  80.         // reset the console service's error buffer
  81.         const cs = Cc["@mozilla.org/consoleservice;1"].
  82.                    getService(Ci.nsIConsoleService);
  83.         cs.logStringMessage(null); // clear the console (in case it's open)
  84.         cs.reset();
  85.         break;
  86.       case "quit-application-requested":
  87.         this._onQuitRequest(subject, data);
  88.         break;
  89.       case "quit-application-granted":
  90.         if (this._saveSession) {
  91.           this._setPrefToSaveSession();
  92.         }
  93.         break;
  94.       case "session-save":
  95.         this._setPrefToSaveSession();
  96.         subject.QueryInterface(Ci.nsISupportsPRBool);
  97.         subject.data = true;
  98.         break;
  99.       case "idle":
  100.         if (this.idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
  101.           // Back up bookmarks.
  102.           this._archiveBookmarks();
  103.         }
  104.         break;
  105.     }
  106.   }, 
  107.  
  108.   // initialization (called on application startup) 
  109.   _init: function() 
  110.   {
  111.     // observer registration
  112.     const osvr = Cc['@mozilla.org/observer-service;1'].
  113.                  getService(Ci.nsIObserverService);
  114.     osvr.addObserver(this, "quit-application", false);
  115.     osvr.addObserver(this, "xpcom-shutdown", false);
  116.     osvr.addObserver(this, "prefservice:after-app-defaults", false);
  117.     osvr.addObserver(this, "final-ui-startup", false);
  118.     osvr.addObserver(this, "sessionstore-windows-restored", false);
  119.     osvr.addObserver(this, "browser:purge-session-history", false);
  120.     osvr.addObserver(this, "quit-application-requested", false);
  121.     osvr.addObserver(this, "quit-application-granted", false);
  122.     osvr.addObserver(this, "session-save", false);
  123.   },
  124.  
  125.   // cleanup (called on application shutdown)
  126.   _dispose: function() 
  127.   {
  128.     // observer removal 
  129.     const osvr = Cc['@mozilla.org/observer-service;1'].
  130.                  getService(Ci.nsIObserverService);
  131.     osvr.removeObserver(this, "quit-application");
  132.     osvr.removeObserver(this, "xpcom-shutdown");
  133.     osvr.removeObserver(this, "prefservice:after-app-defaults");
  134.     osvr.removeObserver(this, "final-ui-startup");
  135.     osvr.removeObserver(this, "sessionstore-windows-restored");
  136.     osvr.removeObserver(this, "browser:purge-session-history");
  137.     osvr.removeObserver(this, "quit-application-requested");
  138.     osvr.removeObserver(this, "quit-application-granted");
  139.     osvr.removeObserver(this, "session-save");
  140.   },
  141.  
  142.   _onAppDefaults: function()
  143.   {
  144.     // apply distribution customizations (prefs)
  145.     // other customizations are applied in _onProfileStartup()
  146.     // XXX Songbird: allow not having a distribution customizer
  147.     if ("function" == typeof(DistributionCustomizer)) {
  148.       var distro = new DistributionCustomizer();
  149.       distro.applyPrefDefaults();
  150.     }
  151.   },
  152.  
  153.   // profile startup handler (contains profile initialization routines)
  154.   _onProfileStartup: function() 
  155.   {
  156.     this.Sanitizer.onStartup();
  157.     // check if we're in safe mode
  158.     var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
  159.               QueryInterface(Ci.nsIXULRuntime);
  160.     if (app.inSafeMode) {
  161.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  162.                getService(Ci.nsIWindowWatcher);
  163.       ww.openWindow(null, "chrome://browser/content/safeMode.xul", 
  164.                     "_blank", "chrome,centerscreen,modal,resizable=no", null);
  165.     }
  166.  
  167.     // initialize Places
  168.     this._initPlaces();
  169.  
  170.     // apply distribution customizations
  171.     // prefs are applied in _onAppDefaults()
  172.     // XXX Songbird: allow not having a distribution customizer
  173.     if ("function" == typeof(DistributionCustomizer)) {
  174.       var distro = new DistributionCustomizer();
  175.       distro.applyCustomizations();
  176.     }
  177.  
  178.     // handle any UI migration
  179.     this._migrateUI();
  180.  
  181.     const osvr = Cc['@mozilla.org/observer-service;1'].
  182.                  getService(Ci.nsIObserverService);
  183.     osvr.notifyObservers(null, "browser-ui-startup-complete", "");
  184.   },
  185.  
  186.   // profile shutdown handler (contains profile cleanup routines)
  187.   _onProfileShutdown: function() 
  188.   {
  189.     this._shutdownPlaces();
  190.     this.idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  191.     this.Sanitizer.onShutdown();
  192.   },
  193.  
  194.   // Browser startup complete. All initial windows have opened.
  195.   _onBrowserStartup: function()
  196.   {
  197.     // Show about:rights notification, if needed.
  198.     if (this._shouldShowRights())
  199.       this._showRightsNotification();
  200.  
  201.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  202.                      getService(Ci.nsIPrefBranch);
  203.     // If new add-ons were installed during startup open the add-ons manager.
  204.     if (prefBranch.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST)) {
  205.       var args = Cc["@mozilla.org/supports-array;1"].
  206.                  createInstance(Ci.nsISupportsArray);
  207.       var str = Cc["@mozilla.org/supports-string;1"].
  208.                 createInstance(Ci.nsISupportsString);
  209.       str.data = "";
  210.       args.AppendElement(str);
  211.       var str = Cc["@mozilla.org/supports-string;1"].
  212.                 createInstance(Ci.nsISupportsString);
  213.       str.data = prefBranch.getCharPref(PREF_EM_NEW_ADDONS_LIST);
  214.       args.AppendElement(str);
  215.       const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
  216.       const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
  217.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  218.                getService(Ci.nsIWindowWatcher);
  219.       ww.openWindow(null, EMURL, "_blank", EMFEATURES, args);
  220.       prefBranch.clearUserPref(PREF_EM_NEW_ADDONS_LIST);
  221.     }
  222.   },
  223.  
  224.   _onQuitRequest: function(aCancelQuit, aQuitType)
  225.   {
  226.     // If user has already dismissed quit request, then do nothing
  227.     if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
  228.       return;
  229.  
  230.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  231.              getService(Ci.nsIWindowMediator);
  232.  
  233.     var windowcount = 0;
  234.     var pagecount = 0;
  235.     var browserEnum = wm.getEnumerator("navigator:browser");
  236.     while (browserEnum.hasMoreElements()) {
  237.       windowcount++;
  238.  
  239.       var browser = browserEnum.getNext();
  240.       var tabbrowser = browser.document.getElementById("content");
  241.       if (tabbrowser)
  242.         pagecount += tabbrowser.browsers.length;
  243.     }
  244.  
  245.     this._saveSession = false;
  246.     if (pagecount < 2)
  247.       return;
  248.  
  249.     if (aQuitType != "restart")
  250.       aQuitType = "quit";
  251.  
  252.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  253.                      getService(Ci.nsIPrefBranch);
  254.     var showPrompt = true;
  255.     try {
  256.       // browser.warnOnQuit is a hidden global boolean to override all quit prompts
  257.       // browser.warnOnRestart specifically covers app-initiated restarts where we restart the app
  258.       // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
  259.  
  260.       var sessionWillBeSaved = prefBranch.getIntPref("browser.startup.page") == 3 ||
  261.                                prefBranch.getBoolPref("browser.sessionstore.resume_session_once");
  262.       if (sessionWillBeSaved || !prefBranch.getBoolPref("browser.warnOnQuit"))
  263.         showPrompt = false;
  264.       else if (aQuitType == "restart")
  265.         showPrompt = prefBranch.getBoolPref("browser.warnOnRestart");
  266.       else
  267.         showPrompt = prefBranch.getBoolPref("browser.tabs.warnOnClose");
  268.     } catch (ex) {}
  269.  
  270.     if (!showPrompt)
  271.       return false;
  272.  
  273.     var buttonChoice = 0;
  274.     var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
  275.                         getService(Ci.nsIStringBundleService);
  276.     var quitBundle = bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
  277.     var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
  278.  
  279.     var appName = brandBundle.GetStringFromName("brandShortName");
  280.     var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle",
  281.                                                             [appName], 1);
  282.  
  283.     var message;
  284.     if (aQuitType == "restart")
  285.       message = quitBundle.formatStringFromName("messageRestart",
  286.                                                 [appName], 1);
  287.     else if (windowcount == 1)
  288.       message = quitBundle.formatStringFromName("messageNoWindows",
  289.                                                 [appName], 1);
  290.     else
  291.       message = quitBundle.formatStringFromName("message",
  292.                                                 [appName], 1);
  293.  
  294.     var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  295.                         getService(Ci.nsIPromptService);
  296.  
  297.     var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
  298.                 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
  299.                 promptService.BUTTON_POS_0_DEFAULT;
  300.  
  301.     var neverAsk = {value:false};
  302.     var button0Title, button2Title;
  303.     var button1Title = quitBundle.GetStringFromName("cancelTitle");
  304.     var neverAskText = quitBundle.GetStringFromName("neverAsk");
  305.  
  306.     if (aQuitType == "restart")
  307.       button0Title = quitBundle.GetStringFromName("restartTitle");
  308.     else {
  309.       flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
  310.       button0Title = quitBundle.GetStringFromName("saveTitle");
  311.       button2Title = quitBundle.GetStringFromName("quitTitle");
  312.     }
  313.  
  314.     buttonChoice = promptService.confirmEx(null, quitDialogTitle, message,
  315.                                  flags, button0Title, button1Title, button2Title,
  316.                                  neverAskText, neverAsk);
  317.  
  318.     switch (buttonChoice) {
  319.     case 2: // Quit
  320.       if (neverAsk.value)
  321.         prefBranch.setBoolPref("browser.tabs.warnOnClose", false);
  322.       break;
  323.     case 1: // Cancel
  324.       aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
  325.       aCancelQuit.data = true;
  326.       break;
  327.     case 0: // Save & Quit
  328.       this._saveSession = true;
  329.       if (neverAsk.value) {
  330.         if (aQuitType == "restart")
  331.           prefBranch.setBoolPref("browser.warnOnRestart", false);
  332.         else {
  333.           // always save state when shutting down
  334.           prefBranch.setIntPref("browser.startup.page", 3);
  335.         }
  336.       }
  337.       break;
  338.     }
  339.   },
  340.  
  341.   /*
  342.    * _shouldShowRights - Determines if the user should be shown the
  343.    * about:rights notification. The notification should *not* be shown if
  344.    * we've already shown the current version, or if the override pref says to
  345.    * never show it. The notification *should* be shown if it's never been seen
  346.    * before, if a newer version is available, or if the override pref says to
  347.    * always show it.
  348.    */
  349.   _shouldShowRights : function () {
  350.     // Look for an unconditional override pref. If set, do what it says.
  351.     // (true --> never show, false --> always show)
  352.     try {
  353.       return !this._prefs.getBoolPref("browser.rights.override");
  354.     } catch (e) { }
  355.     // Ditto, for the legacy EULA pref.
  356.     try {
  357.       return !this._prefs.getBoolPref("browser.EULA.override");
  358.     } catch (e) { }
  359.  
  360. //@line 398 "/e/builds/nightly/release-branch/sb_win32bot01_release/build/dependencies/vendor/mozbrowser/components/nsBrowserGlue.js"
  361.     // Non-official builds shouldn't shouldn't show the notification.
  362.     return false;
  363. //@line 401 "/e/builds/nightly/release-branch/sb_win32bot01_release/build/dependencies/vendor/mozbrowser/components/nsBrowserGlue.js"
  364.  
  365.     // Look to see if the user has seen the current version or not.
  366.     var currentVersion = this._prefs.getIntPref("browser.rights.version");
  367.     try {
  368.       return !this._prefs.getBoolPref("browser.rights." + currentVersion + ".shown");
  369.     } catch (e) { }
  370.  
  371.     // Legacy: If the user accepted a EULA, we won't annoy them with the
  372.     // equivalent about:rights page until the version changes.
  373.     try {
  374.       return !this._prefs.getBoolPref("browser.EULA." + currentVersion + ".accepted");
  375.     } catch (e) { }
  376.  
  377.     // We haven't shown the notification before, so do so now.
  378.     return true;
  379.   },
  380.  
  381.   _showRightsNotification : function () {
  382.     // Stick the notification onto the selected tab of the active browser window.
  383.     var win = this._getMostRecentBrowserWindow();
  384.     var browser = win.gBrowser; // for closure in notification bar callback
  385.     var notifyBox = browser.getNotificationBox();
  386.  
  387.     var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
  388.                         getService(Ci.nsIStringBundleService);
  389.     var brandBundle  = bundleService.createBundle("chrome://branding/locale/brand.properties");
  390.     var rightsBundle = bundleService.createBundle("chrome://browser/locale/aboutRights.properties");
  391.  
  392.     var buttonLabel     = rightsBundle.GetStringFromName("buttonLabel");
  393.     var buttonAccessKey = rightsBundle.GetStringFromName("buttonAccessKey");
  394.     var productName     = brandBundle.GetStringFromName("brandFullName");
  395.     var notifyText      = rightsBundle.formatStringFromName("notifyText", [productName], 1);
  396.     
  397.     var buttons = [
  398.                     {
  399.                       label:     buttonLabel,
  400.                       accessKey: buttonAccessKey,
  401.                       popup:     null,
  402.                       callback: function(aNotificationBar, aButton) {
  403.                         browser.selectedTab = browser.addTab("about:rights");
  404.                       }
  405.                     }
  406.                   ];
  407.  
  408.     // Set pref to indicate we've shown the notification.
  409.     var currentVersion = this._prefs.getIntPref("browser.rights.version");
  410.     this._prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);
  411.  
  412.     var box = notifyBox.appendNotification(notifyText, "about-rights", null, notifyBox.PRIORITY_INFO_LOW, buttons);
  413.     box.persistence = 3; // // arbitrary number, just so bar sticks around for a bit
  414.   },
  415.  
  416.   // returns the (cached) Sanitizer constructor
  417.   get Sanitizer() 
  418.   {
  419.     if(typeof(Sanitizer) != "function") { // we should dynamically load the script
  420.       Cc["@mozilla.org/moz/jssubscript-loader;1"].
  421.       getService(Ci.mozIJSSubScriptLoader).
  422.       loadSubScript("chrome://browser/content/sanitize.js", null);
  423.     }
  424.     return Sanitizer;
  425.   },
  426.  
  427.   _idleService: null,
  428.   get idleService() {
  429.     if (!this._idleService)
  430.       this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
  431.                           getService(Ci.nsIIdleService);
  432.     return this._idleService;
  433.   },
  434.  
  435.   /**
  436.    * Initialize Places
  437.    * - imports the bookmarks html file if bookmarks datastore is empty
  438.    *
  439.    * These prefs are set by the backend services upon creation (or recreation)
  440.    * of the Places db:
  441.    * - browser.places.importBookmarksHTML
  442.    *   Set to false by the history service to indicate we need to re-import.
  443.    * - browser.places.smartBookmarksVersion
  444.    *   Set during HTML import to indicate that Smart Bookmarks were created.
  445.    *   Set to -1 to disable Smart Bookmarks creation.
  446.    *   Set to 0 to restore current Smart Bookmarks.
  447.    *
  448.    * These prefs are set up by the frontend:
  449.    * - browser.bookmarks.restore_default_bookmarks
  450.    *   Set to true by safe-mode dialog to indicate we must restore default
  451.    *   bookmarks.
  452.    */
  453.   _initPlaces: function bg__initPlaces() {
  454.     // XXX Songbird: Songbird does not use Places
  455.     return;
  456.   
  457.     // we need to instantiate the history service before checking
  458.     // the browser.places.importBookmarksHTML pref, as
  459.     // nsNavHistory::ForceMigrateBookmarksDB() will set that pref
  460.     // if we need to force a migration (due to a schema change)
  461.     var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
  462.                   getService(Ci.nsINavHistoryService);
  463.  
  464.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  465.                      getService(Ci.nsIPrefBranch);
  466.  
  467.     var importBookmarks = false;
  468.     var importBookmarksHTML = false;
  469.     var restoreDefaultBookmarks = false;
  470.     try {
  471.       restoreDefaultBookmarks = prefBranch.getBoolPref("browser.bookmarks.restore_default_bookmarks");
  472.     } catch(ex) {}
  473.  
  474.     if (restoreDefaultBookmarks) {
  475.       // Ensure that we already have a bookmarks backup for today
  476.       this._archiveBookmarks();
  477.       // we will restore bookmarks from html
  478.       importBookmarks = true;
  479.     }
  480.     else {
  481.       try {
  482.         importBookmarks = importBookmarksHTML =
  483.           prefBranch.getBoolPref("browser.places.importBookmarksHTML");
  484.       } catch(ex) {}
  485.     }
  486.  
  487.     if (!importBookmarks) {
  488.       // Call it here for Fx3 profiles created before the Places folder
  489.       // has been added, otherwise it's called during import.
  490.       this.ensurePlacesDefaultQueriesInitialized();
  491.     }
  492.     else {
  493.       // get latest backup
  494.       Cu.import("resource://gre/modules/utils.js");
  495.       var bookmarksFile = PlacesUtils.getMostRecentBackup();
  496.  
  497.       if (!restoreDefaultBookmarks &&
  498.           bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
  499.         // restore a JSON backup
  500.         PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
  501.       }
  502.       else {
  503.         // if there's no JSON backup or we are restoring default bookmarks
  504.  
  505.         // ensurePlacesDefaultQueriesInitialized() is called by import.
  506.         prefBranch.setIntPref("browser.places.smartBookmarksVersion", 0);
  507.  
  508.         var dirService = Cc["@mozilla.org/file/directory_service;1"].
  509.                          getService(Ci.nsIProperties);
  510.  
  511.         var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
  512.         if (restoreDefaultBookmarks || !bookmarksFile.exists()) {
  513.           // get bookmarks.html file from default profile folder
  514.           bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
  515.           bookmarksFile.append("bookmarks.html");
  516.         }
  517.  
  518.         // import the file
  519.         try {
  520.           var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
  521.                          getService(Ci.nsIPlacesImportExportService);
  522.           importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
  523.         } catch (err) {
  524.           // Report the error, but ignore it.
  525.           Cu.reportError(err);
  526.         }
  527.       }
  528.       if (importBookmarksHTML)
  529.         prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
  530.       if (restoreDefaultBookmarks)
  531.         prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks",
  532.                                false);
  533.     }
  534.  
  535.     // Initialize bookmark archiving on idle.
  536.     // Once a day, either on idle or shutdown, bookmarks are backed up.
  537.     this.idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  538.   },
  539.  
  540.   /**
  541.    * Places shut-down tasks
  542.    * - back up and archive bookmarks
  543.    * - export bookmarks as HTML, if so configured
  544.    *
  545.    * Note: quit-application-granted notification is received twice
  546.    *       so replace this method with a no-op when first called.
  547.    */
  548.   _shutdownPlaces: function bg__shutdownPlaces() {
  549.     // Backup and archive Places bookmarks.
  550.     this._archiveBookmarks();
  551.  
  552.     // Backup bookmarks to bookmarks.html to support apps that depend
  553.     // on the legacy format.
  554.     var prefs = Cc["@mozilla.org/preferences-service;1"].
  555.                 getService(Ci.nsIPrefBranch);
  556.     var autoExportHTML = false;
  557.     try {
  558.       autoExportHTML = prefs.getBoolPref("browser.bookmarks.autoExportHTML");
  559.     } catch(ex) {
  560.       Components.utils.reportError(ex);
  561.     }
  562.  
  563.     if (autoExportHTML) {
  564.       Cc["@mozilla.org/browser/places/import-export-service;1"].
  565.         getService(Ci.nsIPlacesImportExportService).
  566.         backupBookmarksFile();
  567.     }
  568.   },
  569.  
  570.   /**
  571.    * Back up and archive bookmarks
  572.    */
  573.   _archiveBookmarks: function nsBrowserGlue__archiveBookmarks() {
  574.     Cu.import("resource://gre/modules/utils.js");
  575.  
  576.     var lastBackup = PlacesUtils.getMostRecentBackup();
  577.  
  578.     // Backup bookmarks if there aren't any backups or 
  579.     // they haven't been backed up in the last 24 hrs.
  580.     if (!lastBackup ||
  581.         Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) {
  582.       var maxBackups = 5;
  583.       var prefs = Cc["@mozilla.org/preferences-service;1"].
  584.                   getService(Ci.nsIPrefBranch);
  585.       try {
  586.         maxBackups = prefs.getIntPref("browser.bookmarks.max_backups");
  587.       } catch(ex) {}
  588.  
  589.       PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
  590.     }
  591.   },
  592.  
  593.   _migrateUI: function bg__migrateUI() {
  594.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  595.  
  596.     var migration = 0;
  597.     try {
  598.       migration = prefBranch.getIntPref("browser.migration.version");
  599.     } catch(ex) {}
  600.  
  601.     if (migration == 0) {
  602.       // this code should always migrate pre-FF3 profiles to the current UI state
  603.  
  604.       // grab the localstore.rdf and make changes needed for new UI
  605.       this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
  606.       this._dataSource = this._rdf.GetDataSource("rdf:local-store");
  607.       this._dirty = false;
  608.  
  609.       let currentsetResource = this._rdf.GetResource("currentset");
  610.       let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
  611.       for (let i = 0; i < toolbars.length; i++) {
  612.         let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]);
  613.         let currentset = this._getPersist(toolbar, currentsetResource);
  614.         if (!currentset) {
  615.           // toolbar isn't customized
  616.           if (i == 0)
  617.             // new button is in the defaultset, nothing to migrate
  618.             break;
  619.           continue;
  620.         }
  621.         if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset))
  622.           // new button is already there, nothing to migrate
  623.           break;
  624.         if (/(?:^|,)back-button(?:$|,)/.test(currentset)) {
  625.           let newset = currentset.replace(/(^|,)back-button($|,)/,
  626.                                           "$1unified-back-forward-button,back-button$2")
  627.           this._setPersist(toolbar, currentsetResource, newset);
  628.           // done migrating
  629.           break;
  630.         }
  631.       }
  632.  
  633.       // force the RDF to be saved
  634.       if (this._dirty)
  635.         this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
  636.  
  637.       // free up the RDF service
  638.       this._rdf = null;
  639.       this._dataSource = null;
  640.  
  641.       // update the migration version
  642.       prefBranch.setIntPref("browser.migration.version", 1);
  643.     }
  644.   },
  645.  
  646.   _getPersist: function bg__getPersist(aSource, aProperty) {
  647.     var target = this._dataSource.GetTarget(aSource, aProperty, true);
  648.     if (target instanceof Ci.nsIRDFLiteral)
  649.       return target.Value;
  650.     return null;
  651.   },
  652.  
  653.   _setPersist: function bg__setPersist(aSource, aProperty, aTarget) {
  654.     this._dirty = true;
  655.     try {
  656.       var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true);
  657.       if (oldTarget) {
  658.         if (aTarget)
  659.           this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget));
  660.         else
  661.           this._dataSource.Unassert(aSource, aProperty, oldTarget);
  662.       }
  663.       else {
  664.         this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
  665.       }
  666.     }
  667.     catch(ex) {}
  668.   },
  669.  
  670.   // ------------------------------
  671.   // public nsIBrowserGlue members
  672.   // ------------------------------
  673.   
  674.   sanitize: function(aParentWindow) 
  675.   {
  676.     this.Sanitizer.sanitize(aParentWindow);
  677.   },
  678.  
  679.   ensurePlacesDefaultQueriesInitialized: function() {
  680.     const SMART_BOOKMARKS_VERSION = 1;
  681.     const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
  682.     const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
  683.  
  684.     // XXX should this be a pref?  see bug #399268
  685.     const MAX_RESULTS = 10;
  686.  
  687.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  688.                      getService(Ci.nsIPrefBranch);
  689.  
  690.     // get current smart bookmarks version
  691.     // By default, if the pref is not set up, we must create Smart Bookmarks
  692.     var smartBookmarksCurrentVersion = 0;
  693.     try {
  694.       smartBookmarksCurrentVersion = prefBranch.getIntPref(SMART_BOOKMARKS_PREF);
  695.     } catch(ex) {}
  696.  
  697.     // bail out if we don't have to create or update Smart Bookmarks
  698.     if (smartBookmarksCurrentVersion == -1 ||
  699.         smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION)
  700.       return;
  701.  
  702.     var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
  703.                 getService(Ci.nsINavBookmarksService);
  704.     var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
  705.                   getService(Ci.nsIAnnotationService);
  706.  
  707.     var callback = {
  708.       _placesBundle: Cc["@mozilla.org/intl/stringbundle;1"].
  709.                      getService(Ci.nsIStringBundleService).
  710.                      createBundle("chrome://browser/locale/places/places.properties"),
  711.  
  712.       _uri: function(aSpec) {
  713.         return Cc["@mozilla.org/network/io-service;1"].
  714.                getService(Ci.nsIIOService).
  715.                newURI(aSpec, null, null);
  716.       },
  717.  
  718.       runBatched: function() {
  719.         var smartBookmarks = [];
  720.         var bookmarksMenuIndex = 0;
  721.         var bookmarksToolbarIndex = 0;
  722.  
  723.         // MOST VISITED
  724.         var smart = {queryId: "MostVisited", // don't change this
  725.                      itemId: null,
  726.                      title: this._placesBundle.GetStringFromName("mostVisitedTitle"),
  727.                      uri: this._uri("place:queryType=" +
  728.                                     Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
  729.                                     "&sort=" +
  730.                                     Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
  731.                                     "&maxResults=" + MAX_RESULTS),
  732.                      parent: bmsvc.toolbarFolder,
  733.                      position: bookmarksToolbarIndex++};
  734.         smartBookmarks.push(smart);
  735.  
  736.         // RECENTLY BOOKMARKED
  737.         smart = {queryId: "RecentlyBookmarked", // don't change this
  738.                  itemId: null,
  739.                  title: this._placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
  740.                  uri: this._uri("place:folder=BOOKMARKS_MENU" +
  741.                                 "&folder=UNFILED_BOOKMARKS" +
  742.                                 "&folder=TOOLBAR" +
  743.                                 "&queryType=" +
  744.                                 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
  745.                                 "&sort=" +
  746.                                 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
  747.                                 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
  748.                                 "&maxResults=" + MAX_RESULTS +
  749.                                 "&excludeQueries=1"),
  750.                  parent: bmsvc.bookmarksMenuFolder,
  751.                  position: bookmarksMenuIndex++};
  752.         smartBookmarks.push(smart);
  753.  
  754.         // RECENT TAGS
  755.         smart = {queryId: "RecentTags", // don't change this
  756.                  itemId: null,
  757.                  title: this._placesBundle.GetStringFromName("recentTagsTitle"),
  758.                  uri: this._uri("place:"+
  759.                     "type=" +
  760.                     Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
  761.                     "&sort=" +
  762.                     Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
  763.                     "&maxResults=" + MAX_RESULTS),
  764.                  parent: bmsvc.bookmarksMenuFolder,
  765.                  position: bookmarksMenuIndex++};
  766.         smartBookmarks.push(smart);
  767.  
  768.         var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
  769.         // set current itemId, parent and position if Smart Bookmark exists
  770.         for each(var itemId in smartBookmarkItemIds) {
  771.           var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  772.           for (var i = 0; i < smartBookmarks.length; i++){
  773.             if (smartBookmarks[i].queryId == queryId) {
  774.               smartBookmarks[i].itemId = itemId;
  775.               smartBookmarks[i].parent = bmsvc.getFolderIdForItem(itemId);
  776.               smartBookmarks[i].position = bmsvc.getItemIndex(itemId);
  777.               // remove current item, since it will be replaced
  778.               bmsvc.removeItem(itemId);
  779.               break;
  780.             }
  781.             // We don't remove old Smart Bookmarks because user could still
  782.             // find them useful, or could have personalized them.
  783.             // Instead we remove the Smart Bookmark annotation.
  784.             if (i == smartBookmarks.length - 1)
  785.               annosvc.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  786.           }
  787.         }
  788.  
  789.         // create smart bookmarks
  790.         for each(var smartBookmark in smartBookmarks) {
  791.           smartBookmark.itemId = bmsvc.insertBookmark(smartBookmark.parent,
  792.                                                       smartBookmark.uri,
  793.                                                       smartBookmark.position,
  794.                                                       smartBookmark.title);
  795.           annosvc.setItemAnnotation(smartBookmark.itemId,
  796.                                     SMART_BOOKMARKS_ANNO, smartBookmark.queryId,
  797.                                     0, annosvc.EXPIRE_NEVER);
  798.         }
  799.         
  800.         // If we are creating all Smart Bookmarks from ground up, add a
  801.         // separator below them in the bookmarks menu.
  802.         if (smartBookmarkItemIds.length == 0)
  803.           bmsvc.insertSeparator(bmsvc.bookmarksMenuFolder, bookmarksMenuIndex);
  804.       }
  805.     };
  806.  
  807.     try {
  808.       bmsvc.runInBatchMode(callback, null);
  809.     }
  810.     catch(ex) {
  811.       Components.utils.reportError(ex);
  812.     }
  813.     finally {
  814.       prefBranch.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION);
  815.       prefBranch.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
  816.     }
  817.   },
  818.  
  819. //@line 864 "/e/builds/nightly/release-branch/sb_win32bot01_release/build/dependencies/vendor/mozbrowser/components/nsBrowserGlue.js"
  820.  
  821.   // this returns the most recent non-popup browser window
  822.   _getMostRecentBrowserWindow : function ()
  823.   {
  824.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  825.              getService(Components.interfaces.nsIWindowMediator);
  826.  
  827. //@line 886 "/e/builds/nightly/release-branch/sb_win32bot01_release/build/dependencies/vendor/mozbrowser/components/nsBrowserGlue.js"
  828.     var windowList = wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
  829.     if (!windowList.hasMoreElements())
  830.       return null;
  831.  
  832.     var win = windowList.getNext();
  833.     while (win.document.documentElement.getAttribute("chromehidden")) {
  834.       if (!windowList.hasMoreElements())
  835.         return null;
  836.  
  837.       win = windowList.getNext();
  838.     }
  839. //@line 898 "/e/builds/nightly/release-branch/sb_win32bot01_release/build/dependencies/vendor/mozbrowser/components/nsBrowserGlue.js"
  840.  
  841.     return win;
  842.   },
  843.  
  844.   // for XPCOM
  845.   classDescription: "Firefox Browser Glue Service",
  846.   classID:          Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
  847.   contractID:       "@mozilla.org/browser/browserglue;1",
  848.  
  849.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
  850.                                          Ci.nsISupportsWeakReference,
  851.                                          Ci.nsIBrowserGlue]),
  852.  
  853.   // redefine the default factory for XPCOMUtils
  854.   _xpcom_factory: BrowserGlueServiceFactory,
  855.  
  856.   // get this contractID registered for certain categories via XPCOMUtils
  857.   _xpcom_categories: [
  858.     // make BrowserGlue a startup observer
  859.     { category: "app-startup", service: true }
  860.   ]
  861. }
  862.  
  863. //module initialization
  864. function NSGetModule(aCompMgr, aFileSpec) {
  865.   return XPCOMUtils.generateModule([BrowserGlue]);
  866. }
  867.  
  868.