michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=2 sts=2 expandtab 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: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Constants michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: michael@0: // Fired by TelemetryPing when async telemetry data should be collected. michael@0: const TOPIC_GATHER_TELEMETRY = "gather-telemetry"; michael@0: michael@0: // Seconds between maintenance runs. michael@0: const MAINTENANCE_INTERVAL_SECONDS = 7 * 86400; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Imports michael@0: michael@0: Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: Components.utils.import("resource://gre/modules/PlacesUtils.jsm"); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "PlacesDBUtils", michael@0: "resource://gre/modules/PlacesDBUtils.jsm"); michael@0: michael@0: /** michael@0: * This component can be used as a starter for modules that have to run when michael@0: * certain categories are invoked. michael@0: */ michael@0: function PlacesCategoriesStarter() michael@0: { michael@0: Services.obs.addObserver(this, TOPIC_GATHER_TELEMETRY, false); michael@0: Services.obs.addObserver(this, PlacesUtils.TOPIC_SHUTDOWN, false); michael@0: michael@0: // nsINavBookmarkObserver implementation. michael@0: let notify = (function () { michael@0: if (!this._notifiedBookmarksSvcReady) { michael@0: // For perf reasons unregister from the category, since no further michael@0: // notifications are needed. michael@0: Cc["@mozilla.org/categorymanager;1"] michael@0: .getService(Ci.nsICategoryManager) michael@0: .deleteCategoryEntry("bookmarks-observer", this, false); michael@0: // Directly notify PlacesUtils, to ensure it catches the notification. michael@0: PlacesUtils.observe(null, "bookmarks-service-ready", null); michael@0: } michael@0: }).bind(this); michael@0: [ "onItemAdded", "onItemRemoved", "onItemChanged", "onBeginUpdateBatch", michael@0: "onEndUpdateBatch", "onItemVisited", michael@0: "onItemMoved" ].forEach(function(aMethod) { michael@0: this[aMethod] = notify; michael@0: }, this); michael@0: } michael@0: michael@0: PlacesCategoriesStarter.prototype = { michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: //// nsIObserver michael@0: michael@0: observe: function PCS_observe(aSubject, aTopic, aData) michael@0: { michael@0: switch (aTopic) { michael@0: case PlacesUtils.TOPIC_SHUTDOWN: michael@0: Services.obs.removeObserver(this, PlacesUtils.TOPIC_SHUTDOWN); michael@0: Services.obs.removeObserver(this, TOPIC_GATHER_TELEMETRY); michael@0: let globalObj = michael@0: Cu.getGlobalForObject(PlacesCategoriesStarter.prototype); michael@0: let descriptor = michael@0: Object.getOwnPropertyDescriptor(globalObj, "PlacesDBUtils"); michael@0: if (descriptor.value !== undefined) { michael@0: PlacesDBUtils.shutdown(); michael@0: } michael@0: break; michael@0: case TOPIC_GATHER_TELEMETRY: michael@0: PlacesDBUtils.telemetry(); michael@0: break; michael@0: case "idle-daily": michael@0: // Once a week run places.sqlite maintenance tasks. michael@0: let lastMaintenance = 0; michael@0: try { michael@0: lastMaintenance = michael@0: Services.prefs.getIntPref("places.database.lastMaintenance"); michael@0: } catch (ex) {} michael@0: let nowSeconds = parseInt(Date.now() / 1000); michael@0: if (lastMaintenance < nowSeconds - MAINTENANCE_INTERVAL_SECONDS) { michael@0: PlacesDBUtils.maintenanceOnIdle(); michael@0: } michael@0: break; michael@0: default: michael@0: throw new Error("Trying to handle an unknown category."); michael@0: } michael@0: }, michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: //// nsISupports michael@0: michael@0: classID: Components.ID("803938d5-e26d-4453-bf46-ad4b26e41114"), michael@0: michael@0: _xpcom_factory: XPCOMUtils.generateSingletonFactory(PlacesCategoriesStarter), michael@0: michael@0: QueryInterface: XPCOMUtils.generateQI([ michael@0: Ci.nsIObserver michael@0: , Ci.nsINavBookmarkObserver michael@0: ]) michael@0: }; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Module Registration michael@0: michael@0: let components = [PlacesCategoriesStarter]; michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);