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 = {
78 _setPrefToSaveSession: function()
80 var prefBranch
= Cc
["@mozilla.org/preferences-service;1"].
81 getService(Ci
.nsIPrefBranch
);
82 prefBranch
.setBoolPref("browser.sessionstore.resume_session_once", true);
85 // nsIObserver implementation
86 observe: function(subject
, topic
, data
)
89 case "xpcom-shutdown":
92 case "quit-application":
93 this._onProfileShutdown();
95 case "prefservice:after-app-defaults":
96 this._onAppDefaults();
98 case "final-ui-startup":
99 this._onProfileStartup();
101 case "sessionstore-windows-restored":
102 this._onBrowserStartup();
104 case "browser:purge-session-history":
105 // reset the console service's error buffer
106 const cs
= Cc
["@mozilla.org/consoleservice;1"].
107 getService(Ci
.nsIConsoleService
);
108 cs
.logStringMessage(null); // clear the console (in case it's open)
111 case "quit-application-requested":
112 this._onQuitRequest(subject
, data
);
114 case "quit-application-granted":
115 if (this._saveSession
) {
116 this._setPrefToSaveSession();
120 this._setPrefToSaveSession();
121 subject
.QueryInterface(Ci
.nsISupportsPRBool
);
125 if (this.idleService
.idleTime
> BOOKMARKS_ARCHIVE_IDLE_TIME
* 1000) {
126 // Back up bookmarks.
127 this._archiveBookmarks();
133 // initialization (called on application startup)
136 // observer registration
137 const osvr
= Cc
['@mozilla.org/observer-service;1'].
138 getService(Ci
.nsIObserverService
);
139 osvr
.addObserver(this, "quit-application", false);
140 osvr
.addObserver(this, "xpcom-shutdown", false);
141 osvr
.addObserver(this, "prefservice:after-app-defaults", false);
142 osvr
.addObserver(this, "final-ui-startup", false);
143 osvr
.addObserver(this, "sessionstore-windows-restored", false);
144 osvr
.addObserver(this, "browser:purge-session-history", false);
145 osvr
.addObserver(this, "quit-application-requested", false);
146 osvr
.addObserver(this, "quit-application-granted", false);
147 osvr
.addObserver(this, "session-save", false);
150 // cleanup (called on application shutdown)
154 const osvr
= Cc
['@mozilla.org/observer-service;1'].
155 getService(Ci
.nsIObserverService
);
156 osvr
.removeObserver(this, "quit-application");
157 osvr
.removeObserver(this, "xpcom-shutdown");
158 osvr
.removeObserver(this, "prefservice:after-app-defaults");
159 osvr
.removeObserver(this, "final-ui-startup");
160 osvr
.removeObserver(this, "sessionstore-windows-restored");
161 osvr
.removeObserver(this, "browser:purge-session-history");
162 osvr
.removeObserver(this, "quit-application-requested");
163 osvr
.removeObserver(this, "quit-application-granted");
164 osvr
.removeObserver(this, "session-save");
167 _onAppDefaults: function()
169 // apply distribution customizations (prefs)
170 // other customizations are applied in _onProfileStartup()
171 var distro
= new DistributionCustomizer();
172 distro
.applyPrefDefaults();
175 // profile startup handler (contains profile initialization routines)
176 _onProfileStartup: function()
178 // Check to see if the EULA must be shown on startup
180 var prefBranch
= Cc
["@mozilla.org/preferences-service;1"].
181 getService(Ci
.nsIPrefBranch
);
182 var mustDisplayEULA
= false;
184 mustDisplayEULA
= !prefBranch
.getBoolPref("browser.EULA.override");
186 // Pref might not exist
189 // Make sure it hasn't already been accepted
190 if (mustDisplayEULA
) {
192 var EULAVersion
= prefBranch
.getIntPref("browser.EULA.version");
193 mustDisplayEULA
= !prefBranch
.getBoolPref("browser.EULA." + EULAVersion
+ ".accepted");
198 if (mustDisplayEULA
) {
199 var ww2
= Cc
["@mozilla.org/embedcomp/window-watcher;1"].
200 getService(Ci
.nsIWindowWatcher
);
201 ww2
.openWindow(null, "chrome://browser/content/EULA.xul",
202 "_blank", "chrome,centerscreen,modal,resizable=yes", null);
205 this.Sanitizer
.onStartup();
206 // check if we're in safe mode
207 var app
= Cc
["@mozilla.org/xre/app-info;1"].getService(Ci
.nsIXULAppInfo
).
208 QueryInterface(Ci
.nsIXULRuntime
);
209 if (app
.inSafeMode
) {
210 var ww
= Cc
["@mozilla.org/embedcomp/window-watcher;1"].
211 getService(Ci
.nsIWindowWatcher
);
212 ww
.openWindow(null, "chrome://browser/content/safeMode.xul",
213 "_blank", "chrome,centerscreen,modal,resizable=no", null);
219 // apply distribution customizations
220 // prefs are applied in _onAppDefaults()
221 var distro
= new DistributionCustomizer();
222 distro
.applyCustomizations();
224 // handle any UI migration
228 // profile shutdown handler (contains profile cleanup routines)
229 _onProfileShutdown: function()
231 this._shutdownPlaces();
232 this.idleService
.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME
);
233 this.Sanitizer
.onShutdown();
236 // Browser startup complete. All initial windows have opened.
237 _onBrowserStartup: function()
239 var prefBranch
= Cc
["@mozilla.org/preferences-service;1"].
240 getService(Ci
.nsIPrefBranch
);
241 // If new add-ons were installed during startup open the add-ons manager.
242 if (prefBranch
.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST
)) {
243 var args
= Cc
["@mozilla.org/supports-array;1"].
244 createInstance(Ci
.nsISupportsArray
);
245 var str
= Cc
["@mozilla.org/supports-string;1"].
246 createInstance(Ci
.nsISupportsString
);
248 args
.AppendElement(str
);
249 var str
= Cc
["@mozilla.org/supports-string;1"].
250 createInstance(Ci
.nsISupportsString
);
251 str
.data
= prefBranch
.getCharPref(PREF_EM_NEW_ADDONS_LIST
);
252 args
.AppendElement(str
);
253 const EMURL
= "chrome://mozapps/content/extensions/extensions.xul";
254 const EMFEATURES
= "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
255 var ww
= Cc
["@mozilla.org/embedcomp/window-watcher;1"].
256 getService(Ci
.nsIWindowWatcher
);
257 ww
.openWindow(null, EMURL
, "_blank", EMFEATURES
, args
);
258 prefBranch
.clearUserPref(PREF_EM_NEW_ADDONS_LIST
);
262 _onQuitRequest: function(aCancelQuit
, aQuitType
)
264 // If user has already dismissed quit request, then do nothing
265 if ((aCancelQuit
instanceof Ci
.nsISupportsPRBool
) && aCancelQuit
.data
)
268 var wm
= Cc
["@mozilla.org/appshell/window-mediator;1"].
269 getService(Ci
.nsIWindowMediator
);
273 var browserEnum
= wm
.getEnumerator("navigator:browser");
274 while (browserEnum
.hasMoreElements()) {
277 var browser
= browserEnum
.getNext();
278 var tabbrowser
= browser
.document
.getElementById("content");
280 pagecount
+= tabbrowser
.browsers
.length
;
283 this._saveSession
= false;
287 if (aQuitType
!= "restart")
290 var prefBranch
= Cc
["@mozilla.org/preferences-service;1"].
291 getService(Ci
.nsIPrefBranch
);
292 var showPrompt
= true;
294 // browser.warnOnQuit is a hidden global boolean to override all quit prompts
295 // browser.warnOnRestart specifically covers app-initiated restarts where we restart the app
296 // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
298 var sessionWillBeSaved
= prefBranch
.getIntPref("browser.startup.page") == 3 ||
299 prefBranch
.getBoolPref("browser.sessionstore.resume_session_once");
300 if (sessionWillBeSaved
|| !prefBranch
.getBoolPref("browser.warnOnQuit"))
302 else if (aQuitType
== "restart")
303 showPrompt
= prefBranch
.getBoolPref("browser.warnOnRestart");
305 showPrompt
= prefBranch
.getBoolPref("browser.tabs.warnOnClose");
311 var buttonChoice
= 0;
312 var bundleService
= Cc
["@mozilla.org/intl/stringbundle;1"].
313 getService(Ci
.nsIStringBundleService
);
314 var quitBundle
= bundleService
.createBundle("chrome://browser/locale/quitDialog.properties");
315 var brandBundle
= bundleService
.createBundle("chrome://branding/locale/brand.properties");
317 var appName
= brandBundle
.GetStringFromName("brandShortName");
318 var quitDialogTitle
= quitBundle
.formatStringFromName(aQuitType
+ "DialogTitle",
322 if (aQuitType
== "restart")
323 message
= quitBundle
.formatStringFromName("messageRestart",
325 else if (windowcount
== 1)
326 message
= quitBundle
.formatStringFromName("messageNoWindows",
329 message
= quitBundle
.formatStringFromName("message",
332 var promptService
= Cc
["@mozilla.org/embedcomp/prompt-service;1"].
333 getService(Ci
.nsIPromptService
);
335 var flags
= promptService
.BUTTON_TITLE_IS_STRING
* promptService
.BUTTON_POS_0
+
336 promptService
.BUTTON_TITLE_IS_STRING
* promptService
.BUTTON_POS_1
+
337 promptService
.BUTTON_POS_0_DEFAULT
;
339 var neverAsk
= {value
:false};
340 var button0Title
, button2Title
;
341 var button1Title
= quitBundle
.GetStringFromName("cancelTitle");
342 var neverAskText
= quitBundle
.GetStringFromName("neverAsk");
344 if (aQuitType
== "restart")
345 button0Title
= quitBundle
.GetStringFromName("restartTitle");
347 flags
+= promptService
.BUTTON_TITLE_IS_STRING
* promptService
.BUTTON_POS_2
;
348 button0Title
= quitBundle
.GetStringFromName("saveTitle");
349 button2Title
= quitBundle
.GetStringFromName("quitTitle");
352 buttonChoice
= promptService
.confirmEx(null, quitDialogTitle
, message
,
353 flags
, button0Title
, button1Title
, button2Title
,
354 neverAskText
, neverAsk
);
356 switch (buttonChoice
) {
359 prefBranch
.setBoolPref("browser.tabs.warnOnClose", false);
362 aCancelQuit
.QueryInterface(Ci
.nsISupportsPRBool
);
363 aCancelQuit
.data
= true;
365 case 0: // Save & Quit
366 this._saveSession
= true;
367 if (neverAsk
.value
) {
368 if (aQuitType
== "restart")
369 prefBranch
.setBoolPref("browser.warnOnRestart", false);
371 // always save state when shutting down
372 prefBranch
.setIntPref("browser.startup.page", 3);
379 // returns the (cached) Sanitizer constructor
382 if(typeof(Sanitizer
) != "function") { // we should dynamically load the script
383 Cc
["@mozilla.org/moz/jssubscript-loader;1"].
384 getService(Ci
.mozIJSSubScriptLoader
).
385 loadSubScript("chrome://browser/content/sanitize.js", null);
392 if (!this._idleService
)
393 this._idleService
= Cc
["@mozilla.org/widget/idleservice;1"].
394 getService(Ci
.nsIIdleService
);
395 return this._idleService
;
400 * - imports the bookmarks html file if bookmarks datastore is empty
402 * These prefs are set by the backend services upon creation (or recreation)
404 * - browser.places.importBookmarksHTML
405 * Set to false by the history service to indicate we need to re-import.
406 * - browser.places.smartBookmarksVersion
407 * Set during HTML import to indicate that Smart Bookmarks were created.
408 * Set to -1 to disable Smart Bookmarks creation.
409 * Set to 0 to restore current Smart Bookmarks.
411 * These prefs are set up by the frontend:
412 * - browser.bookmarks.restore_default_bookmarks
413 * Set to true by safe-mode dialog to indicate we must restore default
416 _initPlaces
: function bg__initPlaces() {
417 // we need to instantiate the history service before checking
418 // the browser.places.importBookmarksHTML pref, as
419 // nsNavHistory::ForceMigrateBookmarksDB() will set that pref
420 // if we need to force a migration (due to a schema change)
421 var histsvc
= Cc
["@mozilla.org/browser/nav-history-service;1"].
422 getService(Ci
.nsINavHistoryService
);
424 var prefBranch
= Cc
["@mozilla.org/preferences-service;1"].
425 getService(Ci
.nsIPrefBranch
);
427 var importBookmarks
= false;
428 var restoreDefaultBookmarks
= false;
430 restoreDefaultBookmarks
= prefBranch
.getBoolPref("browser.bookmarks.restore_default_bookmarks");
433 if (restoreDefaultBookmarks
) {
434 // Ensure that we already have a bookmarks backup for today
435 this._archiveBookmarks();
436 // we will restore bookmarks from html
437 importBookmarks
= true;
441 importBookmarks
= prefBranch
.getBoolPref("browser.places.importBookmarksHTML");
445 if (!importBookmarks
) {
446 // Call it here for Fx3 profiles created before the Places folder
447 // has been added, otherwise it's called during import.
448 this.ensurePlacesDefaultQueriesInitialized();
452 Cu
.import("resource://gre/modules/utils.js");
453 var bookmarksFile
= PlacesUtils
.getMostRecentBackup();
455 if (!restoreDefaultBookmarks
&&
456 bookmarksFile
&& bookmarksFile
.leafName
.match("\.json$")) {
457 // restore a JSON backup
458 PlacesUtils
.restoreBookmarksFromJSONFile(bookmarksFile
);
461 // if there's no JSON backup or we are restoring default bookmarks
463 // ensurePlacesDefaultQueriesInitialized() is called by import.
464 prefBranch
.setIntPref("browser.places.smartBookmarksVersion", 0);
466 var dirService
= Cc
["@mozilla.org/file/directory_service;1"].
467 getService(Ci
.nsIProperties
);
469 var bookmarksFile
= dirService
.get("BMarks", Ci
.nsILocalFile
);
470 if (restoreDefaultBookmarks
|| !bookmarksFile
.exists()) {
471 // get bookmarks.html file from default profile folder
472 bookmarksFile
= dirService
.get("profDef", Ci
.nsILocalFile
);
473 bookmarksFile
.append("bookmarks.html");
478 var importer
= Cc
["@mozilla.org/browser/places/import-export-service;1"].
479 getService(Ci
.nsIPlacesImportExportService
);
480 importer
.importHTMLFromFile(bookmarksFile
, true /* overwrite existing */);
482 // Report the error, but ignore it.
485 prefBranch
.setBoolPref("browser.places.importBookmarksHTML", false);
486 if (restoreDefaultBookmarks
)
487 prefBranch
.setBoolPref("browser.bookmarks.restore_default_bookmarks",
492 // Initialize bookmark archiving on idle.
493 // Once a day, either on idle or shutdown, bookmarks are backed up.
494 this.idleService
.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME
);
498 * Places shut-down tasks
499 * - back up and archive bookmarks
500 * - export bookmarks as HTML, if so configured
502 * Note: quit-application-granted notification is received twice
503 * so replace this method with a no-op when first called.
505 _shutdownPlaces
: function bg__shutdownPlaces() {
506 // Backup and archive Places bookmarks.
507 this._archiveBookmarks();
509 // Backup bookmarks to bookmarks.html to support apps that depend
510 // on the legacy format.
511 var prefs
= Cc
["@mozilla.org/preferences-service;1"].
512 getService(Ci
.nsIPrefBranch
);
513 var autoExportHTML
= false;
515 autoExportHTML
= prefs
.getBoolPref("browser.bookmarks.autoExportHTML");
517 Components
.utils
.reportError(ex
);
520 if (autoExportHTML
) {
521 Cc
["@mozilla.org/browser/places/import-export-service;1"].
522 getService(Ci
.nsIPlacesImportExportService
).
523 backupBookmarksFile();
528 * Back up and archive bookmarks
530 _archiveBookmarks
: function nsBrowserGlue__archiveBookmarks() {
531 Cu
.import("resource://gre/modules/utils.js");
533 var lastBackup
= PlacesUtils
.getMostRecentBackup();
535 // Backup bookmarks if there aren't any backups or
536 // they haven't been backed up in the last 24 hrs.
538 Date
.now() - lastBackup
.lastModifiedTime
> BOOKMARKS_ARCHIVE_INTERVAL
) {
540 var prefs
= Cc
["@mozilla.org/preferences-service;1"].
541 getService(Ci
.nsIPrefBranch
);
543 maxBackups
= prefs
.getIntPref("browser.bookmarks.max_backups");
546 PlacesUtils
.archiveBookmarksFile(maxBackups
, false /* don't force */);
550 _migrateUI
: function bg__migrateUI() {
551 var prefBranch
= Cc
["@mozilla.org/preferences-service;1"].getService(Ci
.nsIPrefBranch
);
555 migration
= prefBranch
.getIntPref("browser.migration.version");
558 if (migration
== 0) {
559 // this code should always migrate pre-FF3 profiles to the current UI state
561 // grab the localstore.rdf and make changes needed for new UI
562 this._rdf
= Cc
["@mozilla.org/rdf/rdf-service;1"].getService(Ci
.nsIRDFService
);
563 this._dataSource
= this._rdf
.GetDataSource("rdf:local-store");
566 let currentsetResource
= this._rdf
.GetResource("currentset");
567 let toolbars
= ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
568 for (let i
= 0; i
< toolbars
.length
; i
++) {
569 let toolbar
= this._rdf
.GetResource("chrome://browser/content/browser.xul#" + toolbars
[i
]);
570 let currentset
= this._getPersist(toolbar
, currentsetResource
);
572 // toolbar isn't customized
574 // new button is in the defaultset, nothing to migrate
578 if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset
))
579 // new button is already there, nothing to migrate
581 if (/(?:^|,)back-button(?:$|,)/.test(currentset
)) {
582 let newset
= currentset
.replace(/(^|,)back-button($|,)/,
583 "$1unified-back-forward-button,back-button$2")
584 this._setPersist(toolbar
, currentsetResource
, newset
);
590 // force the RDF to be saved
592 this._dataSource
.QueryInterface(Ci
.nsIRDFRemoteDataSource
).Flush();
594 // free up the RDF service
596 this._dataSource
= null;
598 // update the migration version
599 prefBranch
.setIntPref("browser.migration.version", 1);
603 _getPersist
: function bg__getPersist(aSource
, aProperty
) {
604 var target
= this._dataSource
.GetTarget(aSource
, aProperty
, true);
605 if (target
instanceof Ci
.nsIRDFLiteral
)
610 _setPersist
: function bg__setPersist(aSource
, aProperty
, aTarget
) {
613 var oldTarget
= this._dataSource
.GetTarget(aSource
, aProperty
, true);
616 this._dataSource
.Change(aSource
, aProperty
, oldTarget
, this._rdf
.GetLiteral(aTarget
));
618 this._dataSource
.Unassert(aSource
, aProperty
, oldTarget
);
621 this._dataSource
.Assert(aSource
, aProperty
, this._rdf
.GetLiteral(aTarget
), true);
627 // ------------------------------
628 // public nsIBrowserGlue members
629 // ------------------------------
631 sanitize: function(aParentWindow
)
633 this.Sanitizer
.sanitize(aParentWindow
);
636 ensurePlacesDefaultQueriesInitialized: function() {
637 const SMART_BOOKMARKS_VERSION
= 1;
638 const SMART_BOOKMARKS_ANNO
= "Places/SmartBookmark";
639 const SMART_BOOKMARKS_PREF
= "browser.places.smartBookmarksVersion";
641 // XXX should this be a pref? see bug #399268
642 const MAX_RESULTS
= 10;
644 var prefBranch
= Cc
["@mozilla.org/preferences-service;1"].
645 getService(Ci
.nsIPrefBranch
);
647 // get current smart bookmarks version
648 // By default, if the pref is not set up, we must create Smart Bookmarks
649 var smartBookmarksCurrentVersion
= 0;
651 smartBookmarksCurrentVersion
= prefBranch
.getIntPref(SMART_BOOKMARKS_PREF
);
654 // bail out if we don't have to create or update Smart Bookmarks
655 if (smartBookmarksCurrentVersion
== -1 ||
656 smartBookmarksCurrentVersion
>= SMART_BOOKMARKS_VERSION
)
659 var bmsvc
= Cc
["@mozilla.org/browser/nav-bookmarks-service;1"].
660 getService(Ci
.nsINavBookmarksService
);
661 var annosvc
= Cc
["@mozilla.org/browser/annotation-service;1"].
662 getService(Ci
.nsIAnnotationService
);
665 _placesBundle
: Cc
["@mozilla.org/intl/stringbundle;1"].
666 getService(Ci
.nsIStringBundleService
).
667 createBundle("chrome://browser/locale/places/places.properties"),
669 _uri: function(aSpec
) {
670 return Cc
["@mozilla.org/network/io-service;1"].
671 getService(Ci
.nsIIOService
).
672 newURI(aSpec
, null, null);
675 runBatched: function() {
676 var smartBookmarks
= [];
677 var bookmarksMenuIndex
= 0;
678 var bookmarksToolbarIndex
= 0;
681 var smart
= {queryId
: "MostVisited", // don't change this
683 title
: this._placesBundle
.GetStringFromName("mostVisitedTitle"),
684 uri
: this._uri("place:queryType=" +
685 Ci
.nsINavHistoryQueryOptions
.QUERY_TYPE_HISTORY
+
687 Ci
.nsINavHistoryQueryOptions
.SORT_BY_VISITCOUNT_DESCENDING
+
688 "&maxResults=" + MAX_RESULTS
),
689 parent
: bmsvc
.toolbarFolder
,
690 position
: bookmarksToolbarIndex
++};
691 smartBookmarks
.push(smart
);
693 // RECENTLY BOOKMARKED
694 smart
= {queryId
: "RecentlyBookmarked", // don't change this
696 title
: this._placesBundle
.GetStringFromName("recentlyBookmarkedTitle"),
697 uri
: this._uri("place:folder=BOOKMARKS_MENU" +
698 "&folder=UNFILED_BOOKMARKS" +
701 Ci
.nsINavHistoryQueryOptions
.QUERY_TYPE_BOOKMARKS
+
703 Ci
.nsINavHistoryQueryOptions
.SORT_BY_DATEADDED_DESCENDING
+
704 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
705 "&maxResults=" + MAX_RESULTS
+
706 "&excludeQueries=1"),
707 parent
: bmsvc
.bookmarksMenuFolder
,
708 position
: bookmarksMenuIndex
++};
709 smartBookmarks
.push(smart
);
712 smart
= {queryId
: "RecentTags", // don't change this
714 title
: this._placesBundle
.GetStringFromName("recentTagsTitle"),
715 uri
: this._uri("place:"+
717 Ci
.nsINavHistoryQueryOptions
.RESULTS_AS_TAG_QUERY
+
719 Ci
.nsINavHistoryQueryOptions
.SORT_BY_LASTMODIFIED_DESCENDING
+
720 "&maxResults=" + MAX_RESULTS
),
721 parent
: bmsvc
.bookmarksMenuFolder
,
722 position
: bookmarksMenuIndex
++};
723 smartBookmarks
.push(smart
);
725 var smartBookmarkItemIds
= annosvc
.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO
, {});
726 // set current itemId, parent and position if Smart Bookmark exists
727 for each(var itemId
in smartBookmarkItemIds
) {
728 var queryId
= annosvc
.getItemAnnotation(itemId
, SMART_BOOKMARKS_ANNO
);
729 for (var i
= 0; i
< smartBookmarks
.length
; i
++){
730 if (smartBookmarks
[i
].queryId
== queryId
) {
731 smartBookmarks
[i
].itemId
= itemId
;
732 smartBookmarks
[i
].parent
= bmsvc
.getFolderIdForItem(itemId
);
733 smartBookmarks
[i
].position
= bmsvc
.getItemIndex(itemId
);
734 // remove current item, since it will be replaced
735 bmsvc
.removeItem(itemId
);
738 // We don't remove old Smart Bookmarks because user could still
739 // find them useful, or could have personalized them.
740 // Instead we remove the Smart Bookmark annotation.
741 if (i
== smartBookmarks
.length
- 1)
742 annosvc
.removeItemAnnotation(itemId
, SMART_BOOKMARKS_ANNO
);
746 // create smart bookmarks
747 for each(var smartBookmark
in smartBookmarks
) {
748 smartBookmark
.itemId
= bmsvc
.insertBookmark(smartBookmark
.parent
,
750 smartBookmark
.position
,
751 smartBookmark
.title
);
752 annosvc
.setItemAnnotation(smartBookmark
.itemId
,
753 SMART_BOOKMARKS_ANNO
, smartBookmark
.queryId
,
754 0, annosvc
.EXPIRE_NEVER
);
757 // If we are creating all Smart Bookmarks from ground up, add a
758 // separator below them in the bookmarks menu.
759 if (smartBookmarkItemIds
.length
== 0)
760 bmsvc
.insertSeparator(bmsvc
.bookmarksMenuFolder
, bookmarksMenuIndex
);
765 bmsvc
.runInBatchMode(callback
, null);
768 Components
.utils
.reportError(ex
);
771 prefBranch
.setIntPref(SMART_BOOKMARKS_PREF
, SMART_BOOKMARKS_VERSION
);
772 prefBranch
.QueryInterface(Ci
.nsIPrefService
).savePrefFile(null);
777 classDescription
: "Firefox Browser Glue Service",
778 classID
: Components
.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
779 contractID
: "@mozilla.org/browser/browserglue;1",
781 QueryInterface
: XPCOMUtils
.generateQI([Ci
.nsIObserver
,
782 Ci
.nsISupportsWeakReference
,
785 // redefine the default factory for XPCOMUtils
786 _xpcom_factory
: BrowserGlueServiceFactory
,
788 // get this contractID registered for certain categories via XPCOMUtils
790 // make BrowserGlue a startup observer
791 { category
: "app-startup", service
: true }
795 //module initialization
796 function NSGetModule(aCompMgr
, aFileSpec
) {
797 return XPCOMUtils
.generateModule([BrowserGlue
]);