123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- /* 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/. */
- "use strict";
- const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
- this.EXPORTED_SYMBOLS = ["SystemUpdateService"];
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
- Cu.import("resource://gre/modules/Services.jsm");
- const CATEGORY_SYSTEM_UPDATE_PROVIDER = "system-update-provider";
- const PROVIDER_ACTIVITY_IDLE = 0;
- const PROVIDER_ACTIVITY_CHECKING = 1;
- const PROVIDER_ACTIVITY_DOWNLOADING = 1 << 1;
- const PROVIDER_ACTIVITY_APPLYING = 1 << 2;
- var debug = Services.prefs.getBoolPref("dom.system_update.debug")
- ? (aMsg) => dump("-*- SystemUpdateService.jsm : " + aMsg + "\n")
- : (aMsg) => {};
- XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageBroadcaster");
- function ActiveProvider(aProvider) {
- this.id = aProvider.id;
- this._instance = Components.classesByID[aProvider.id].getService(Ci.nsISystemUpdateProvider);
- this._instance.setListener(this);
- }
- ActiveProvider.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemUpdateListener]),
- _activity: PROVIDER_ACTIVITY_IDLE,
- destroy: function() {
- if (this._instance) {
- this._instance.unsetListener();
- this._instance = null;
- }
- this.id = null;
- },
- checkForUpdate: function() {
- this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_CHECKING,
- this._instance.checkForUpdate);
- },
- startDownload: function() {
- this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_DOWNLOADING,
- this._instance.startDownload);
- },
- stopDownload: function() {
- this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_DOWNLOADING,
- this._instance.stopDownload);
- },
- applyUpdate: function() {
- this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_APPLYING,
- this._instance.applyUpdate);
- },
- setParameter: function(aName, aValue) {
- return this._instance.setParameter(aName, aValue);
- },
- getParameter: function(aName) {
- return this._instance.getParameter(aName);
- },
- // nsISystemUpdateListener
- onUpdateAvailable: function(aType, aVersion, aDescription, aBuildDate, aSize) {
- this._execFuncIfActiveAndInAction(PROVIDER_ACTIVITY_CHECKING, function() {
- ppmm.broadcastAsyncMessage("SystemUpdate:OnUpdateAvailable", {
- uuid: this.id,
- packageInfo: {
- type: aType,
- version: aVersion,
- description: aDescription,
- buildDate: aBuildDate,
- size: aSize,
- }
- });
- this._unsetActivity(PROVIDER_ACTIVITY_CHECKING);
- }.bind(this));
- },
- onProgress: function(aLoaded, aTotal) {
- this._execFuncIfActiveAndInAction(PROVIDER_ACTIVITY_DOWNLOADING, function() {
- ppmm.broadcastAsyncMessage("SystemUpdate:OnProgress", {
- uuid: this.id,
- loaded: aLoaded,
- total: aTotal,
- });
- }.bind(this));
- },
- onUpdateReady: function() {
- this._execFuncIfActiveAndInAction(PROVIDER_ACTIVITY_DOWNLOADING, function() {
- ppmm.broadcastAsyncMessage("SystemUpdate:OnUpdateReady", {
- uuid: this.id,
- });
- this._unsetActivity(PROVIDER_ACTIVITY_DOWNLOADING);
- }.bind(this));
- },
- onError: function(aErrMsg) {
- if (!SystemUpdateService._isActiveProviderId(this.id)) {
- return;
- }
- ppmm.broadcastAsyncMessage("SystemUpdate:OnError", {
- uuid: this.id,
- message: aErrMsg,
- });
- this._activity = PROVIDER_ACTIVITY_IDLE;
- },
- isIdle: function() {
- return this._activity === PROVIDER_ACTIVITY_IDLE;
- },
- _isInActivity: function(aActivity) {
- return (this._activity & aActivity) !== PROVIDER_ACTIVITY_IDLE;
- },
- _setActivity: function(aActivity) {
- this._activity |= aActivity;
- },
- _unsetActivity: function(aActivity) {
- this._activity &= ~aActivity;
- },
- _execFuncIfNotInActivity: function(aActivity, aFunc) {
- if (!this._isInActivity(aActivity)) {
- this._setActivity(aActivity);
- aFunc();
- }
- },
- _execFuncIfActiveAndInAction: function(aActivity, aFunc) {
- if (!SystemUpdateService._isActiveProviderId(this.id)) {
- return;
- }
- if (this._isInActivity(aActivity)) {
- aFunc();
- }
- },
- };
- this.SystemUpdateService = {
- _providers: [],
- _activeProvider: null,
- _updateActiveProvider: function(aProvider) {
- if (this._activeProvider) {
- this._activeProvider.destroy();
- }
- this._activeProvider = new ActiveProvider(aProvider);
- },
- _isActiveProviderId: function(aId) {
- return (this._activeProvider && this._activeProvider.id === aId);
- },
- init: function() {
- debug("init");
- let messages = ["SystemUpdate:GetProviders",
- "SystemUpdate:GetActiveProvider",
- "SystemUpdate:SetActiveProvider",
- "SystemUpdate:CheckForUpdate",
- "SystemUpdate:StartDownload",
- "SystemUpdate:StopDownload",
- "SystemUpdate:ApplyUpdate",
- "SystemUpdate:SetParameter",
- "SystemUpdate:GetParameter"];
- messages.forEach((function(aMsgName) {
- ppmm.addMessageListener(aMsgName, this);
- }).bind(this));
- // load available provider list
- let catMan = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
- let entries = catMan.enumerateCategory(CATEGORY_SYSTEM_UPDATE_PROVIDER);
- while (entries.hasMoreElements()) {
- let name = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
- let [contractId, id] = catMan.getCategoryEntry(CATEGORY_SYSTEM_UPDATE_PROVIDER, name).split(",");
- this._providers.push({
- id: id,
- name: name,
- contractId: contractId
- });
- }
- debug("available providers: " + JSON.stringify(this._providers));
- // setup default active provider
- let defaultActive;
- try {
- defaultActive = Services.prefs.getCharPref("dom.system_update.active");
- } catch (e) {}
- if (defaultActive) {
- let defaultProvider = this._providers.find(function(aProvider) {
- return aProvider.contractId === defaultActive;
- });
- if (defaultProvider) {
- this._updateActiveProvider(defaultProvider);
- }
- }
- },
- addProvider: function(aClassId, aContractId, aName) {
- debug("addProvider");
- //did not allow null or empty string to add.
- if(!aClassId || !aContractId || !aName) {
- return;
- }
- let existedProvider = this._providers.find(function(provider) {
- return provider.id === aClassId;
- });
- //skip if adding the existed provider.
- if (existedProvider) {
- debug("existing providers: " + JSON.stringify(existedProvider));
- return;
- }
- //dynamically add the provider info to list.
- this._providers.push({
- id: aClassId,
- name: aName,
- contractId: aContractId
- });
- debug("available providers: " + JSON.stringify(this._providers));
- },
- getProviders: function(aData, aMm) {
- debug("getProviders");
- aData.providers = [];
- for (let provider of this._providers) {
- aData.providers.push({
- name: provider.name,
- uuid: provider.id
- });
- }
- aMm.sendAsyncMessage("SystemUpdate:GetProviders:Result:OK", aData);
- },
- getActiveProvider: function(aData, aMm) {
- debug("getActiveProvider");
- let self = this;
- let providerInfo = this._providers.find(function(provider) {
- return self._isActiveProviderId(provider.id);
- });
- if (!providerInfo) {
- aData.error = "NotFoundError";
- aMm.sendAsyncMessage("SystemUpdate:GetActiveProvider:Result:Error", aData);
- return;
- }
- aData.provider = {
- name: providerInfo.name,
- uuid: providerInfo.id
- };
- aMm.sendAsyncMessage("SystemUpdate:GetActiveProvider:Result:OK", aData);
- },
- setActiveProvider: function(aData, aMm) {
- debug("setActiveProvider");
- let self = this;
- let selectedProvider = this._providers.find(function(provider) {
- return provider.id === aData.uuid;
- });
- if (!selectedProvider) {
- aData.error = "DataError";
- aMm.sendAsyncMessage("SystemUpdate:SetActiveProvider:Result:Error", aData);
- return;
- }
- if (!this._isActiveProviderId(selectedProvider.id)) {
- // not allow changing active provider while there is an ongoing update activity
- if (this.activeProvider && !this._activeProvider.isIdle()) {
- aData.error = "DataError";
- aMm.sendAsyncMessage("SystemUpdate:SetActiveProvider:Result:Error", aData);
- return;
- }
- this._updateActiveProvider(selectedProvider);
- Services.prefs.setCharPref("dom.system_update.active", selectedProvider.contractId);
- }
- aData.provider = {
- name: selectedProvider.name,
- uuid: selectedProvider.id
- };
- aMm.sendAsyncMessage("SystemUpdate:SetActiveProvider:Result:OK", aData);
- },
- receiveMessage: function(aMessage) {
- if (!aMessage.target.assertPermission("system-update")) {
- debug("receive message " + aMessage.name +
- " from a content process with no 'system-update' privileges.");
- return null;
- }
- let msg = aMessage.data || {};
- let mm = aMessage.target;
- switch (aMessage.name) {
- case "SystemUpdate:GetProviders": {
- this.getProviders(msg, mm);
- break;
- }
- case "SystemUpdate:GetActiveProvider": {
- this.getActiveProvider(msg, mm);
- break;
- }
- case "SystemUpdate:SetActiveProvider": {
- this.setActiveProvider(msg, mm);
- break;
- }
- case "SystemUpdate:CheckForUpdate": {
- if (this._isActiveProviderId(msg.uuid)) {
- this._activeProvider.checkForUpdate();
- }
- break;
- }
- case "SystemUpdate:StartDownload": {
- if (this._isActiveProviderId(msg.uuid)) {
- this._activeProvider.startDownload();
- }
- break;
- }
- case "SystemUpdate:StopDownload": {
- if (this._isActiveProviderId(msg.uuid)) {
- this._activeProvider.stopDownload();
- }
- break;
- }
- case "SystemUpdate:ApplyUpdate": {
- if (this._isActiveProviderId(msg.uuid)) {
- this._activeProvider.applyUpdate();
- }
- break;
- }
- case "SystemUpdate:SetParameter": {
- if (this._isActiveProviderId(msg.uuid)) {
- return this._activeProvider.setParameter(msg.name, msg.value);
- }
- break;
- }
- case "SystemUpdate:GetParameter": {
- if (this._isActiveProviderId(msg.uuid)) {
- return this._activeProvider.getParameter(msg.name);
- }
- break;
- }
- }
- },
- };
- SystemUpdateService.init();
|