1 # ***** BEGIN LICENSE BLOCK *****
2 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 # The Original Code is the Browser Search Service.
16 # The Initial Developer of the Original Code is
18 # Portions created by the Initial Developer are Copyright (C) 2005
19 # the Initial Developer. All Rights Reserved.
22 # Giorgio Maone <g.maone@informaction.com>
23 # Seth Spitzer <sspitzer@mozilla.com>
24 # Asaf Romano <mano@mozilla.com>
26 # Alternatively, the contents of this file may be used under the terms of
27 # either the GNU General Public License Version 2 or later (the "GPL"), or
28 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 # in which case the provisions of the GPL or the LGPL are applicable instead
30 # of those above. If you wish to allow use of your version of this file only
31 # under the terms of either the GPL or the LGPL, and not to allow others to
32 # use your version of this file under the terms of the MPL, indicate your
33 # decision by deleting the provisions above and replace them with the notice
34 # and other provisions required by the GPL or the LGPL. If you do not delete
35 # the provisions above, a recipient may use your version of this file under
36 # the terms of any one of the MPL, the GPL or the LGPL.
38 # ***** END LICENSE BLOCK *****
40 const Ci = Components.interfaces;
41 const Cc = Components.classes;
42 const Cr = Components.results;
43 const Cu = Components.utils;
45 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
46 Cu.import("resource:///modules/distribution.js");
48 const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
50 // Check to see if bookmarks need backing up once per
51 // day on 1 hour idle.
52 const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60;
54 // Backup bookmarks once every 24 hours.
55 const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000;
58 const BrowserGlueServiceFactory = {
60 createInstance: function (outer, iid)
63 throw Components.results.NS_ERROR_NO_AGGREGATION;
64 return this._instance == null ?
65 this._instance = new BrowserGlue() : this._instance;
71 function BrowserGlue() {
75 BrowserGlue.prototype = {
79 this.__prefs = Cc["@mozilla.org/preferences-service;1"].
80 getService(Ci.nsIPrefBranch);
86 _setPrefToSaveSession: function()
88 var prefBranch = Cc["@mozilla.org/preferences-service;1"].
89 getService(Ci.nsIPrefBranch);
90 prefBranch.setBoolPref("browser.sessionstore.resume_session_once", true);
93 // nsIObserver implementation
94 observe: function(subject, topic, data)
97 case "xpcom-shutdown":
100 case "quit-application":
101 this._onProfileShutdown();
103 case "prefservice:after-app-defaults":
104 this._onAppDefaults();
106 case "final-ui-startup":
107 this._onProfileStartup();
109 case "sessionstore-windows-restored":
110 this._onBrowserStartup();
112 case "browser:purge-session-history":
113 // reset the console service's error buffer
114 const cs = Cc["@mozilla.org/consoleservice;1"].
115 getService(Ci.nsIConsoleService);
116 cs.logStringMessage(null); // clear the console (in case it's open)
119 case "quit-application-requested":
120 this._onQuitRequest(subject, data);
122 case "quit-application-granted":
123 if (this._saveSession) {
124 this._setPrefToSaveSession();
128 this._setPrefToSaveSession();
129 subject.QueryInterface(Ci.nsISupportsPRBool);
133 if (this.idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
134 // Back up bookmarks.
135 this._archiveBookmarks();
141 // initialization (called on application startup)
144 // observer registration
145 const osvr = Cc['@mozilla.org/observer-service;1'].
146 getService(Ci.nsIObserverService);
147 osvr.addObserver(this, "quit-application", false);
148 osvr.addObserver(this, "xpcom-shutdown", false);
149 osvr.addObserver(this, "prefservice:after-app-defaults", false);
150 osvr.addObserver(this, "final-ui-startup", false);
151 osvr.addObserver(this, "sessionstore-windows-restored", false);
152 osvr.addObserver(this, "browser:purge-session-history", false);
153 osvr.addObserver(this, "quit-application-requested", false);
154 osvr.addObserver(this, "quit-application-granted", false);
155 osvr.addObserver(this, "session-save", false);
158 // cleanup (called on application shutdown)
162 const osvr = Cc['@mozilla.org/observer-service;1'].
163 getService(Ci.nsIObserverService);
164 osvr.removeObserver(this, "quit-application");
165 osvr.removeObserver(this, "xpcom-shutdown");
166 osvr.removeObserver(this, "prefservice:after-app-defaults");
167 osvr.removeObserver(this, "final-ui-startup");
168 osvr.removeObserver(this, "sessionstore-windows-restored");
169 osvr.removeObserver(this, "browser:purge-session-history");
170 osvr.removeObserver(this, "quit-application-requested");
171 osvr.removeObserver(this, "quit-application-granted");
172 osvr.removeObserver(this, "session-save");
175 _onAppDefaults: function()
177 // apply distribution customizations (prefs)
178 // other customizations are applied in _onProfileStartup()
179 var distro = new DistributionCustomizer();
180 distro.applyPrefDefaults();
183 // profile startup handler (contains profile initialization routines)
184 _onProfileStartup: function()
186 this.Sanitizer.onStartup();
187 // check if we're in safe mode
188 var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
189 QueryInterface(Ci.nsIXULRuntime);
190 if (app.inSafeMode) {
191 var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
192 getService(Ci.nsIWindowWatcher);
193 ww.openWindow(null, "chrome://browser/content/safeMode.xul",
194 "_blank", "chrome,centerscreen,modal,resizable=no", null);
200 // apply distribution customizations
201 // prefs are applied in _onAppDefaults()
202 var distro = new DistributionCustomizer();
203 distro.applyCustomizations();
205 // handle any UI migration
208 const osvr = Cc['@mozilla.org/observer-service;1'].
209 getService(Ci.nsIObserverService);
210 osvr.notifyObservers(null, "browser-ui-startup-complete", "");
213 // profile shutdown handler (contains profile cleanup routines)
214 _onProfileShutdown: function()
216 this._shutdownPlaces();
217 this.idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
218 this.Sanitizer.onShutdown();
221 // Browser startup complete. All initial windows have opened.
222 _onBrowserStartup: function()
224 // Show about:rights notification, if needed.
225 if (this._shouldShowRights())
226 this._showRightsNotification();
228 var prefBranch = Cc["@mozilla.org/preferences-service;1"].
229 getService(Ci.nsIPrefBranch);
230 // If new add-ons were installed during startup open the add-ons manager.
231 if (prefBranch.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST)) {
232 var args = Cc["@mozilla.org/supports-array;1"].
233 createInstance(Ci.nsISupportsArray);
234 var str = Cc["@mozilla.org/supports-string;1"].
235 createInstance(Ci.nsISupportsString);
237 args.AppendElement(str);
238 var str = Cc["@mozilla.org/supports-string;1"].
239 createInstance(Ci.nsISupportsString);
240 str.data = prefBranch.getCharPref(PREF_EM_NEW_ADDONS_LIST);
241 args.AppendElement(str);
242 const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
243 const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
244 var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
245 getService(Ci.nsIWindowWatcher);
246 ww.openWindow(null, EMURL, "_blank", EMFEATURES, args);
247 prefBranch.clearUserPref(PREF_EM_NEW_ADDONS_LIST);
251 _onQuitRequest: function(aCancelQuit, aQuitType)
253 // If user has already dismissed quit request, then do nothing
254 if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
257 var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
258 getService(Ci.nsIWindowMediator);
262 var browserEnum = wm.getEnumerator("navigator:browser");
263 while (browserEnum.hasMoreElements()) {
266 var browser = browserEnum.getNext();
267 var tabbrowser = browser.document.getElementById("content");
269 pagecount += tabbrowser.browsers.length;
272 this._saveSession = false;
276 if (aQuitType != "restart")
279 var prefBranch = Cc["@mozilla.org/preferences-service;1"].
280 getService(Ci.nsIPrefBranch);
281 var showPrompt = true;
283 // browser.warnOnQuit is a hidden global boolean to override all quit prompts
284 // browser.warnOnRestart specifically covers app-initiated restarts where we restart the app
285 // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
287 var sessionWillBeSaved = prefBranch.getIntPref("browser.startup.page") == 3 ||
288 prefBranch.getBoolPref("browser.sessionstore.resume_session_once");
289 if (sessionWillBeSaved || !prefBranch.getBoolPref("browser.warnOnQuit"))
291 else if (aQuitType == "restart")
292 showPrompt = prefBranch.getBoolPref("browser.warnOnRestart");
294 showPrompt = prefBranch.getBoolPref("browser.tabs.warnOnClose");
300 var buttonChoice = 0;
301 var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
302 getService(Ci.nsIStringBundleService);
303 var quitBundle = bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
304 var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
306 var appName = brandBundle.GetStringFromName("brandShortName");
307 var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle",
311 if (aQuitType == "restart")
312 message = quitBundle.formatStringFromName("messageRestart",
314 else if (windowcount == 1)
315 message = quitBundle.formatStringFromName("messageNoWindows",
318 message = quitBundle.formatStringFromName("message",
321 var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
322 getService(Ci.nsIPromptService);
324 var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
325 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
326 promptService.BUTTON_POS_0_DEFAULT;
328 var neverAsk = {value:false};
329 var button0Title, button2Title;
330 var button1Title = quitBundle.GetStringFromName("cancelTitle");
331 var neverAskText = quitBundle.GetStringFromName("neverAsk");
333 if (aQuitType == "restart")
334 button0Title = quitBundle.GetStringFromName("restartTitle");
336 flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
337 button0Title = quitBundle.GetStringFromName("saveTitle");
338 button2Title = quitBundle.GetStringFromName("quitTitle");
341 buttonChoice = promptService.confirmEx(null, quitDialogTitle, message,
342 flags, button0Title, button1Title, button2Title,
343 neverAskText, neverAsk);
345 switch (buttonChoice) {
348 prefBranch.setBoolPref("browser.tabs.warnOnClose", false);
351 aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
352 aCancelQuit.data = true;
354 case 0: // Save & Quit
355 this._saveSession = true;
356 if (neverAsk.value) {
357 if (aQuitType == "restart")
358 prefBranch.setBoolPref("browser.warnOnRestart", false);
360 // always save state when shutting down
361 prefBranch.setIntPref("browser.startup.page", 3);
369 * _shouldShowRights - Determines if the user should be shown the
370 * about:rights notification. The notification should *not* be shown if
371 * we've already shown the current version, or if the override pref says to
372 * never show it. The notification *should* be shown if it's never been seen
373 * before, if a newer version is available, or if the override pref says to
376 _shouldShowRights : function () {
377 // Look for an unconditional override pref. If set, do what it says.
378 // (true --> never show, false --> always show)
380 return !this._prefs.getBoolPref("browser.rights.override");
382 // Ditto, for the legacy EULA pref.
384 return !this._prefs.getBoolPref("browser.EULA.override");
387 #ifndef OFFICIAL_BUILD
388 // Non-official builds shouldn't shouldn't show the notification.
392 // Look to see if the user has seen the current version or not.
393 var currentVersion = this._prefs.getIntPref("browser.rights.version");
395 return !this._prefs.getBoolPref("browser.rights." + currentVersion + ".shown");
398 // Legacy: If the user accepted a EULA, we won't annoy them with the
399 // equivalent about:rights page until the version changes.
401 return !this._prefs.getBoolPref("browser.EULA." + currentVersion + ".accepted");
404 // We haven't shown the notification before, so do so now.
408 _showRightsNotification : function () {
409 // Stick the notification onto the selected tab of the active browser window.
410 var win = this._getMostRecentBrowserWindow();
411 var browser = win.gBrowser; // for closure in notification bar callback
412 var notifyBox = browser.getNotificationBox();
414 var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
415 getService(Ci.nsIStringBundleService);
416 var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
417 var rightsBundle = bundleService.createBundle("chrome://browser/locale/aboutRights.properties");
419 var buttonLabel = rightsBundle.GetStringFromName("buttonLabel");
420 var buttonAccessKey = rightsBundle.GetStringFromName("buttonAccessKey");
421 var productName = brandBundle.GetStringFromName("brandFullName");
422 var notifyText = rightsBundle.formatStringFromName("notifyText", [productName], 1);
427 accessKey: buttonAccessKey,
429 callback: function(aNotificationBar, aButton) {
430 browser.selectedTab = browser.addTab("about:rights");
435 // Set pref to indicate we've shown the notification.
436 var currentVersion = this._prefs.getIntPref("browser.rights.version");
437 this._prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);
439 notifyBox.appendNotification(notifyText, "about-rights", null, notifyBox.PRIORITY_INFO_LOW, buttons);
442 // returns the (cached) Sanitizer constructor
445 if(typeof(Sanitizer) != "function") { // we should dynamically load the script
446 Cc["@mozilla.org/moz/jssubscript-loader;1"].
447 getService(Ci.mozIJSSubScriptLoader).
448 loadSubScript("chrome://browser/content/sanitize.js", null);
455 if (!this._idleService)
456 this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
457 getService(Ci.nsIIdleService);
458 return this._idleService;
463 * - imports the bookmarks html file if bookmarks datastore is empty
465 * These prefs are set by the backend services upon creation (or recreation)
467 * - browser.places.importBookmarksHTML
468 * Set to false by the history service to indicate we need to re-import.
469 * - browser.places.smartBookmarksVersion
470 * Set during HTML import to indicate that Smart Bookmarks were created.
471 * Set to -1 to disable Smart Bookmarks creation.
472 * Set to 0 to restore current Smart Bookmarks.
474 * These prefs are set up by the frontend:
475 * - browser.bookmarks.restore_default_bookmarks
476 * Set to true by safe-mode dialog to indicate we must restore default
479 _initPlaces: function bg__initPlaces() {
480 // we need to instantiate the history service before checking
481 // the browser.places.importBookmarksHTML pref, as
482 // nsNavHistory::ForceMigrateBookmarksDB() will set that pref
483 // if we need to force a migration (due to a schema change)
484 var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
485 getService(Ci.nsINavHistoryService);
487 var prefBranch = Cc["@mozilla.org/preferences-service;1"].
488 getService(Ci.nsIPrefBranch);
490 var importBookmarks = false;
491 var restoreDefaultBookmarks = false;
493 restoreDefaultBookmarks = prefBranch.getBoolPref("browser.bookmarks.restore_default_bookmarks");
496 if (restoreDefaultBookmarks) {
497 // Ensure that we already have a bookmarks backup for today
498 this._archiveBookmarks();
499 // we will restore bookmarks from html
500 importBookmarks = true;
504 importBookmarks = prefBranch.getBoolPref("browser.places.importBookmarksHTML");
508 if (!importBookmarks) {
509 // Call it here for Fx3 profiles created before the Places folder
510 // has been added, otherwise it's called during import.
511 this.ensurePlacesDefaultQueriesInitialized();
515 Cu.import("resource://gre/modules/utils.js");
516 var bookmarksFile = PlacesUtils.getMostRecentBackup();
518 if (!restoreDefaultBookmarks &&
519 bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
520 // restore a JSON backup
521 PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
524 // if there's no JSON backup or we are restoring default bookmarks
526 // ensurePlacesDefaultQueriesInitialized() is called by import.
527 prefBranch.setIntPref("browser.places.smartBookmarksVersion", 0);
529 var dirService = Cc["@mozilla.org/file/directory_service;1"].
530 getService(Ci.nsIProperties);
532 var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
533 if (restoreDefaultBookmarks || !bookmarksFile.exists()) {
534 // get bookmarks.html file from default profile folder
535 bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
536 bookmarksFile.append("bookmarks.html");
541 var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
542 getService(Ci.nsIPlacesImportExportService);
543 importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
545 // Report the error, but ignore it.
548 prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
549 if (restoreDefaultBookmarks)
550 prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks",
555 // Initialize bookmark archiving on idle.
556 // Once a day, either on idle or shutdown, bookmarks are backed up.
557 this.idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
561 * Places shut-down tasks
562 * - back up and archive bookmarks
563 * - export bookmarks as HTML, if so configured
565 * Note: quit-application-granted notification is received twice
566 * so replace this method with a no-op when first called.
568 _shutdownPlaces: function bg__shutdownPlaces() {
569 // Backup and archive Places bookmarks.
570 this._archiveBookmarks();
572 // Backup bookmarks to bookmarks.html to support apps that depend
573 // on the legacy format.
574 var prefs = Cc["@mozilla.org/preferences-service;1"].
575 getService(Ci.nsIPrefBranch);
576 var autoExportHTML = false;
578 autoExportHTML = prefs.getBoolPref("browser.bookmarks.autoExportHTML");
580 Components.utils.reportError(ex);
583 if (autoExportHTML) {
584 Cc["@mozilla.org/browser/places/import-export-service;1"].
585 getService(Ci.nsIPlacesImportExportService).
586 backupBookmarksFile();
591 * Back up and archive bookmarks
593 _archiveBookmarks: function nsBrowserGlue__archiveBookmarks() {
594 Cu.import("resource://gre/modules/utils.js");
596 var lastBackup = PlacesUtils.getMostRecentBackup();
598 // Backup bookmarks if there aren't any backups or
599 // they haven't been backed up in the last 24 hrs.
601 Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) {
603 var prefs = Cc["@mozilla.org/preferences-service;1"].
604 getService(Ci.nsIPrefBranch);
606 maxBackups = prefs.getIntPref("browser.bookmarks.max_backups");
609 PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
613 _migrateUI: function bg__migrateUI() {
614 var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
618 migration = prefBranch.getIntPref("browser.migration.version");
621 if (migration == 0) {
622 // this code should always migrate pre-FF3 profiles to the current UI state
624 // grab the localstore.rdf and make changes needed for new UI
625 this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
626 this._dataSource = this._rdf.GetDataSource("rdf:local-store");
629 let currentsetResource = this._rdf.GetResource("currentset");
630 let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
631 for (let i = 0; i < toolbars.length; i++) {
632 let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]);
633 let currentset = this._getPersist(toolbar, currentsetResource);
635 // toolbar isn't customized
637 // new button is in the defaultset, nothing to migrate
641 if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset))
642 // new button is already there, nothing to migrate
644 if (/(?:^|,)back-button(?:$|,)/.test(currentset)) {
645 let newset = currentset.replace(/(^|,)back-button($|,)/,
646 "$1unified-back-forward-button,back-button$2")
647 this._setPersist(toolbar, currentsetResource, newset);
653 // force the RDF to be saved
655 this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
657 // free up the RDF service
659 this._dataSource = null;
661 // update the migration version
662 prefBranch.setIntPref("browser.migration.version", 1);
666 _getPersist: function bg__getPersist(aSource, aProperty) {
667 var target = this._dataSource.GetTarget(aSource, aProperty, true);
668 if (target instanceof Ci.nsIRDFLiteral)
673 _setPersist: function bg__setPersist(aSource, aProperty, aTarget) {
676 var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true);
679 this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget));
681 this._dataSource.Unassert(aSource, aProperty, oldTarget);
684 this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
690 // ------------------------------
691 // public nsIBrowserGlue members
692 // ------------------------------
694 sanitize: function(aParentWindow)
696 this.Sanitizer.sanitize(aParentWindow);
699 ensurePlacesDefaultQueriesInitialized: function() {
700 const SMART_BOOKMARKS_VERSION = 1;
701 const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
702 const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
704 // XXX should this be a pref? see bug #399268
705 const MAX_RESULTS = 10;
707 var prefBranch = Cc["@mozilla.org/preferences-service;1"].
708 getService(Ci.nsIPrefBranch);
710 // get current smart bookmarks version
711 // By default, if the pref is not set up, we must create Smart Bookmarks
712 var smartBookmarksCurrentVersion = 0;
714 smartBookmarksCurrentVersion = prefBranch.getIntPref(SMART_BOOKMARKS_PREF);
717 // bail out if we don't have to create or update Smart Bookmarks
718 if (smartBookmarksCurrentVersion == -1 ||
719 smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION)
722 var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
723 getService(Ci.nsINavBookmarksService);
724 var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
725 getService(Ci.nsIAnnotationService);
728 _placesBundle: Cc["@mozilla.org/intl/stringbundle;1"].
729 getService(Ci.nsIStringBundleService).
730 createBundle("chrome://browser/locale/places/places.properties"),
732 _uri: function(aSpec) {
733 return Cc["@mozilla.org/network/io-service;1"].
734 getService(Ci.nsIIOService).
735 newURI(aSpec, null, null);
738 runBatched: function() {
739 var smartBookmarks = [];
740 var bookmarksMenuIndex = 0;
741 var bookmarksToolbarIndex = 0;
744 var smart = {queryId: "MostVisited", // don't change this
746 title: this._placesBundle.GetStringFromName("mostVisitedTitle"),
747 uri: this._uri("place:queryType=" +
748 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
750 Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
751 "&maxResults=" + MAX_RESULTS),
752 parent: bmsvc.toolbarFolder,
753 position: bookmarksToolbarIndex++};
754 smartBookmarks.push(smart);
756 // RECENTLY BOOKMARKED
757 smart = {queryId: "RecentlyBookmarked", // don't change this
759 title: this._placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
760 uri: this._uri("place:folder=BOOKMARKS_MENU" +
761 "&folder=UNFILED_BOOKMARKS" +
764 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
766 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
767 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
768 "&maxResults=" + MAX_RESULTS +
769 "&excludeQueries=1"),
770 parent: bmsvc.bookmarksMenuFolder,
771 position: bookmarksMenuIndex++};
772 smartBookmarks.push(smart);
775 smart = {queryId: "RecentTags", // don't change this
777 title: this._placesBundle.GetStringFromName("recentTagsTitle"),
778 uri: this._uri("place:"+
780 Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
782 Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
783 "&maxResults=" + MAX_RESULTS),
784 parent: bmsvc.bookmarksMenuFolder,
785 position: bookmarksMenuIndex++};
786 smartBookmarks.push(smart);
788 var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
789 // set current itemId, parent and position if Smart Bookmark exists
790 for each(var itemId in smartBookmarkItemIds) {
791 var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
792 for (var i = 0; i < smartBookmarks.length; i++){
793 if (smartBookmarks[i].queryId == queryId) {
794 smartBookmarks[i].itemId = itemId;
795 smartBookmarks[i].parent = bmsvc.getFolderIdForItem(itemId);
796 smartBookmarks[i].position = bmsvc.getItemIndex(itemId);
797 // remove current item, since it will be replaced
798 bmsvc.removeItem(itemId);
801 // We don't remove old Smart Bookmarks because user could still
802 // find them useful, or could have personalized them.
803 // Instead we remove the Smart Bookmark annotation.
804 if (i == smartBookmarks.length - 1)
805 annosvc.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
809 // create smart bookmarks
810 for each(var smartBookmark in smartBookmarks) {
811 smartBookmark.itemId = bmsvc.insertBookmark(smartBookmark.parent,
813 smartBookmark.position,
814 smartBookmark.title);
815 annosvc.setItemAnnotation(smartBookmark.itemId,
816 SMART_BOOKMARKS_ANNO, smartBookmark.queryId,
817 0, annosvc.EXPIRE_NEVER);
820 // If we are creating all Smart Bookmarks from ground up, add a
821 // separator below them in the bookmarks menu.
822 if (smartBookmarkItemIds.length == 0)
823 bmsvc.insertSeparator(bmsvc.bookmarksMenuFolder, bookmarksMenuIndex);
828 bmsvc.runInBatchMode(callback, null);
831 Components.utils.reportError(ex);
834 prefBranch.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION);
835 prefBranch.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
841 #define BROKEN_WM_Z_ORDER
845 #define BROKEN_WM_Z_ORDER
848 // this returns the most recent non-popup browser window
849 _getMostRecentBrowserWindow : function ()
851 var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
852 getService(Components.interfaces.nsIWindowMediator);
854 #ifdef BROKEN_WM_Z_ORDER
855 var win = wm.getMostRecentWindow("navigator:browser", true);
857 // if we're lucky, this isn't a popup, and we can just return this
858 if (win && win.document.documentElement.getAttribute("chromehidden")) {
860 var windowList = wm.getEnumerator("navigator:browser", true);
861 // this is oldest to newest, so this gets a bit ugly
862 while (windowList.hasMoreElements()) {
863 var nextWin = windowList.getNext();
864 if (!nextWin.document.documentElement.getAttribute("chromehidden"))
869 var windowList = wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
870 if (!windowList.hasMoreElements())
873 var win = windowList.getNext();
874 while (win.document.documentElement.getAttribute("chromehidden")) {
875 if (!windowList.hasMoreElements())
878 win = windowList.getNext();
886 classDescription: "Firefox Browser Glue Service",
887 classID: Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
888 contractID: "@mozilla.org/browser/browserglue;1",
890 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
891 Ci.nsISupportsWeakReference,
894 // redefine the default factory for XPCOMUtils
895 _xpcom_factory: BrowserGlueServiceFactory,
897 // get this contractID registered for certain categories via XPCOMUtils
899 // make BrowserGlue a startup observer
900 { category: "app-startup", service: true }
904 //module initialization
905 function NSGetModule(aCompMgr, aFileSpec) {
906 return XPCOMUtils.generateModule([BrowserGlue]);