1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 const Cc = Components.classes;
6 const Ci = Components.interfaces;
7 const Cu = Components.utils;
9 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
10 Cu.import("resource://gre/modules/Services.jsm");
12 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
13 "resource://gre/modules/AddonManager.jsm");
15 XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
16 "resource://gre/modules/AddonRepository.jsm");
18 XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
20 function getPref(func, preference, defaultValue) {
22 return Services.prefs[func](preference);
28 // -----------------------------------------------------------------------
29 // Add-on auto-update management service
30 // -----------------------------------------------------------------------
32 const PREF_ADDON_UPDATE_ENABLED = "extensions.autoupdate.enabled";
34 var gNeedsRestart = false;
36 function AddonUpdateService() {}
38 AddonUpdateService.prototype = {
39 classDescription: "Add-on auto-update management",
40 classID: Components.ID("{93c8824c-9b87-45ae-bc90-5b82a1e4d877}"),
42 QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]),
44 notify: function aus_notify(aTimer) {
45 if (aTimer && !getPref("getBoolPref", PREF_ADDON_UPDATE_ENABLED, true))
48 // If we already auto-upgraded and installed new versions, ignore this check
52 Services.io.offline = false;
54 // Assume we are doing a periodic update check
55 let reason = AddonManager.UPDATE_WHEN_PERIODIC_UPDATE;
57 reason = AddonManager.UPDATE_WHEN_USER_REQUESTED;
59 AddonManager.getAddonsByTypes(null, function(aAddonList) {
60 aAddonList.forEach(function(aAddon) {
61 if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) {
62 let data = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
63 data.data = JSON.stringify({ id: aAddon.id, name: aAddon.name });
64 Services.obs.notifyObservers(data, "addon-update-started", null);
66 let listener = new UpdateCheckListener();
67 aAddon.findUpdates(listener, reason);
72 RecommendedSearchResults.search();
76 // -----------------------------------------------------------------------
77 // Add-on update listener. Starts a download for any add-on with a viable
79 // -----------------------------------------------------------------------
81 function UpdateCheckListener() {
86 UpdateCheckListener.prototype = {
87 onCompatibilityUpdateAvailable: function(aAddon) {
88 this._status = "compatibility";
91 onUpdateAvailable: function(aAddon, aInstall) {
92 this._status = "update";
93 this._version = aInstall.version;
97 onNoUpdateAvailable: function(aAddon) {
99 this._status = "no-update";
102 onUpdateFinished: function(aAddon, aError) {
103 let data = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
105 data.data = JSON.stringify({ id: aAddon.id, name: aAddon.name, version: this._version });
107 data.data = JSON.stringify({ id: aAddon.id, name: aAddon.name });
110 this._status = "error";
112 Services.obs.notifyObservers(data, "addon-update-ended", this._status);
116 // -----------------------------------------------------------------------
117 // RecommendedSearchResults fetches add-on data and saves it to a cache
118 // -----------------------------------------------------------------------
120 var RecommendedSearchResults = {
121 _getFile: function() {
122 let dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
123 let file = dirService.get("ProfD", Ci.nsILocalFile);
124 file.append("recommended-addons.json");
128 _writeFile: function (aFile, aData) {
132 // Asynchronously copy the data to the file.
133 let array = new TextEncoder().encode(aData);
134 OS.File.writeAtomic(aFile.path, array, { tmpPath: aFile.path + ".tmp" }).then(function onSuccess() {
135 Services.obs.notifyObservers(null, "recommended-addons-cache-updated", "");
139 searchSucceeded: function(aAddons, aAddonCount, aTotalResults) {
142 // Filter addons already installed
143 AddonManager.getAllAddons(function(aAllAddons) {
144 let addons = aAddons.filter(function(addon) {
145 for (let i = 0; i < aAllAddons.length; i++)
146 if (addon.id == aAllAddons[i].id)
156 addons.forEach(function(aAddon) {
160 version: aAddon.version,
161 learnmoreURL: aAddon.learnmoreURL,
162 iconURL: aAddon.iconURL
166 let file = self._getFile();
167 self._writeFile(file, JSON.stringify(json));
171 searchFailed: function searchFailed() { },
174 const kAddonsMaxDisplay = 2;
176 if (AddonRepository.isSearching)
177 AddonRepository.cancelSearch();
178 AddonRepository.retrieveRecommendedAddons(kAddonsMaxDisplay, RecommendedSearchResults);
182 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AddonUpdateService]);