michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", michael@0: "resource://gre/modules/PlacesUtils.jsm"); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", michael@0: "resource://gre/modules/NetUtil.jsm"); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "Task", michael@0: "resource://gre/modules/Task.jsm"); michael@0: michael@0: // Custom factory object to ensure that we're a singleton michael@0: const BrowserStartupServiceFactory = { michael@0: _instance: null, michael@0: createInstance: function (outer, iid) { michael@0: if (outer != null) michael@0: throw Components.results.NS_ERROR_NO_AGGREGATION; michael@0: return this._instance || (this._instance = new BrowserStartup()); michael@0: } michael@0: }; michael@0: michael@0: function BrowserStartup() { michael@0: this._init(); michael@0: } michael@0: michael@0: BrowserStartup.prototype = { michael@0: // for XPCOM michael@0: classID: Components.ID("{1d542abc-c88b-4636-a4ef-075b49806317}"), michael@0: michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), michael@0: michael@0: _xpcom_factory: BrowserStartupServiceFactory, michael@0: michael@0: _init: function() { michael@0: Services.obs.addObserver(this, "places-init-complete", false); michael@0: Services.obs.addObserver(this, "final-ui-startup", false); michael@0: }, michael@0: michael@0: _initDefaultBookmarks: function() { michael@0: // We must instantiate the history service since it will tell us if we michael@0: // need to import or restore bookmarks due to first-run, corruption or michael@0: // forced migration (due to a major schema change). michael@0: let histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. michael@0: getService(Ci.nsINavHistoryService); michael@0: michael@0: // If the database is corrupt or has been newly created we should michael@0: // import bookmarks. michael@0: let databaseStatus = histsvc.databaseStatus; michael@0: let importBookmarks = databaseStatus == histsvc.DATABASE_STATUS_CREATE || michael@0: databaseStatus == histsvc.DATABASE_STATUS_CORRUPT; michael@0: michael@0: if (!importBookmarks) { michael@0: // Check to see whether "mobile" root already exists. This is to handle michael@0: // existing profiles created with pre-1.0 builds (which won't have mobile michael@0: // bookmarks root). We can remove this eventually when we stop michael@0: // caring about users migrating to current builds with pre-1.0 profiles. michael@0: let annos = Cc["@mozilla.org/browser/annotation-service;1"]. michael@0: getService(Ci.nsIAnnotationService); michael@0: let metroRootItems = annos.getItemsWithAnnotation("metro/bookmarksRoot", {}); michael@0: if (metroRootItems.length > 0) michael@0: return; // no need to do initial import michael@0: } michael@0: michael@0: Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm"); michael@0: michael@0: Task.spawn(function() { michael@0: yield BookmarkJSONUtils.importFromURL("chrome://browser/locale/bookmarks.json", false); michael@0: michael@0: // Create the new smart bookmark. michael@0: const MAX_RESULTS = 10; michael@0: const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark"; michael@0: michael@0: // Place the Metro folder at the end of the smart bookmarks list. michael@0: let maxIndex = Math.max.apply(null, michael@0: PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO).map(id => { michael@0: return PlacesUtils.bookmarks.getItemIndex(id); michael@0: })); michael@0: let smartBookmarkId = michael@0: PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarksMenuFolderId, michael@0: NetUtil.newURI("place:folder=" + michael@0: PlacesUtils.annotations.getItemsWithAnnotation('metro/bookmarksRoot', {})[0] + michael@0: "&queryType=" + michael@0: Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS + michael@0: "&sort=" + michael@0: Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING + michael@0: "&maxResults=" + MAX_RESULTS + michael@0: "&excludeQueries=1"), michael@0: maxIndex + 1, michael@0: PlacesUtils.getString("windows8TouchTitle")); michael@0: PlacesUtils.annotations.setItemAnnotation(smartBookmarkId, michael@0: SMART_BOOKMARKS_ANNO, michael@0: "Windows8Touch", 0, michael@0: PlacesUtils.annotations.EXPIRE_NEVER); michael@0: }); michael@0: }, michael@0: michael@0: _startupActions: function() { michael@0: }, michael@0: michael@0: // nsIObserver michael@0: observe: function(aSubject, aTopic, aData) { michael@0: switch (aTopic) { michael@0: case "places-init-complete": michael@0: Services.obs.removeObserver(this, "places-init-complete"); michael@0: this._initDefaultBookmarks(); michael@0: break; michael@0: case "final-ui-startup": michael@0: Services.obs.removeObserver(this, "final-ui-startup"); michael@0: this._startupActions(); michael@0: break; michael@0: } michael@0: } michael@0: }; michael@0: michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserStartup]);