home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 February / PCWorld_2008-02_cd.bin / temacd / songbird / Songbird_0.4_windows-i686.exe / components / nsBrowserGlue.js < prev    next >
Text File  |  2007-12-21  |  17KB  |  482 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is the Firefox Browser Glue Service.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Giorgio Maone
  18.  * Portions created by the Initial Developer are Copyright (C) 2005
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *   Giorgio Maone <g.maone@informaction.com>
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. const Ci = Components.interfaces;
  39. const Cc = Components.classes;
  40. const Cr = Components.results;
  41.  
  42. // Constructor
  43.  
  44. function BrowserGlue() {
  45.   this._init();
  46.   this._profileStarted = false;
  47. }
  48.  
  49. BrowserGlue.prototype = {
  50.   _saveSession: false,
  51.  
  52.   QueryInterface: function(iid) 
  53.   {
  54.      xpcomCheckInterfaces(iid, kServiceIIds, Cr.NS_ERROR_NO_INTERFACE);
  55.      return this;
  56.   }
  57. ,
  58.   // nsIObserver implementation 
  59.   observe: function(subject, topic, data) 
  60.   {
  61.     switch(topic) {
  62.       case "xpcom-shutdown":
  63.         this._dispose();
  64.         break;
  65.       case "profile-before-change":
  66.         this._onProfileChange();
  67.         break;
  68.       case "profile-change-teardown": 
  69.         this._onProfileShutdown();
  70.         break;
  71.       case "final-ui-startup":
  72.         this._onProfileStartup();
  73.         break;
  74.       case "browser:purge-session-history":
  75.         // reset the console service's error buffer
  76.         const cs = Cc["@mozilla.org/consoleservice;1"].
  77.                    getService(Ci.nsIConsoleService);
  78.         cs.logStringMessage(null); // clear the console (in case it's open)
  79.         cs.reset();
  80.         break;
  81.       case "quit-application-requested":
  82.         this._onQuitRequest(subject, data);
  83.         break;
  84.       case "quit-application-granted":
  85.         if (this._saveSession) {
  86.           var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  87.                            getService(Ci.nsIPrefBranch);
  88.           prefBranch.setBoolPref("browser.sessionstore.resume_session_once", true);
  89.         }
  90.         break;
  91.     }
  92.   }
  93.   // initialization (called on application startup) 
  94.   _init: function() 
  95.   {
  96.     // observer registration
  97.     const osvr = Cc['@mozilla.org/observer-service;1'].
  98.                  getService(Ci.nsIObserverService);
  99.     osvr.addObserver(this, "profile-before-change", false);
  100.     osvr.addObserver(this, "profile-change-teardown", false);
  101.     osvr.addObserver(this, "xpcom-shutdown", false);
  102.     osvr.addObserver(this, "final-ui-startup", false);
  103.     osvr.addObserver(this, "browser:purge-session-history", false);
  104.     osvr.addObserver(this, "quit-application-requested", false);
  105.     osvr.addObserver(this, "quit-application-granted", false);
  106.   },
  107.  
  108.   // cleanup (called on application shutdown)
  109.   _dispose: function() 
  110.   {
  111.     // observer removal 
  112.     const osvr = Cc['@mozilla.org/observer-service;1'].
  113.                  getService(Ci.nsIObserverService);
  114.     osvr.removeObserver(this, "profile-before-change");
  115.     osvr.removeObserver(this, "profile-change-teardown");
  116.     osvr.removeObserver(this, "xpcom-shutdown");
  117.     osvr.removeObserver(this, "final-ui-startup");
  118.     osvr.removeObserver(this, "browser:purge-session-history");
  119.     osvr.removeObserver(this, "quit-application-requested");
  120.     osvr.removeObserver(this, "quit-application-granted");
  121.   },
  122.  
  123.   // profile startup handler (contains profile initialization routines)
  124.   _onProfileStartup: function() 
  125.   {
  126.     // check to see if the EULA must be shown on startup
  127.     try {
  128.       var mustDisplayEULA = true;
  129.       var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  130.                        getService(Ci.nsIPrefBranch);
  131.       var EULAVersion = prefBranch.getIntPref("browser.EULA.version");
  132.       mustDisplayEULA = !prefBranch.getBoolPref("browser.EULA." + EULAVersion + ".accepted");
  133.     } catch(ex) {
  134.     }
  135.  
  136. /*
  137.  * Songbird handles its own EULA so we don't want to try and show this
  138.  * one. The browser.EULA* preferences do not exist in songbird either.
  139.  */
  140.     mustDisplayEULA = false;
  141.     if (mustDisplayEULA) {
  142.       var ww2 = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  143.                 getService(Ci.nsIWindowWatcher);
  144.       ww2.openWindow(null, "chrome://browser/content/EULA.xul", 
  145.                      "_blank", "chrome,centerscreen,modal,resizable=yes", null);
  146.     }
  147.  
  148.     this.Sanitizer.onStartup();
  149.     // check if we're in safe mode
  150.     var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
  151.               QueryInterface(Ci.nsIXULRuntime);
  152.     if (app.inSafeMode) {
  153.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  154.                getService(Ci.nsIWindowWatcher);
  155.       ww.openWindow(null, "chrome://browser/content/safeMode.xul", 
  156.                     "_blank", "chrome,centerscreen,modal,resizable=no", null);
  157.     }
  158.  
  159.     // initialize Places
  160.     this._initPlaces();
  161.  
  162.     // indicate that the profile was initialized
  163.     this._profileStarted = true;
  164.   },
  165.  
  166.   _onProfileChange: function()
  167.   {
  168.     // this block is for code that depends on _onProfileStartup() having 
  169.     // been called.
  170.     if (this._profileStarted) {
  171.       // final places cleanup
  172.       this._shutdownPlaces();
  173.     }
  174.   },
  175.  
  176.   // profile shutdown handler (contains profile cleanup routines)
  177.   _onProfileShutdown: function() 
  178.   {
  179.     // here we enter last survival area, in order to avoid multiple
  180.     // "quit-application" notifications caused by late window closings
  181.     const appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
  182.                        getService(Ci.nsIAppStartup);
  183.     try {
  184.       appStartup.enterLastWindowClosingSurvivalArea();
  185.  
  186.       this.Sanitizer.onShutdown();
  187.  
  188.     } catch(ex) {
  189.     } finally {
  190.       appStartup.exitLastWindowClosingSurvivalArea();
  191.     }
  192.   },
  193.  
  194.   _onQuitRequest: function(aCancelQuit, aQuitType)
  195.   {
  196.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  197.              getService(Ci.nsIWindowMediator);
  198.     var windowcount = 0;
  199.     var pagecount = 0;
  200.     var browserEnum = wm.getEnumerator("navigator:browser");
  201.     while (browserEnum.hasMoreElements()) {
  202.       windowcount++;
  203.  
  204.       var browser = browserEnum.getNext();
  205.       var tabbrowser = browser.document.getElementById("content");
  206.       if (tabbrowser)
  207.         pagecount += tabbrowser.browsers.length;
  208.     }
  209.  
  210.     this._saveSession = false;
  211.     if (pagecount < 2)
  212.       return;
  213.  
  214.     if (aQuitType != "restart")
  215.       aQuitType = "quit";
  216.  
  217.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  218.                      getService(Ci.nsIPrefBranch);
  219.     var showPrompt = true;
  220.     try {
  221.       if (prefBranch.getIntPref("browser.startup.page") == 3 ||
  222.           prefBranch.getBoolPref("browser.sessionstore.resume_session_once"))
  223.         showPrompt = false;
  224.       else
  225.         showPrompt = prefBranch.getBoolPref("browser.warnOnQuit");
  226.     } catch (ex) {}
  227.  
  228.     var buttonChoice = 0;
  229.     if (showPrompt) {
  230.       var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
  231.                           getService(Ci.nsIStringBundleService);
  232.       var quitBundle = bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
  233.       var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
  234.  
  235.       var appName = brandBundle.GetStringFromName("brandShortName");
  236.       var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle",
  237.                                                               [appName], 1);
  238.       var quitTitle = quitBundle.GetStringFromName(aQuitType + "Title");
  239.       var cancelTitle = quitBundle.GetStringFromName("cancelTitle");
  240.       var saveTitle = quitBundle.GetStringFromName("saveTitle");
  241.       var neverAskText = quitBundle.GetStringFromName("neverAsk");
  242.  
  243.       var message;
  244.       if (aQuitType == "restart")
  245.         message = quitBundle.formatStringFromName("messageRestart",
  246.                                                   [appName], 1);
  247.       else if (windowcount == 1)
  248.         message = quitBundle.formatStringFromName("messageNoWindows",
  249.                                                   [appName], 1);
  250.       else
  251.         message = quitBundle.formatStringFromName("message",
  252.                                                   [appName], 1);
  253.  
  254.       var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  255.                           getService(Ci.nsIPromptService);
  256.  
  257.       var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
  258.                   promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
  259.                   promptService.BUTTON_POS_0_DEFAULT;
  260.       var neverAsk = {value:false};
  261.       if (aQuitType != "restart")
  262.         flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
  263.       buttonChoice = promptService.confirmEx(null, quitDialogTitle, message,
  264.                                    flags, quitTitle, cancelTitle, saveTitle,
  265.                                    neverAskText, neverAsk);
  266.  
  267.       switch (buttonChoice) {
  268.       case 0:
  269.         if (neverAsk.value)
  270.           prefBranch.setBoolPref("browser.warnOnQuit", false);
  271.         break;
  272.       case 1:
  273.         aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
  274.         aCancelQuit.data = true;
  275.         break;
  276.       case 2:
  277.         // could also set browser.warnOnQuit to false here,
  278.         // but not setting it is a little safer.
  279.         if (neverAsk.value)
  280.           prefBranch.setIntPref("browser.startup.page", 3);
  281.         break;
  282.       }
  283.  
  284.       this._saveSession = buttonChoice == 2;
  285.     }
  286.   },
  287.  
  288.   // returns the (cached) Sanitizer constructor
  289.   get Sanitizer() 
  290.   {
  291.     if(typeof(Sanitizer) != "function") { // we should dynamically load the script
  292.       Cc["@mozilla.org/moz/jssubscript-loader;1"].
  293.       getService(Ci.mozIJSSubScriptLoader).
  294.       loadSubScript("chrome://browser/content/sanitize.js", null);
  295.     }
  296.     return Sanitizer;
  297.   },
  298.  
  299.   /**
  300.    * Initialize Places
  301.    * - imports the bookmarks html file if bookmarks datastore is empty
  302.    */
  303.   _initPlaces: function bg__initPlaces() {
  304.     // we need to instantiate the history service before we check the 
  305.     // the browser.places.importBookmarksHTML pref, as 
  306.     // nsNavHistory::ForceMigrateBookmarksDB() will set that pref
  307.     // if we need to force a migration (due to a schema change)
  308.     var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
  309.                   getService(Ci.nsINavHistoryService);
  310.  
  311.     var importBookmarks = false;
  312.     try {
  313.       var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  314.                        getService(Ci.nsIPrefBranch);
  315.       importBookmarks = prefBranch.getBoolPref("browser.places.importBookmarksHTML");
  316.     } catch(ex) {}
  317.  
  318.     if (!importBookmarks)
  319.       return;
  320.  
  321.     var dirService = Cc["@mozilla.org/file/directory_service;1"].
  322.                      getService(Ci.nsIProperties);
  323.  
  324.     var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
  325.  
  326.     if (bookmarksFile.exists()) {
  327.       // import the file
  328.       try {
  329.         var importer = 
  330.           Cc["@mozilla.org/browser/places/import-export-service;1"].
  331.           getService(Ci.nsIPlacesImportExportService);
  332.         importer.importHTMLFromFile(bookmarksFile, true);
  333.       } catch(ex) {
  334.       } finally {
  335.         prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
  336.       }
  337.  
  338.       // backup pre-places bookmarks.html
  339.       // XXXtodo remove this before betas, after import/export is solid
  340.       var profDir = dirService.get("ProfD", Ci.nsILocalFile);
  341.       var bookmarksBackup = profDir.clone();
  342.       bookmarksBackup.append("bookmarks.preplaces.html");
  343.       if (!bookmarksBackup.exists()) {
  344.         // save old bookmarks.html file as bookmarks.preplaces.html
  345.         try {
  346.           bookmarksFile.copyTo(profDir, "bookmarks.preplaces.html");
  347.         } catch(ex) {
  348.           dump("nsBrowserGlue::_initPlaces(): copy of bookmarks.html to bookmarks.preplaces.html failed: " + ex + "\n");
  349.         }
  350.       }
  351.     }
  352.   },
  353.  
  354.   /**
  355.    * Places shut-down tasks
  356.    * - back up and archive bookmarks
  357.    */
  358.   _shutdownPlaces: function bg__shutdownPlaces() {
  359.     // backup bookmarks to bookmarks.html
  360.     var importer =
  361.       Cc["@mozilla.org/browser/places/import-export-service;1"].
  362.       getService(Ci.nsIPlacesImportExportService);
  363.     importer.backupBookmarksFile();
  364.   },
  365.   
  366.   // ------------------------------
  367.   // public nsIBrowserGlue members
  368.   // ------------------------------
  369.   
  370.   sanitize: function(aParentWindow) 
  371.   {
  372.     this.Sanitizer.sanitize(aParentWindow);
  373.   }
  374. }
  375.  
  376.  
  377. // XPCOM Scaffolding code
  378.  
  379. // component defined in this file
  380.  
  381. const kServiceName = "Firefox Browser Glue Service";
  382. const kServiceId = "{eab9012e-5f74-4cbc-b2b5-a590235513cc}";
  383. const kServiceCtrId = "@mozilla.org/browser/browserglue;1";
  384. const kServiceConstructor = BrowserGlue;
  385.  
  386. const kServiceCId = Components.ID(kServiceId);
  387.  
  388. // interfaces implemented by this component
  389. const kServiceIIds = [ 
  390.   Ci.nsIObserver,
  391.   Ci.nsISupports,
  392.   Ci.nsISupportsWeakReference,
  393.   Ci.nsIBrowserGlue
  394.   ];
  395.  
  396. // categories which this component is registered in
  397. const kServiceCats = ["app-startup"];
  398.  
  399. // Factory object
  400. const kServiceFactory = {
  401.   _instance: null,
  402.   createInstance: function (outer, iid) 
  403.   {
  404.     if (outer != null) throw Cr.NS_ERROR_NO_AGGREGATION;
  405.  
  406.     xpcomCheckInterfaces(iid, kServiceIIds, 
  407.                           Cr.NS_ERROR_INVALID_ARG);
  408.     return this._instance == null ?
  409.       this._instance = new kServiceConstructor() : this._instance;
  410.   }
  411. };
  412.  
  413. function xpcomCheckInterfaces(iid, iids, ex) {
  414.   for (var j = iids.length; j-- >0;) {
  415.     if (iid.equals(iids[j])) return true;
  416.   }
  417.   throw ex;
  418. }
  419.  
  420. // Module
  421.  
  422. var Module = {
  423.   registered: false,
  424.   
  425.   registerSelf: function(compMgr, fileSpec, location, type) 
  426.   {
  427.     if (!this.registered) {
  428.       compMgr.QueryInterface(Ci.nsIComponentRegistrar)
  429.              .registerFactoryLocation(kServiceCId,
  430.                                       kServiceName,
  431.                                       kServiceCtrId, 
  432.                                       fileSpec,
  433.                                       location, 
  434.                                       type);
  435.       const catman = Cc['@mozilla.org/categorymanager;1'].
  436.                      getService(Ci.nsICategoryManager);
  437.       var len = kServiceCats.length;
  438.       for (var j = 0; j < len; j++) {
  439.         catman.addCategoryEntry(kServiceCats[j],
  440.           kServiceCtrId, kServiceCtrId, true, true);
  441.       }
  442.       this.registered = true;
  443.     } 
  444.   },
  445.   
  446.   unregisterSelf: function(compMgr, fileSpec, location) 
  447.   {
  448.     compMgr.QueryInterface(Ci.nsIComponentRegistrar)
  449.            .unregisterFactoryLocation(kServiceCId, fileSpec);
  450.     const catman = Cc['@mozilla.org/categorymanager;1'].
  451.                    getService(Ci.nsICategoryManager);
  452.     var len = kServiceCats.length;
  453.     for (var j = 0; j < len; j++) {
  454.       catman.deleteCategoryEntry(kServiceCats[j], kServiceCtrId, true);
  455.     }
  456.   },
  457.   
  458.   getClassObject: function(compMgr, cid, iid) 
  459.   {
  460.     if(cid.equals(kServiceCId))
  461.       return kServiceFactory;
  462.     
  463.     throw Cr[
  464.       iid.equals(Ci.nsIFactory)
  465.       ? "NS_ERROR_NO_INTERFACE"
  466.       : "NS_ERROR_NOT_IMPLEMENTED"
  467.     ];
  468.     
  469.   },
  470.   
  471.   canUnload: function(compMgr) 
  472.   {
  473.     return true;
  474.   }
  475. };
  476.  
  477. // entrypoint
  478. function NSGetModule(compMgr, fileSpec) {
  479.   return Module;
  480. }
  481.