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