summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/update
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps/update')
-rw-r--r--toolkit/mozapps/update/BackgroundUpdate.sys.mjs40
-rw-r--r--toolkit/mozapps/update/UpdateService.sys.mjs1200
-rw-r--r--toolkit/mozapps/update/common/readstrings.cpp9
-rw-r--r--toolkit/mozapps/update/docs/MaintenanceServiceTests.rst4
-rw-r--r--toolkit/mozapps/update/nsUpdateService.manifest2
-rw-r--r--toolkit/mozapps/update/updater/Makefile.in11
-rw-r--r--toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/Makefile.in25
-rw-r--r--toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/moz.build18
-rw-r--r--toolkit/mozapps/update/updater/macos-frameworks/moz.build7
-rw-r--r--toolkit/mozapps/update/updater/updater.cpp2
10 files changed, 690 insertions, 628 deletions
diff --git a/toolkit/mozapps/update/BackgroundUpdate.sys.mjs b/toolkit/mozapps/update/BackgroundUpdate.sys.mjs
index 3022c9ffde..1435c0fa2b 100644
--- a/toolkit/mozapps/update/BackgroundUpdate.sys.mjs
+++ b/toolkit/mozapps/update/BackgroundUpdate.sys.mjs
@@ -69,18 +69,6 @@ function taskNameVersion(taskVersion) {
return 2;
}
-async function deleteTasksInRange(installedVersion, currentVersion) {
- for (
- let taskVersion = installedVersion;
- taskVersion <= currentVersion;
- taskVersion++
- ) {
- await lazy.TaskScheduler.deleteTask(this.taskId, {
- nameVersion: taskNameVersion(taskVersion),
- });
- }
-}
-
export var BackgroundUpdate = {
QueryInterface: ChromeUtils.generateQI([
"nsINamed",
@@ -102,6 +90,24 @@ export var BackgroundUpdate = {
return taskId;
},
+ async deleteTasksInRange(installedVersion, currentVersion) {
+ for (
+ let taskVersion = installedVersion;
+ taskVersion <= currentVersion;
+ taskVersion++
+ ) {
+ try {
+ await lazy.TaskScheduler.deleteTask(this.taskId, {
+ nameVersion: taskNameVersion(taskVersion),
+ });
+ } catch (e) {
+ lazy.log.error(
+ `deleteTasksInRange: Error deleting task ${taskVersion}: ${e}`
+ );
+ }
+ }
+ },
+
/**
* Whether this installation has an App and a GRE omnijar.
*
@@ -583,7 +589,10 @@ export var BackgroundUpdate = {
TASK_INSTALLED_VERSION_PREF,
TASK_DEF_CURRENT_VERSION
);
- await deleteTasksInRange(installedVersion, TASK_DEF_CURRENT_VERSION);
+ await this.deleteTasksInRange(
+ installedVersion,
+ TASK_DEF_CURRENT_VERSION
+ );
lazy.log.debug(
`${SLUG}: witnessed falling (enabled -> disabled) edge; deleted task ${this.taskId}.`
);
@@ -616,7 +625,10 @@ export var BackgroundUpdate = {
TASK_INSTALLED_VERSION_PREF,
TASK_DEF_CURRENT_VERSION
);
- await deleteTasksInRange(installedVersion, TASK_DEF_CURRENT_VERSION);
+ await this.deleteTasksInRange(
+ installedVersion,
+ TASK_DEF_CURRENT_VERSION
+ );
} catch (e) {
lazy.log.error(`${SLUG}: Error removing old task: ${e}`);
}
diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs
index 34bf1b9e19..21ecb3db48 100644
--- a/toolkit/mozapps/update/UpdateService.sys.mjs
+++ b/toolkit/mozapps/update/UpdateService.sys.mjs
@@ -2082,69 +2082,10 @@ function pollForStagingEnd() {
lazy.setTimeout(pollingFn, pollingIntervalMs);
}
-/**
- * Update Patch
- * @param patch
- * A <patch> element to initialize this object with
- * @throws if patch has a size of 0
- * @constructor
- */
-function UpdatePatch(patch) {
- this._properties = {};
- this.errorCode = 0;
- this.finalURL = null;
- this.state = STATE_NONE;
-
- for (let i = 0; i < patch.attributes.length; ++i) {
- var attr = patch.attributes.item(i);
- // If an undefined value is saved to the xml file it will be a string when
- // it is read from the xml file.
- if (attr.value == "undefined") {
- continue;
- }
- switch (attr.name) {
- case "xmlns":
- // Don't save the XML namespace.
- break;
- case "selected":
- this.selected = attr.value == "true";
- break;
- case "size":
- if (0 == parseInt(attr.value)) {
- LOG("UpdatePatch:init - 0-sized patch!");
- throw Components.Exception("", Cr.NS_ERROR_ILLEGAL_VALUE);
- }
- this[attr.name] = attr.value;
- break;
- case "errorCode":
- if (attr.value) {
- let val = parseInt(attr.value);
- // This will evaluate to false if the value is 0 but that's ok since
- // this.errorCode is set to the default of 0 above.
- if (val) {
- this.errorCode = val;
- }
- }
- break;
- case "finalURL":
- case "state":
- case "type":
- case "URL":
- this[attr.name] = attr.value;
- break;
- default:
- if (!this._attrNames.includes(attr.name)) {
- // Set nsIPropertyBag properties that were read from the xml file.
- this.setProperty(attr.name, attr.value);
- }
- break;
- }
- }
-}
-UpdatePatch.prototype = {
+class UpdatePatch {
// nsIUpdatePatch attribute names used to prevent nsIWritablePropertyBag from
// over writing nsIUpdatePatch attributes.
- _attrNames: [
+ _attrNames = [
"errorCode",
"finalURL",
"selected",
@@ -2152,12 +2093,71 @@ UpdatePatch.prototype = {
"state",
"type",
"URL",
- ],
+ ];
+
+ /**
+ * @param patch
+ * A <patch> element to initialize this object with
+ * @throws if patch has a size of 0
+ * @constructor
+ */
+ constructor(patch) {
+ this._properties = {};
+ this.errorCode = 0;
+ this.finalURL = null;
+ this.state = STATE_NONE;
+
+ for (let i = 0; i < patch.attributes.length; ++i) {
+ var attr = patch.attributes.item(i);
+ // If an undefined value is saved to the xml file it will be a string when
+ // it is read from the xml file.
+ if (attr.value == "undefined") {
+ continue;
+ }
+ switch (attr.name) {
+ case "xmlns":
+ // Don't save the XML namespace.
+ break;
+ case "selected":
+ this.selected = attr.value == "true";
+ break;
+ case "size":
+ if (0 == parseInt(attr.value)) {
+ LOG("UpdatePatch:init - 0-sized patch!");
+ throw Components.Exception("", Cr.NS_ERROR_ILLEGAL_VALUE);
+ }
+ this[attr.name] = attr.value;
+ break;
+ case "errorCode":
+ if (attr.value) {
+ let val = parseInt(attr.value);
+ // This will evaluate to false if the value is 0 but that's ok since
+ // this.errorCode is set to the default of 0 above.
+ if (val) {
+ this.errorCode = val;
+ }
+ }
+ break;
+ case "finalURL":
+ case "state":
+ case "type":
+ case "URL":
+ this[attr.name] = attr.value;
+ break;
+ default:
+ if (!this._attrNames.includes(attr.name)) {
+ // Set nsIPropertyBag properties that were read from the xml file.
+ this.setProperty(attr.name, attr.value);
+ }
+ break;
+ }
+ }
+ }
/**
* See nsIUpdateService.idl
*/
- serialize: function UpdatePatch_serialize(updates) {
+ serialize(updates) {
var patch = updates.createElementNS(URI_UPDATE_NS, "patch");
patch.setAttribute("size", this.size);
patch.setAttribute("type", this.type);
@@ -2185,12 +2185,12 @@ UpdatePatch.prototype = {
}
}
return patch;
- },
+ }
/**
* See nsIWritablePropertyBag.idl
*/
- setProperty: function UpdatePatch_setProperty(name, value) {
+ setProperty(name, value) {
if (this._attrNames.includes(name)) {
throw Components.Exception(
"Illegal value '" +
@@ -2201,12 +2201,12 @@ UpdatePatch.prototype = {
);
}
this._properties[name] = { data: value, present: true };
- },
+ }
/**
* See nsIWritablePropertyBag.idl
*/
- deleteProperty: function UpdatePatch_deleteProperty(name) {
+ deleteProperty(name) {
if (this._attrNames.includes(name)) {
throw Components.Exception(
"Illegal value '" +
@@ -2221,7 +2221,7 @@ UpdatePatch.prototype = {
} else {
throw Components.Exception("", Cr.NS_ERROR_FAILURE);
}
- },
+ }
/**
* See nsIPropertyBag.idl
@@ -2231,7 +2231,7 @@ UpdatePatch.prototype = {
*/
get enumerator() {
return this.enumerate();
- },
+ }
*enumerate() {
// An nsISupportsInterfacePointer is used so creating an array using
@@ -2239,7 +2239,7 @@ UpdatePatch.prototype = {
let ip = Cc["@mozilla.org/supports-interface-pointer;1"].createInstance(
Ci.nsISupportsInterfacePointer
);
- let qi = ChromeUtils.generateQI(["nsIProperty"]);
+ let qi = ChromeUtils.generateQI([Ci.nsIProperty]);
for (let [name, value] of Object.entries(this._properties)) {
if (value.present && !this._attrNames.includes(name)) {
// The nsIPropertyBag enumerator returns a nsISimpleEnumerator whose
@@ -2251,7 +2251,7 @@ UpdatePatch.prototype = {
yield ip.data.QueryInterface(Ci.nsIProperty);
}
}
- },
+ }
/**
* See nsIPropertyBag.idl
@@ -2259,7 +2259,7 @@ UpdatePatch.prototype = {
* Note: returns null instead of throwing when the property doesn't exist to
* simplify code and to silence warnings in debug builds.
*/
- getProperty: function UpdatePatch_getProperty(name) {
+ getProperty(name) {
if (this._attrNames.includes(name)) {
throw Components.Exception(
"Illegal value '" +
@@ -2273,161 +2273,19 @@ UpdatePatch.prototype = {
return this._properties[name].data;
}
return null;
- },
-
- QueryInterface: ChromeUtils.generateQI([
- "nsIUpdatePatch",
- "nsIPropertyBag",
- "nsIWritablePropertyBag",
- ]),
-};
-
-/**
- * Update
- * Implements nsIUpdate
- * @param update
- * An <update> element to initialize this object with
- * @throws if the update contains no patches
- * @constructor
- */
-function Update(update) {
- this._patches = [];
- this._properties = {};
- this.isCompleteUpdate = false;
- this.channel = "default";
- this.promptWaitTime = Services.prefs.getIntPref(
- PREF_APP_UPDATE_PROMPTWAITTIME,
- 43200
- );
- this.unsupported = false;
-
- // Null <update>, assume this is a message container and do no
- // further initialization
- if (!update) {
- return;
- }
-
- for (let i = 0; i < update.childNodes.length; ++i) {
- let patchElement = update.childNodes.item(i);
- if (
- patchElement.nodeType != patchElement.ELEMENT_NODE ||
- patchElement.localName != "patch"
- ) {
- continue;
- }
-
- let patch;
- try {
- patch = new UpdatePatch(patchElement);
- } catch (e) {
- continue;
- }
- this._patches.push(patch);
- }
-
- if (!this._patches.length && !update.hasAttribute("unsupported")) {
- throw Components.Exception("", Cr.NS_ERROR_ILLEGAL_VALUE);
- }
-
- // Set the installDate value with the current time. If the update has an
- // installDate attribute this will be replaced with that value if it doesn't
- // equal 0.
- this.installDate = new Date().getTime();
- this.patchCount = this._patches.length;
-
- for (let i = 0; i < update.attributes.length; ++i) {
- let attr = update.attributes.item(i);
- if (attr.name == "xmlns" || attr.value == "undefined") {
- // Don't save the XML namespace or undefined values.
- // If an undefined value is saved to the xml file it will be a string when
- // it is read from the xml file.
- continue;
- } else if (attr.name == "detailsURL") {
- this.detailsURL = attr.value;
- } else if (attr.name == "installDate" && attr.value) {
- let val = parseInt(attr.value);
- if (val) {
- this.installDate = val;
- }
- } else if (attr.name == "errorCode" && attr.value) {
- let val = parseInt(attr.value);
- if (val) {
- // Set the value of |_errorCode| instead of |errorCode| since
- // selectedPatch won't be available at this point and normally the
- // nsIUpdatePatch will provide the errorCode.
- this._errorCode = val;
- }
- } else if (attr.name == "isCompleteUpdate") {
- this.isCompleteUpdate = attr.value == "true";
- } else if (attr.name == "promptWaitTime") {
- if (!isNaN(attr.value)) {
- this.promptWaitTime = parseInt(attr.value);
- }
- } else if (attr.name == "unsupported") {
- this.unsupported = attr.value == "true";
- } else {
- switch (attr.name) {
- case "appVersion":
- case "buildID":
- case "channel":
- case "displayVersion":
- case "elevationFailure":
- case "name":
- case "previousAppVersion":
- case "serviceURL":
- case "statusText":
- case "type":
- this[attr.name] = attr.value;
- break;
- default:
- if (!this._attrNames.includes(attr.name)) {
- // Set nsIPropertyBag properties that were read from the xml file.
- this.setProperty(attr.name, attr.value);
- }
- break;
- }
- }
}
- if (!this.previousAppVersion) {
- this.previousAppVersion = Services.appinfo.version;
- }
-
- if (!this.elevationFailure) {
- this.elevationFailure = false;
- }
-
- if (!this.detailsURL) {
- try {
- // Try using a default details URL supplied by the distribution
- // if the update XML does not supply one.
- this.detailsURL = Services.urlFormatter.formatURLPref(
- PREF_APP_UPDATE_URL_DETAILS
- );
- } catch (e) {
- this.detailsURL = "";
- }
- }
-
- if (!this.displayVersion) {
- this.displayVersion = this.appVersion;
- }
-
- if (!this.name) {
- // When the update doesn't provide a name fallback to using
- // "<App Name> <Update App Version>"
- let brandBundle = Services.strings.createBundle(URI_BRAND_PROPERTIES);
- let appName = brandBundle.GetStringFromName("brandShortName");
- this.name = lazy.gUpdateBundle.formatStringFromName("updateName", [
- appName,
- this.displayVersion,
- ]);
- }
+ QueryInterface = ChromeUtils.generateQI([
+ Ci.nsIUpdatePatch,
+ Ci.nsIPropertyBag,
+ Ci.nsIWritablePropertyBag,
+ ]);
}
-Update.prototype = {
+
+class Update {
// nsIUpdate attribute names used to prevent nsIWritablePropertyBag from over
// writing nsIUpdate attributes.
- _attrNames: [
+ _attrNames = [
"appVersion",
"buildID",
"channel",
@@ -2445,14 +2303,156 @@ Update.prototype = {
"statusText",
"type",
"unsupported",
- ],
+ ];
+
+ /**
+ * Implements nsIUpdate
+ * @param update
+ * An <update> element to initialize this object with
+ * @throws if the update contains no patches
+ * @constructor
+ */
+ constructor(update) {
+ this._patches = [];
+ this._properties = {};
+ this.isCompleteUpdate = false;
+ this.channel = "default";
+ this.promptWaitTime = Services.prefs.getIntPref(
+ PREF_APP_UPDATE_PROMPTWAITTIME,
+ 43200
+ );
+ this.unsupported = false;
+
+ // Null <update>, assume this is a message container and do no
+ // further initialization
+ if (!update) {
+ return;
+ }
+
+ for (let i = 0; i < update.childNodes.length; ++i) {
+ let patchElement = update.childNodes.item(i);
+ if (
+ patchElement.nodeType != patchElement.ELEMENT_NODE ||
+ patchElement.localName != "patch"
+ ) {
+ continue;
+ }
+
+ let patch;
+ try {
+ patch = new UpdatePatch(patchElement);
+ } catch (e) {
+ continue;
+ }
+ this._patches.push(patch);
+ }
+
+ if (!this._patches.length && !update.hasAttribute("unsupported")) {
+ throw Components.Exception("", Cr.NS_ERROR_ILLEGAL_VALUE);
+ }
+
+ // Set the installDate value with the current time. If the update has an
+ // installDate attribute this will be replaced with that value if it doesn't
+ // equal 0.
+ this.installDate = new Date().getTime();
+ this.patchCount = this._patches.length;
+
+ for (let i = 0; i < update.attributes.length; ++i) {
+ let attr = update.attributes.item(i);
+ if (attr.name == "xmlns" || attr.value == "undefined") {
+ // Don't save the XML namespace or undefined values.
+ // If an undefined value is saved to the xml file it will be a string when
+ // it is read from the xml file.
+ continue;
+ } else if (attr.name == "detailsURL") {
+ this.detailsURL = attr.value;
+ } else if (attr.name == "installDate" && attr.value) {
+ let val = parseInt(attr.value);
+ if (val) {
+ this.installDate = val;
+ }
+ } else if (attr.name == "errorCode" && attr.value) {
+ let val = parseInt(attr.value);
+ if (val) {
+ // Set the value of |_errorCode| instead of |errorCode| since
+ // selectedPatch won't be available at this point and normally the
+ // nsIUpdatePatch will provide the errorCode.
+ this._errorCode = val;
+ }
+ } else if (attr.name == "isCompleteUpdate") {
+ this.isCompleteUpdate = attr.value == "true";
+ } else if (attr.name == "promptWaitTime") {
+ if (!isNaN(attr.value)) {
+ this.promptWaitTime = parseInt(attr.value);
+ }
+ } else if (attr.name == "unsupported") {
+ this.unsupported = attr.value == "true";
+ } else {
+ switch (attr.name) {
+ case "appVersion":
+ case "buildID":
+ case "channel":
+ case "displayVersion":
+ case "elevationFailure":
+ case "name":
+ case "previousAppVersion":
+ case "serviceURL":
+ case "statusText":
+ case "type":
+ this[attr.name] = attr.value;
+ break;
+ default:
+ if (!this._attrNames.includes(attr.name)) {
+ // Set nsIPropertyBag properties that were read from the xml file.
+ this.setProperty(attr.name, attr.value);
+ }
+ break;
+ }
+ }
+ }
+
+ if (!this.previousAppVersion) {
+ this.previousAppVersion = Services.appinfo.version;
+ }
+
+ if (!this.elevationFailure) {
+ this.elevationFailure = false;
+ }
+
+ if (!this.detailsURL) {
+ try {
+ // Try using a default details URL supplied by the distribution
+ // if the update XML does not supply one.
+ this.detailsURL = Services.urlFormatter.formatURLPref(
+ PREF_APP_UPDATE_URL_DETAILS
+ );
+ } catch (e) {
+ this.detailsURL = "";
+ }
+ }
+
+ if (!this.displayVersion) {
+ this.displayVersion = this.appVersion;
+ }
+
+ if (!this.name) {
+ // When the update doesn't provide a name fallback to using
+ // "<App Name> <Update App Version>"
+ let brandBundle = Services.strings.createBundle(URI_BRAND_PROPERTIES);
+ let appName = brandBundle.GetStringFromName("brandShortName");
+ this.name = lazy.gUpdateBundle.formatStringFromName("updateName", [
+ appName,
+ this.displayVersion,
+ ]);
+ }
+ }
/**
* See nsIUpdateService.idl
*/
- getPatchAt: function Update_getPatchAt(index) {
+ getPatchAt(index) {
return this._patches[index];
- },
+ }
/**
* See nsIUpdateService.idl
@@ -2462,19 +2462,19 @@ Update.prototype = {
* active updates from the update manager for some reason but still have
* the update.status file to work with.
*/
- _state: "",
+ _state = "";
get state() {
if (this.selectedPatch) {
return this.selectedPatch.state;
}
return this._state;
- },
+ }
set state(state) {
if (this.selectedPatch) {
this.selectedPatch.state = state;
}
this._state = state;
- },
+ }
/**
* See nsIUpdateService.idl
@@ -2484,19 +2484,19 @@ Update.prototype = {
* active updates from the update manager for some reason but still have
* the update.status file to work with.
*/
- _errorCode: 0,
+ _errorCode = 0;
get errorCode() {
if (this.selectedPatch) {
return this.selectedPatch.errorCode;
}
return this._errorCode;
- },
+ }
set errorCode(errorCode) {
if (this.selectedPatch) {
this.selectedPatch.errorCode = errorCode;
}
this._errorCode = errorCode;
- },
+ }
/**
* See nsIUpdateService.idl
@@ -2508,12 +2508,12 @@ Update.prototype = {
}
}
return null;
- },
+ }
/**
* See nsIUpdateService.idl
*/
- serialize: function Update_serialize(updates) {
+ serialize(updates) {
// If appVersion isn't defined just return null. This happens when cleaning
// up invalid updates (e.g. incorrect channel).
if (!this.appVersion) {
@@ -2555,12 +2555,12 @@ Update.prototype = {
updates.documentElement.appendChild(update);
return update;
- },
+ }
/**
* See nsIWritablePropertyBag.idl
*/
- setProperty: function Update_setProperty(name, value) {
+ setProperty(name, value) {
if (this._attrNames.includes(name)) {
throw Components.Exception(
"Illegal value '" +
@@ -2571,12 +2571,12 @@ Update.prototype = {
);
}
this._properties[name] = { data: value, present: true };
- },
+ }
/**
* See nsIWritablePropertyBag.idl
*/
- deleteProperty: function Update_deleteProperty(name) {
+ deleteProperty(name) {
if (this._attrNames.includes(name)) {
throw Components.Exception(
"Illegal value '" +
@@ -2591,7 +2591,7 @@ Update.prototype = {
} else {
throw Components.Exception("", Cr.NS_ERROR_FAILURE);
}
- },
+ }
/**
* See nsIPropertyBag.idl
@@ -2601,7 +2601,7 @@ Update.prototype = {
*/
get enumerator() {
return this.enumerate();
- },
+ }
*enumerate() {
// An nsISupportsInterfacePointer is used so creating an array using
@@ -2609,7 +2609,7 @@ Update.prototype = {
let ip = Cc["@mozilla.org/supports-interface-pointer;1"].createInstance(
Ci.nsISupportsInterfacePointer
);
- let qi = ChromeUtils.generateQI(["nsIProperty"]);
+ let qi = ChromeUtils.generateQI([Ci.nsIProperty]);
for (let [name, value] of Object.entries(this._properties)) {
if (value.present && !this._attrNames.includes(name)) {
// The nsIPropertyBag enumerator returns a nsISimpleEnumerator whose
@@ -2621,14 +2621,14 @@ Update.prototype = {
yield ip.data.QueryInterface(Ci.nsIProperty);
}
}
- },
+ }
/**
* See nsIPropertyBag.idl
* Note: returns null instead of throwing when the property doesn't exist to
* simplify code and to silence warnings in debug builds.
*/
- getProperty: function Update_getProperty(name) {
+ getProperty(name) {
if (this._attrNames.includes(name)) {
throw Components.Exception(
"Illegal value '" +
@@ -2642,60 +2642,60 @@ Update.prototype = {
return this._properties[name].data;
}
return null;
- },
-
- QueryInterface: ChromeUtils.generateQI([
- "nsIUpdate",
- "nsIPropertyBag",
- "nsIWritablePropertyBag",
- ]),
-};
-
-/**
- * UpdateService
- * A Service for managing the discovery and installation of software updates.
- * @constructor
- */
-export function UpdateService() {
- LOG("Creating UpdateService");
- // The observor notification to shut down the service must be before
- // profile-before-change since nsIUpdateManager uses profile-before-change
- // to shutdown and write the update xml files.
- Services.obs.addObserver(this, "quit-application");
- lazy.UpdateLog.addConfigChangeListener(() => {
- this._logStatus();
- });
+ }
- this._logStatus();
+ QueryInterface = ChromeUtils.generateQI([
+ Ci.nsIUpdate,
+ Ci.nsIPropertyBag,
+ Ci.nsIWritablePropertyBag,
+ ]);
}
-UpdateService.prototype = {
+export class UpdateService {
/**
* The downloader we are using to download updates. There is only ever one of
* these.
*/
- _downloader: null,
+ _downloader = null;
/**
* Whether or not the service registered the "online" observer.
*/
- _registeredOnlineObserver: false,
+ _registeredOnlineObserver = false;
/**
* The current number of consecutive socket errors
*/
- _consecutiveSocketErrors: 0,
+ _consecutiveSocketErrors = 0;
/**
* A timer used to retry socket errors
*/
- _retryTimer: null,
+ _retryTimer = null;
/**
* Whether or not a background update check was initiated by the
* application update timer notification.
*/
- _isNotify: true,
+ _isNotify = true;
+
+ /**
+ * UpdateService
+ * A Service for managing the discovery and installation of software updates.
+ * @constructor
+ */
+ constructor() {
+ LOG("Creating UpdateService");
+ // The observor notification to shut down the service must be before
+ // profile-before-change since nsIUpdateManager uses profile-before-change
+ // to shutdown and write the update xml files.
+ Services.obs.addObserver(this, "quit-application");
+ lazy.UpdateLog.addConfigChangeListener(() => {
+ this._logStatus();
+ });
+
+ this._logStatus();
+ }
/**
* Handle Observer Service notifications
@@ -2706,7 +2706,7 @@ UpdateService.prototype = {
* @param data
* Additional data
*/
- observe: async function AUS_observe(subject, topic, data) {
+ async observe(subject, topic, data) {
switch (topic) {
case "post-update-processing":
// This pref was not cleared out of profiles after it stopped being used
@@ -2790,7 +2790,7 @@ UpdateService.prototype = {
}
break;
}
- },
+ }
/**
* The following needs to happen during the post-update-processing
@@ -2808,7 +2808,7 @@ UpdateService.prototype = {
* notify the user of install success.
*/
/* eslint-disable-next-line complexity */
- _postUpdateProcessing: async function AUS__postUpdateProcessing() {
+ async _postUpdateProcessing() {
if (this.disabled) {
// This function is a point when we can potentially enter the update
// system, even with update disabled. Make sure that we do not continue
@@ -3178,13 +3178,13 @@ UpdateService.prototype = {
// Something went wrong with the patch application process.
await handleFallbackToCompleteUpdate();
}
- },
+ }
/**
* Register an observer when the network comes online, so we can short-circuit
* the app.update.interval when there isn't connectivity
*/
- _registerOnlineObserver: function AUS__registerOnlineObserver() {
+ _registerOnlineObserver() {
if (this._registeredOnlineObserver) {
LOG(
"UpdateService:_registerOnlineObserver - observer already registered"
@@ -3199,12 +3199,12 @@ UpdateService.prototype = {
Services.obs.addObserver(this, "network:offline-status-changed");
this._registeredOnlineObserver = true;
- },
+ }
/**
* Called from the network:offline-status-changed observer.
*/
- _offlineStatusChanged: async function AUS__offlineStatusChanged(status) {
+ async _offlineStatusChanged(status) {
if (status !== "online") {
return;
}
@@ -3219,12 +3219,12 @@ UpdateService.prototype = {
// the background checker is contained in notify
await this._attemptResume();
- },
+ }
/**
* See nsIUpdateService.idl
*/
- onCheckComplete: async function AUS_onCheckComplete(result) {
+ async onCheckComplete(result) {
if (result.succeeded) {
await this._selectAndInstallUpdate(result.updates);
return;
@@ -3307,12 +3307,12 @@ UpdateService.prototype = {
);
AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_GENERAL_ERROR_SILENT);
}
- },
+ }
/**
* Called when a connection should be resumed
*/
- _attemptResume: async function AUS_attemptResume() {
+ async _attemptResume() {
LOG("UpdateService:_attemptResume");
// If a download is in progress and we aren't already downloading it, then
// resume it.
@@ -3348,23 +3348,23 @@ UpdateService.prototype = {
let check = lazy.CheckSvc.checkForUpdates(lazy.CheckSvc.BACKGROUND_CHECK);
await this.onCheckComplete(await check.result);
})();
- },
+ }
/**
* Notified when a timer fires
* @param _timer
* The timer that fired
*/
- notify: function AUS_notify(_timer) {
+ notify(_timer) {
this._checkForBackgroundUpdates(true);
- },
+ }
/**
* See nsIUpdateService.idl
*/
- checkForBackgroundUpdates: function AUS_checkForBackgroundUpdates() {
+ checkForBackgroundUpdates() {
return this._checkForBackgroundUpdates(false);
- },
+ }
// The suffix used for background update check telemetry histogram ID's.
get _pingSuffix() {
@@ -3376,7 +3376,7 @@ UpdateService.prototype = {
return AUSTLMY.SUBSEQUENT;
}
return this._isNotify ? AUSTLMY.NOTIFY : AUSTLMY.EXTERNAL;
- },
+ }
/**
* Checks for updates in the background.
@@ -3384,9 +3384,7 @@ UpdateService.prototype = {
* Whether or not a background update check was initiated by the
* application update timer notification.
*/
- _checkForBackgroundUpdates: function AUS__checkForBackgroundUpdates(
- isNotify
- ) {
+ _checkForBackgroundUpdates(isNotify) {
if (!this.disabled && AppConstants.NIGHTLY_BUILD) {
// Scalar ID: update.suppress_prompts
AUSTLMY.pingSuppressPrompts();
@@ -3584,7 +3582,7 @@ UpdateService.prototype = {
})();
return true;
- },
+ }
/**
* Determine the update from the specified updates that should be offered.
@@ -3594,7 +3592,7 @@ UpdateService.prototype = {
* An array of available nsIUpdate items
* @return The nsIUpdate to offer.
*/
- selectUpdate: function AUS_selectUpdate(updates) {
+ selectUpdate(updates) {
if (!updates.length) {
AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_NO_UPDATE_FOUND);
return null;
@@ -3753,7 +3751,7 @@ UpdateService.prototype = {
}
return update;
- },
+ }
/**
* Determine which of the specified updates should be installed and begin the
@@ -3761,7 +3759,7 @@ UpdateService.prototype = {
* @param updates
* An array of available updates
*/
- _selectAndInstallUpdate: async function AUS__selectAndInstallUpdate(updates) {
+ async _selectAndInstallUpdate(updates) {
// Return early if there's an active update. The user is already aware and
// is downloading or performed some user action to prevent notification.
if (lazy.UM.downloadingUpdate) {
@@ -3842,14 +3840,14 @@ UpdateService.prototype = {
cleanupDownloadingUpdate();
}
AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_DOWNLOAD_UPDATE);
- },
+ }
/**
* See nsIUpdateService.idl
*/
get isAppBaseDirWritable() {
return isAppBaseDirWritable();
- },
+ }
get disabledForTesting() {
return (
@@ -3858,7 +3856,7 @@ UpdateService.prototype = {
lazy.RemoteAgent.running) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_DISABLEDFORTESTING, false)
);
- },
+ }
/**
* See nsIUpdateService.idl
@@ -3869,7 +3867,7 @@ UpdateService.prototype = {
this.disabledForTesting ||
Services.sysinfo.getProperty("isPackagedApp")
);
- },
+ }
/**
* See nsIUpdateService.idl
@@ -3878,7 +3876,7 @@ UpdateService.prototype = {
return (
Services.policies && !Services.policies.isAllowed("autoAppUpdateChecking")
);
- },
+ }
/**
* See nsIUpdateService.idl
@@ -3912,7 +3910,7 @@ UpdateService.prototype = {
LOG("UpdateService.canUsuallyCheckForUpdates - able to check for updates");
return true;
- },
+ }
/**
* See nsIUpdateService.idl
@@ -3941,21 +3939,21 @@ UpdateService.prototype = {
LOG("UpdateService.canCheckForUpdates - able to check for updates");
return true;
- },
+ }
/**
* See nsIUpdateService.idl
*/
get elevationRequired() {
return getElevationRequired();
- },
+ }
/**
* See nsIUpdateService.idl
*/
get canUsuallyApplyUpdates() {
return getCanApplyUpdates();
- },
+ }
/**
* See nsIUpdateService.idl
@@ -3966,42 +3964,42 @@ UpdateService.prototype = {
hasUpdateMutex() &&
!isOtherInstanceRunning()
);
- },
+ }
/**
* See nsIUpdateService.idl
*/
get canUsuallyStageUpdates() {
return getCanStageUpdates(false);
- },
+ }
/**
* See nsIUpdateService.idl
*/
get canStageUpdates() {
return getCanStageUpdates();
- },
+ }
/**
* See nsIUpdateService.idl
*/
get canUsuallyUseBits() {
return getCanUseBits(false) == "CanUseBits";
- },
+ }
/**
* See nsIUpdateService.idl
*/
get canUseBits() {
return getCanUseBits() == "CanUseBits";
- },
+ }
/**
* See nsIUpdateService.idl
*/
get isOtherInstanceHandlingUpdates() {
return !hasUpdateMutex() || isOtherInstanceRunning();
- },
+ }
/**
* A set of download listeners to be notified by this._downloader when it
@@ -4010,12 +4008,12 @@ UpdateService.prototype = {
* These are stored on the UpdateService rather than on the Downloader,
* because they ought to persist across multiple Downloader instances.
*/
- _downloadListeners: new Set(),
+ _downloadListeners = new Set();
/**
* See nsIUpdateService.idl
*/
- addDownloadListener: function AUS_addDownloadListener(listener) {
+ addDownloadListener(listener) {
let oldSize = this._downloadListeners.size;
this._downloadListeners.add(listener);
@@ -4030,12 +4028,12 @@ UpdateService.prototype = {
if (this._downloader) {
this._downloader.onDownloadListenerAdded();
}
- },
+ }
/**
* See nsIUpdateService.idl
*/
- removeDownloadListener: function AUS_removeDownloadListener(listener) {
+ removeDownloadListener(listener) {
let elementRemoved = this._downloadListeners.delete(listener);
if (!elementRemoved) {
@@ -4049,29 +4047,29 @@ UpdateService.prototype = {
if (this._downloader) {
this._downloader.onDownloadListenerRemoved();
}
- },
+ }
/**
* Returns a boolean indicating whether there are any download listeners
*/
get hasDownloadListeners() {
return !!this._downloadListeners.length;
- },
+ }
/*
* Calls the provided function once with each download listener that is
* currently registered.
*/
- forEachDownloadListener: function AUS_forEachDownloadListener(fn) {
+ forEachDownloadListener(fn) {
// Make a shallow copy in case listeners remove themselves.
let listeners = new Set(this._downloadListeners);
listeners.forEach(fn);
- },
+ }
/**
* See nsIUpdateService.idl
*/
- downloadUpdate: async function AUS_downloadUpdate(update) {
+ async downloadUpdate(update) {
if (!update) {
throw Components.Exception("", Cr.NS_ERROR_NULL_POINTER);
}
@@ -4133,12 +4131,12 @@ UpdateService.prototype = {
}
this._downloader = new Downloader(this);
return this._downloader.downloadUpdate(update);
- },
+ }
/**
* See nsIUpdateService.idl
*/
- stopDownload: async function AUS_stopDownload() {
+ async stopDownload() {
if (this.isDownloading) {
await this._downloader.cancel();
} else if (this._retryTimer) {
@@ -4154,7 +4152,7 @@ UpdateService.prototype = {
await this._downloader.cleanup();
}
this._downloader = null;
- },
+ }
/**
* Note that this is different from checking if `currentState` is
@@ -4163,9 +4161,9 @@ UpdateService.prototype = {
*/
get isDownloading() {
return this._downloader && this._downloader.isBusy;
- },
+ }
- _logStatus: function AUS__logStatus() {
+ _logStatus() {
if (!lazy.UpdateLog.enabled) {
return;
}
@@ -4211,21 +4209,21 @@ UpdateService.prototype = {
}
}
LOG("End of UpdateService status");
- },
+ }
/**
* See nsIUpdateService.idl
*/
get onlyDownloadUpdatesThisSession() {
return gOnlyDownloadUpdatesThisSession;
- },
+ }
/**
* See nsIUpdateService.idl
*/
set onlyDownloadUpdatesThisSession(newValue) {
gOnlyDownloadUpdatesThisSession = newValue;
- },
+ }
/**
* See nsIUpdateService.idl
@@ -4244,129 +4242,129 @@ UpdateService.prototype = {
return "STATE_SWAP";
}
return `[unknown update state: ${state}]`;
- },
+ }
/**
* See nsIUpdateService.idl
*/
get currentState() {
return gUpdateState;
- },
+ }
/**
* See nsIUpdateService.idl
*/
get stateTransition() {
return gStateTransitionPromise.promise;
- },
-
- classID: UPDATESERVICE_CID,
-
- QueryInterface: ChromeUtils.generateQI([
- "nsIApplicationUpdateService",
- "nsITimerCallback",
- "nsIObserver",
- ]),
-};
-
-/**
- * A service to manage active and past updates.
- * @constructor
- */
-export function UpdateManager() {
- // Load the active-update.xml file to see if there is an active update.
- let activeUpdates = this._loadXMLFileIntoArray(FILE_ACTIVE_UPDATE_XML);
- if (activeUpdates.length) {
- // Set the active update directly on the var used to cache the value.
- this._readyUpdate = activeUpdates[0];
- if (activeUpdates.length >= 2) {
- this._downloadingUpdate = activeUpdates[1];
- }
- let status = readStatusFile(getReadyUpdateDir());
- LOG(`UpdateManager:UpdateManager - status = "${status}"`);
- // This check is performed here since UpdateService:_postUpdateProcessing
- // won't be called when there isn't an update.status file.
- if (status == STATE_NONE) {
- // Under some edgecases such as Windows system restore the
- // active-update.xml will contain a pending update without the status
- // file. To recover from this situation clean the updates dir and move
- // the active update to the update history.
- LOG(
- "UpdateManager:UpdateManager - Found update data with no status " +
- "file. Cleaning up..."
- );
- this._readyUpdate.state = STATE_FAILED;
- this._readyUpdate.errorCode = ERR_UPDATE_STATE_NONE;
- this._readyUpdate.statusText =
- lazy.gUpdateBundle.GetStringFromName("statusFailed");
- let newStatus = STATE_FAILED + ": " + ERR_UPDATE_STATE_NONE;
- pingStateAndStatusCodes(this._readyUpdate, true, newStatus);
- this.addUpdateToHistory(this._readyUpdate);
- this._readyUpdate = null;
- this.saveUpdates();
- cleanUpReadyUpdateDir();
- cleanUpDownloadingUpdateDir();
- } else if (status == STATE_DOWNLOADING) {
- // The first update we read out of activeUpdates may not be the ready
- // update, it may be the downloading update.
- if (this._downloadingUpdate) {
- // If the first update we read is a downloading update, it's
- // unexpected to have read another active update. That would seem to
- // indicate that we were downloading two updates at once, which we don't
- // do.
- LOG(
- "UpdateManager:UpdateManager - Warning: Found and discarded a " +
- "second downloading update."
- );
- }
- this._downloadingUpdate = this._readyUpdate;
- this._readyUpdate = null;
- }
}
- LOG(
- "UpdateManager:UpdateManager - Initialized downloadingUpdate to " +
- this._downloadingUpdate
- );
- if (this._downloadingUpdate) {
- LOG(
- "UpdateManager:UpdateManager - Initialized downloadingUpdate state to " +
- this._downloadingUpdate.state
- );
- }
- LOG(
- "UpdateManager:UpdateManager - Initialized readyUpdate to " +
- this._readyUpdate
- );
- if (this._readyUpdate) {
- LOG(
- "UpdateManager:UpdateManager - Initialized readyUpdate state to " +
- this._readyUpdate.state
- );
- }
+ classID = UPDATESERVICE_CID;
+
+ QueryInterface = ChromeUtils.generateQI([
+ Ci.nsIApplicationUpdateService,
+ Ci.nsITimerCallback,
+ Ci.nsIObserver,
+ ]);
}
-UpdateManager.prototype = {
+export class UpdateManager {
/**
* The nsIUpdate object for the update that has been downloaded.
*/
- _readyUpdate: null,
+ _readyUpdate = null;
/**
* The nsIUpdate object for the update currently being downloaded.
*/
- _downloadingUpdate: null,
+ _downloadingUpdate = null;
/**
* Whether the update history stored in _updates has changed since it was
* loaded.
*/
- _updatesDirty: false,
+ _updatesDirty = false;
+
+ /**
+ * A service to manage active and past updates.
+ * @constructor
+ */
+ constructor() {
+ // Load the active-update.xml file to see if there is an active update.
+ let activeUpdates = this._loadXMLFileIntoArray(FILE_ACTIVE_UPDATE_XML);
+ if (activeUpdates.length) {
+ // Set the active update directly on the var used to cache the value.
+ this._readyUpdate = activeUpdates[0];
+ if (activeUpdates.length >= 2) {
+ this._downloadingUpdate = activeUpdates[1];
+ }
+ let status = readStatusFile(getReadyUpdateDir());
+ LOG(`UpdateManager:UpdateManager - status = "${status}"`);
+ // This check is performed here since UpdateService:_postUpdateProcessing
+ // won't be called when there isn't an update.status file.
+ if (status == STATE_NONE) {
+ // Under some edgecases such as Windows system restore the
+ // active-update.xml will contain a pending update without the status
+ // file. To recover from this situation clean the updates dir and move
+ // the active update to the update history.
+ LOG(
+ "UpdateManager:UpdateManager - Found update data with no status " +
+ "file. Cleaning up..."
+ );
+ this._readyUpdate.state = STATE_FAILED;
+ this._readyUpdate.errorCode = ERR_UPDATE_STATE_NONE;
+ this._readyUpdate.statusText =
+ lazy.gUpdateBundle.GetStringFromName("statusFailed");
+ let newStatus = STATE_FAILED + ": " + ERR_UPDATE_STATE_NONE;
+ pingStateAndStatusCodes(this._readyUpdate, true, newStatus);
+ this.addUpdateToHistory(this._readyUpdate);
+ this._readyUpdate = null;
+ this.saveUpdates();
+ cleanUpReadyUpdateDir();
+ cleanUpDownloadingUpdateDir();
+ } else if (status == STATE_DOWNLOADING) {
+ // The first update we read out of activeUpdates may not be the ready
+ // update, it may be the downloading update.
+ if (this._downloadingUpdate) {
+ // If the first update we read is a downloading update, it's
+ // unexpected to have read another active update. That would seem to
+ // indicate that we were downloading two updates at once, which we don't
+ // do.
+ LOG(
+ "UpdateManager:UpdateManager - Warning: Found and discarded a " +
+ "second downloading update."
+ );
+ }
+ this._downloadingUpdate = this._readyUpdate;
+ this._readyUpdate = null;
+ }
+ }
+
+ LOG(
+ "UpdateManager:UpdateManager - Initialized downloadingUpdate to " +
+ this._downloadingUpdate
+ );
+ if (this._downloadingUpdate) {
+ LOG(
+ "UpdateManager:UpdateManager - Initialized downloadingUpdate state to " +
+ this._downloadingUpdate.state
+ );
+ }
+ LOG(
+ "UpdateManager:UpdateManager - Initialized readyUpdate to " +
+ this._readyUpdate
+ );
+ if (this._readyUpdate) {
+ LOG(
+ "UpdateManager:UpdateManager - Initialized readyUpdate state to " +
+ this._readyUpdate.state
+ );
+ }
+ }
/**
* See nsIObserver.idl
*/
- observe: function UM_observe(subject, topic, data) {
+ observe(subject, topic, data) {
// Hack to be able to run and cleanup tests by reloading the update data.
if (topic == "um-reload-update-data") {
if (!Cu.isInAutomation) {
@@ -4431,7 +4429,7 @@ UpdateManager.prototype = {
);
}
}
- },
+ }
/**
* Loads an updates.xml formatted file into an array of nsIUpdate items.
@@ -4439,7 +4437,7 @@ UpdateManager.prototype = {
* The file name in the updates directory to load.
* @return The array of nsIUpdate items held in the file.
*/
- _loadXMLFileIntoArray: function UM__loadXMLFileIntoArray(fileName) {
+ _loadXMLFileIntoArray(fileName) {
let updates = [];
let file = getUpdateFile([fileName]);
if (!file.exists()) {
@@ -4528,7 +4526,7 @@ UpdateManager.prototype = {
}
}
return updates;
- },
+ }
/**
* Loads the update history from the updates.xml file into a cache.
@@ -4538,41 +4536,41 @@ UpdateManager.prototype = {
this._updatesCache = this._loadXMLFileIntoArray(FILE_UPDATES_XML);
}
return this._updatesCache;
- },
+ }
/**
* See nsIUpdateService.idl
*/
- getUpdateAt: function UM_getUpdateAt(aIndex) {
+ getUpdateAt(aIndex) {
return this._getUpdates()[aIndex];
- },
+ }
/**
* See nsIUpdateService.idl
*/
getUpdateCount() {
return this._getUpdates().length;
- },
+ }
/**
* See nsIUpdateService.idl
*/
get readyUpdate() {
return this._readyUpdate;
- },
+ }
set readyUpdate(aUpdate) {
this._readyUpdate = aUpdate;
- },
+ }
/**
* See nsIUpdateService.idl
*/
get downloadingUpdate() {
return this._downloadingUpdate;
- },
+ }
set downloadingUpdate(aUpdate) {
this._downloadingUpdate = aUpdate;
- },
+ }
/**
* See nsIUpdateService.idl
@@ -4583,7 +4581,7 @@ UpdateManager.prototype = {
updates.unshift(aUpdate);
// Limit the update history to 10 updates.
updates.splice(10);
- },
+ }
/**
* Serializes an array of updates to an XML file or removes the file if the
@@ -4594,10 +4592,7 @@ UpdateManager.prototype = {
* The file name in the updates directory to write to.
* @return true on success, false on error
*/
- _writeUpdatesToXMLFile: async function UM__writeUpdatesToXMLFile(
- updates,
- fileName
- ) {
+ async _writeUpdatesToXMLFile(updates, fileName) {
let file;
try {
file = getUpdateFile([fileName]);
@@ -4656,14 +4651,14 @@ UpdateManager.prototype = {
return false;
}
return true;
- },
+ }
- _updatesXMLSaver: null,
- _updatesXMLSaverCallback: null,
+ _updatesXMLSaver = null;
+ _updatesXMLSaverCallback = null;
/**
* See nsIUpdateService.idl
*/
- saveUpdates: function UM_saveUpdates() {
+ saveUpdates() {
if (!this._updatesXMLSaver) {
this._updatesXMLSaverCallback = () => this._updatesXMLSaver.finalize();
@@ -4680,13 +4675,13 @@ UpdateManager.prototype = {
}
this._updatesXMLSaver.arm();
- },
+ }
/**
* Saves the active-updates.xml and updates.xml when the updates history has
* been modified files.
*/
- _saveUpdatesXML: function UM__saveUpdatesXML() {
+ _saveUpdatesXML() {
// This mechanism for how we store the updates might seem a bit odd, since,
// if only one update is stored, we don't know if it's the ready update or
// the downloading update. However, we can determine which it is by reading
@@ -4718,12 +4713,12 @@ UpdateManager.prototype = {
);
}
return Promise.all(promises);
- },
+ }
/**
* See nsIUpdateService.idl
*/
- refreshUpdateStatus: async function UM_refreshUpdateStatus() {
+ async refreshUpdateStatus() {
try {
LOG("UpdateManager:refreshUpdateStatus - Staging done.");
@@ -4855,12 +4850,12 @@ UpdateManager.prototype = {
transitionState(Ci.nsIApplicationUpdateService.STATE_IDLE);
}
}
- },
+ }
/**
* See nsIUpdateService.idl
*/
- elevationOptedIn: function UM_elevationOptedIn() {
+ elevationOptedIn() {
// The user has been been made aware that the update requires elevation.
let update = this._readyUpdate;
if (!update) {
@@ -4884,30 +4879,30 @@ UpdateManager.prototype = {
} else {
LOG("UpdateManager:elevationOptedIn - Not in pending-elevate state.");
}
- },
+ }
/**
* See nsIUpdateService.idl
*/
- cleanupDownloadingUpdate: function UM_cleanupDownloadingUpdate() {
+ cleanupDownloadingUpdate() {
LOG(
"UpdateManager:cleanupDownloadingUpdate - cleaning up downloading update."
);
cleanupDownloadingUpdate();
- },
+ }
/**
* See nsIUpdateService.idl
*/
- cleanupReadyUpdate: function UM_cleanupReadyUpdate() {
+ cleanupReadyUpdate() {
LOG("UpdateManager:cleanupReadyUpdate - cleaning up ready update.");
cleanupReadyUpdate();
- },
+ }
/**
* See nsIUpdateService.idl
*/
- doInstallCleanup: async function UM_doInstallCleanup() {
+ async doInstallCleanup() {
LOG("UpdateManager:doInstallCleanup - cleaning up");
let completionPromises = [];
@@ -4944,12 +4939,12 @@ UpdateManager.prototype = {
}
return Promise.allSettled(completionPromises);
- },
+ }
/**
* See nsIUpdateService.idl
*/
- doUninstallCleanup: async function UM_doUninstallCleanup() {
+ async doUninstallCleanup() {
LOG("UpdateManager:doUninstallCleanup - cleaning up.");
let completionPromises = [];
@@ -4965,11 +4960,14 @@ UpdateManager.prototype = {
);
return Promise.allSettled(completionPromises);
- },
+ }
- classID: Components.ID("{093C2356-4843-4C65-8709-D7DBCBBE7DFB}"),
- QueryInterface: ChromeUtils.generateQI(["nsIUpdateManager", "nsIObserver"]),
-};
+ classID = Components.ID("{093C2356-4843-4C65-8709-D7DBCBBE7DFB}");
+ QueryInterface = ChromeUtils.generateQI([
+ Ci.nsIUpdateManager,
+ Ci.nsIObserver,
+ ]);
+}
/**
* CheckerService
@@ -5199,7 +5197,7 @@ export class CheckerService {
return {
id: checkId,
result: this.#updateCheckData[requestKey].promise,
- QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheck"]),
+ QueryInterface: ChromeUtils.generateQI([Ci.nsIUpdateCheck]),
};
}
@@ -5212,10 +5210,10 @@ export class CheckerService {
succeeded: false,
request: null,
updates: [],
- QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheckResult"]),
+ QueryInterface: ChromeUtils.generateQI([Ci.nsIUpdateCheckResult]),
})
),
- QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheck"]),
+ QueryInterface: ChromeUtils.generateQI([Ci.nsIUpdateCheck]),
};
}
@@ -5370,7 +5368,7 @@ export class CheckerService {
succeeded: true,
request,
updates,
- QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheckResult"]),
+ QueryInterface: ChromeUtils.generateQI([Ci.nsIUpdateCheckResult]),
});
}
@@ -5408,7 +5406,7 @@ export class CheckerService {
succeeded: false,
request,
updates: [update],
- QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheckResult"]),
+ QueryInterface: ChromeUtils.generateQI([Ci.nsIUpdateCheckResult]),
});
}
@@ -5523,51 +5521,38 @@ export class CheckerService {
}
classID = Components.ID("{898CDC9B-E43F-422F-9CC4-2F6291B415A3}");
- QueryInterface = ChromeUtils.generateQI(["nsIUpdateChecker"]);
+ QueryInterface = ChromeUtils.generateQI([Ci.nsIUpdateChecker]);
}
-/**
- * Manages the download of updates
- * @param background
- * Whether or not this downloader is operating in background
- * update mode.
- * @param updateService
- * The update service that created this downloader.
- * @constructor
- */
-function Downloader(updateService) {
- LOG("Creating Downloader");
- this.updateService = updateService;
-}
-Downloader.prototype = {
+class Downloader {
/**
* The nsIUpdatePatch that we are downloading
*/
- _patch: null,
+ _patch = null;
/**
* The nsIUpdate that we are downloading
*/
- _update: null,
+ _update = null;
/**
* The nsIRequest object handling the download.
*/
- _request: null,
+ _request = null;
/**
* Whether or not the update being downloaded is a complete replacement of
* the user's existing installation or a patch representing the difference
* between the new version and the previous version.
*/
- isCompleteUpdate: null,
+ isCompleteUpdate = null;
/**
* We get the nsIRequest from nsIBITS asynchronously. When downloadUpdate has
* been called, but this._request is not yet valid, _pendingRequest will be
* a promise that will resolve when this._request has been set.
*/
- _pendingRequest: null,
+ _pendingRequest = null;
/**
* When using BITS, cancel actions happen asynchronously. This variable
@@ -5577,7 +5562,7 @@ Downloader.prototype = {
* resolved promise will remain stored in this variable to prevent cancel
* from being called twice (which, for BITS, is an error).
*/
- _cancelPromise: null,
+ _cancelPromise = null;
/**
* BITS receives progress notifications slowly, unless a user is watching.
@@ -5591,14 +5576,14 @@ Downloader.prototype = {
* we don't know if we need to start Active mode when _pendingRequest
* resolves.
*/
- _bitsActiveNotifications: false,
+ _bitsActiveNotifications = false;
/**
* This is a function that when called will stop the update process from
* waiting for language pack updates. This is for safety to ensure that a
* problem in the add-ons manager doesn't delay updates by much.
*/
- _langPackTimeout: null,
+ _langPackTimeout = null;
/**
* If gOnlyDownloadUpdatesThisSession is true, we prevent the update process
@@ -5606,7 +5591,21 @@ Downloader.prototype = {
* pretend that it hasn't in order to keep the current update in the
* "downloading" state.
*/
- _pretendingDownloadIsNotDone: false,
+ _pretendingDownloadIsNotDone = false;
+
+ /**
+ * Manages the download of updates
+ * @param background
+ * Whether or not this downloader is operating in background
+ * update mode.
+ * @param updateService
+ * The update service that created this downloader.
+ * @constructor
+ */
+ constructor(updateService) {
+ LOG("Creating Downloader");
+ this.updateService = updateService;
+ }
/**
* Cancels the active download.
@@ -5615,7 +5614,7 @@ Downloader.prototype = {
* an nsIIncrementalDownload, this will stop the download, but leaves the
* data around to allow the transfer to be resumed later.
*/
- cancel: async function Downloader_cancel(cancelError) {
+ async cancel(cancelError) {
LOG("Downloader: cancel");
if (cancelError === undefined) {
cancelError = Cr.NS_BINDING_ABORTED;
@@ -5664,13 +5663,13 @@ Downloader.prototype = {
this._request.cancel(cancelError);
}
}
- },
+ }
/**
* Verify the downloaded file. We assume that the download is complete at
* this point.
*/
- _verifyDownload: function Downloader__verifyDownload() {
+ _verifyDownload() {
LOG("Downloader:_verifyDownload called");
if (!this._request) {
AUSTLMY.pingDownloadCode(
@@ -5695,7 +5694,7 @@ Downloader.prototype = {
LOG("Downloader:_verifyDownload downloaded size == expected size.");
return true;
- },
+ }
/**
* Select the patch to use given the current state of updateDir and the given
@@ -5704,7 +5703,7 @@ Downloader.prototype = {
* A nsIUpdate object to select a patch from
* @return A nsIUpdatePatch object to download
*/
- _selectPatch: function Downloader__selectPatch(update) {
+ _selectPatch(update) {
// Given an update to download, we will always try to download the patch
// for a partial update over the patch for a full update.
@@ -5809,7 +5808,7 @@ Downloader.prototype = {
lazy.UM.downloadingUpdate = update;
return selectedPatch;
- },
+ }
/**
* Whether or not the user wants to be notified that an update is being
@@ -5820,35 +5819,30 @@ Downloader.prototype = {
PREF_APP_UPDATE_NOTIFYDURINGDOWNLOAD,
false
);
- },
-
- _notifyDownloadStatusObservers:
- function Downloader_notifyDownloadStatusObservers() {
- if (this._notifyDuringDownload) {
- let status = this.updateService.isDownloading ? "downloading" : "idle";
- Services.obs.notifyObservers(
- this._update,
- "update-downloading",
- status
- );
- }
- },
+ }
+
+ _notifyDownloadStatusObservers() {
+ if (this._notifyDuringDownload) {
+ let status = this.updateService.isDownloading ? "downloading" : "idle";
+ Services.obs.notifyObservers(this._update, "update-downloading", status);
+ }
+ }
/**
* Whether or not we are currently downloading something.
*/
get isBusy() {
return this._request != null || this._pendingRequest != null;
- },
+ }
get usingBits() {
return this._pendingRequest != null || this._request instanceof BitsRequest;
- },
+ }
/**
* Returns true if the specified patch can be downloaded with BITS.
*/
- _canUseBits: function Downloader__canUseBits(patch) {
+ _canUseBits(patch) {
if (getCanUseBits() != "CanUseBits") {
// This will have printed its own logging. No need to print more.
return false;
@@ -5863,13 +5857,13 @@ Downloader.prototype = {
}
LOG("Downloader:_canUseBits - Patch is able to use BITS download");
return true;
- },
+ }
/**
* Instruct the add-ons manager to start downloading language pack updates in
* preparation for the current update.
*/
- _startLangPackUpdates: function Downloader__startLangPackUpdates() {
+ _startLangPackUpdates() {
if (!Services.prefs.getBoolPref(PREF_APP_UPDATE_LANGPACK_ENABLED, false)) {
return;
}
@@ -5912,14 +5906,14 @@ Downloader.prototype = {
update,
Promise.race([langPackPromise, timeoutPromise])
);
- },
+ }
/**
* Download and stage the given update.
* @param update
* A nsIUpdate object to download a patch for. Cannot be null.
*/
- downloadUpdate: async function Downloader_downloadUpdate(update) {
+ async downloadUpdate(update) {
LOG("UpdateService:downloadUpdate");
if (!update) {
AUSTLMY.pingDownloadCode(undefined, AUSTLMY.DWNLD_ERR_NO_UPDATE);
@@ -6190,116 +6184,114 @@ Downloader.prototype = {
this._notifyDownloadStatusObservers();
return true;
- },
+ }
/**
* This is run when a download listener is added.
*/
- onDownloadListenerAdded: function Downloader_onDownloadListenerAdded() {
+ onDownloadListenerAdded() {
// Increase the status update frequency when someone starts listening
this._maybeStartActiveNotifications();
- },
+ }
/**
* This is run when a download listener is removed.
*/
- onDownloadListenerRemoved: function Downloader_onDownloadListenerRemoved() {
+ onDownloadListenerRemoved() {
// Decrease the status update frequency when no one is listening
if (!this.hasDownloadListeners) {
this._maybeStopActiveNotifications();
}
- },
+ }
get hasDownloadListeners() {
return this.updateService.hasDownloadListeners;
- },
+ }
/**
* This speeds up BITS progress notifications in response to a user watching
* the notifications.
*/
- _maybeStartActiveNotifications:
- async function Downloader__maybeStartActiveNotifications() {
- if (
- this.usingBits &&
- !this._bitsActiveNotifications &&
- this.hasDownloadListeners &&
+ async _maybeStartActiveNotifications() {
+ if (
+ this.usingBits &&
+ !this._bitsActiveNotifications &&
+ this.hasDownloadListeners &&
+ this._request
+ ) {
+ LOG(
+ "Downloader:_maybeStartActiveNotifications - Starting active " +
+ "notifications"
+ );
+ this._bitsActiveNotifications = true;
+ await Promise.all([
this._request
- ) {
- LOG(
- "Downloader:_maybeStartActiveNotifications - Starting active " +
- "notifications"
- );
- this._bitsActiveNotifications = true;
- await Promise.all([
- this._request
- .setNoProgressTimeout(BITS_ACTIVE_NO_PROGRESS_TIMEOUT_SECS)
- .catch(error => {
- LOG(
- "Downloader:_maybeStartActiveNotifications - Failed to set " +
- "no progress timeout. Error: " +
- error
- );
- }),
- this._request
- .changeMonitorInterval(BITS_ACTIVE_POLL_RATE_MS)
- .catch(error => {
- LOG(
- "Downloader:_maybeStartActiveNotifications - Failed to increase " +
- "status update frequency. Error: " +
- error
- );
- }),
- ]);
- }
- },
+ .setNoProgressTimeout(BITS_ACTIVE_NO_PROGRESS_TIMEOUT_SECS)
+ .catch(error => {
+ LOG(
+ "Downloader:_maybeStartActiveNotifications - Failed to set " +
+ "no progress timeout. Error: " +
+ error
+ );
+ }),
+ this._request
+ .changeMonitorInterval(BITS_ACTIVE_POLL_RATE_MS)
+ .catch(error => {
+ LOG(
+ "Downloader:_maybeStartActiveNotifications - Failed to increase " +
+ "status update frequency. Error: " +
+ error
+ );
+ }),
+ ]);
+ }
+ }
/**
* This slows down BITS progress notifications in response to a user no longer
* watching the notifications.
*/
- _maybeStopActiveNotifications:
- async function Downloader__maybeStopActiveNotifications() {
- if (
- this.usingBits &&
- this._bitsActiveNotifications &&
- !this.hasDownloadListeners &&
+ async _maybeStopActiveNotifications() {
+ if (
+ this.usingBits &&
+ this._bitsActiveNotifications &&
+ !this.hasDownloadListeners &&
+ this._request
+ ) {
+ LOG(
+ "Downloader:_maybeStopActiveNotifications - Stopping active " +
+ "notifications"
+ );
+ this._bitsActiveNotifications = false;
+ await Promise.all([
this._request
- ) {
- LOG(
- "Downloader:_maybeStopActiveNotifications - Stopping active " +
- "notifications"
- );
- this._bitsActiveNotifications = false;
- await Promise.all([
- this._request
- .setNoProgressTimeout(BITS_IDLE_NO_PROGRESS_TIMEOUT_SECS)
- .catch(error => {
- LOG(
- "Downloader:_maybeStopActiveNotifications - Failed to set " +
- "no progress timeout: " +
- error
- );
- }),
- this._request
- .changeMonitorInterval(BITS_IDLE_POLL_RATE_MS)
- .catch(error => {
- LOG(
- "Downloader:_maybeStopActiveNotifications - Failed to decrease " +
- "status update frequency: " +
- error
- );
- }),
- ]);
- }
- },
+ .setNoProgressTimeout(BITS_IDLE_NO_PROGRESS_TIMEOUT_SECS)
+ .catch(error => {
+ LOG(
+ "Downloader:_maybeStopActiveNotifications - Failed to set " +
+ "no progress timeout: " +
+ error
+ );
+ }),
+ this._request
+ .changeMonitorInterval(BITS_IDLE_POLL_RATE_MS)
+ .catch(error => {
+ LOG(
+ "Downloader:_maybeStopActiveNotifications - Failed to decrease " +
+ "status update frequency: " +
+ error
+ );
+ }),
+ ]);
+ }
+ }
/**
* When the async request begins
* @param request
* The nsIRequest object for the transfer
*/
- onStartRequest: function Downloader_onStartRequest(request) {
+ onStartRequest(request) {
if (this.usingBits) {
LOG("Downloader:onStartRequest");
} else {
@@ -6319,7 +6311,7 @@ Downloader.prototype = {
this.updateService.forEachDownloadListener(listener => {
listener.onStartRequest(request);
});
- },
+ }
/**
* When new data has been downloaded
@@ -6330,7 +6322,7 @@ Downloader.prototype = {
* @param maxProgress
* The total number of bytes that must be transferred
*/
- onProgress: function Downloader_onProgress(request, progress, maxProgress) {
+ onProgress(request, progress, maxProgress) {
LOG("Downloader:onProgress - progress: " + progress + "/" + maxProgress);
if (progress > this._patch.size) {
@@ -6372,7 +6364,7 @@ Downloader.prototype = {
}
});
this.updateService._consecutiveSocketErrors = 0;
- },
+ }
/**
* When we have new status text
@@ -6383,7 +6375,7 @@ Downloader.prototype = {
* @param statusText
* Human readable version of |status|
*/
- onStatus: function Downloader_onStatus(request, status, statusText) {
+ onStatus(request, status, statusText) {
LOG(
"Downloader:onStatus - status: " + status + ", statusText: " + statusText
);
@@ -6393,7 +6385,7 @@ Downloader.prototype = {
listener.onStatus(request, status, statusText);
}
});
- },
+ }
/**
* When data transfer ceases
@@ -6403,7 +6395,7 @@ Downloader.prototype = {
* Status code containing the reason for the cessation.
*/
/* eslint-disable-next-line complexity */
- onStopRequest: async function Downloader_onStopRequest(request, status) {
+ async onStopRequest(request, status) {
if (gOnlyDownloadUpdatesThisSession) {
LOG(
"Downloader:onStopRequest - End of update download detected and " +
@@ -6936,25 +6928,25 @@ Downloader.prototype = {
// Prevent leaking the update object (bug 454964)
this._update = null;
}
- },
+ }
/**
* This function should be called when shutting down so that resources get
* freed properly.
*/
- cleanup: async function Downloader_cleanup() {
+ async cleanup() {
if (this.usingBits) {
if (this._pendingRequest) {
await this._pendingRequest;
}
this._request.shutdown();
}
- },
+ }
/**
* See nsIInterfaceRequestor.idl
*/
- getInterface: function Downloader_getInterface(iid) {
+ getInterface(iid) {
// The network request may require proxy authentication, so provide the
// default nsIAuthPrompt if requested.
if (iid.equals(Ci.nsIAuthPrompt)) {
@@ -6963,14 +6955,14 @@ Downloader.prototype = {
return prompt.QueryInterface(iid);
}
throw Components.Exception("", Cr.NS_NOINTERFACE);
- },
+ }
- QueryInterface: ChromeUtils.generateQI([
- "nsIRequestObserver",
- "nsIProgressEventSink",
- "nsIInterfaceRequestor",
- ]),
-};
+ QueryInterface = ChromeUtils.generateQI([
+ Ci.nsIRequestObserver,
+ Ci.nsIProgressEventSink,
+ Ci.nsIInterfaceRequestor,
+ ]);
+}
// On macOS, all browser windows can be closed without Firefox exiting. If it
// is left in this state for a while and an update is pending, we should restart
diff --git a/toolkit/mozapps/update/common/readstrings.cpp b/toolkit/mozapps/update/common/readstrings.cpp
index 28dc8ea6ff..4d09c9d9a4 100644
--- a/toolkit/mozapps/update/common/readstrings.cpp
+++ b/toolkit/mozapps/update/common/readstrings.cpp
@@ -144,7 +144,7 @@ int ReadStrings(const NS_tchar* path, const char* keyList,
size_t flen = size_t(len);
- char* fileContents = new char[flen + 1];
+ mozilla::UniquePtr<char[]> fileContents(new char[flen + 1]);
if (!fileContents) {
return READ_STRINGS_MEM_ERROR;
}
@@ -154,16 +154,15 @@ int ReadStrings(const NS_tchar* path, const char* keyList,
return READ_ERROR;
}
- size_t rd = fread(fileContents, sizeof(char), flen, fp);
+ size_t rd = fread(fileContents.get(), sizeof(char), flen, fp);
if (rd != flen) {
return READ_ERROR;
}
fileContents[flen] = '\0';
- int result = ReadStringsFromBuffer(fileContents, keyList, numStrings, results,
- section);
- delete[] fileContents;
+ int result = ReadStringsFromBuffer(fileContents.get(), keyList, numStrings,
+ results, section);
return result;
}
diff --git a/toolkit/mozapps/update/docs/MaintenanceServiceTests.rst b/toolkit/mozapps/update/docs/MaintenanceServiceTests.rst
index b954b572f8..65259c94d9 100644
--- a/toolkit/mozapps/update/docs/MaintenanceServiceTests.rst
+++ b/toolkit/mozapps/update/docs/MaintenanceServiceTests.rst
@@ -47,11 +47,11 @@ into the registry.
[HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4]
[HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4\0]
- "issuer"="DigiCert SHA2 Assured ID Code Signing CA"
+ "issuer"="DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1"
"name"="Mozilla Corporation"
[HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4\1]
- "issuer"="DigiCert Assured ID Code Signing CA-1"
+ "issuer"="DigiCert SHA2 Assured ID Code Signing CA"
"name"="Mozilla Corporation"
[HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4\2]
diff --git a/toolkit/mozapps/update/nsUpdateService.manifest b/toolkit/mozapps/update/nsUpdateService.manifest
index a8d2534b1e..6db9b00eb3 100644
--- a/toolkit/mozapps/update/nsUpdateService.manifest
+++ b/toolkit/mozapps/update/nsUpdateService.manifest
@@ -1 +1 @@
-category update-timer nsUpdateService @mozilla.org/updates/update-service;1,getService,background-update-timer,app.update.interval,43200,86400
+category update-timer nsUpdateService @mozilla.org/updates/update-service;1,getService,background-update-timer,app.update.interval,21600,86400
diff --git a/toolkit/mozapps/update/updater/Makefile.in b/toolkit/mozapps/update/updater/Makefile.in
index ec3ad9773a..f93a374428 100644
--- a/toolkit/mozapps/update/updater/Makefile.in
+++ b/toolkit/mozapps/update/updater/Makefile.in
@@ -5,6 +5,12 @@
# For changes here, also consider ./updater-xpcshell/Makefile.in
+# In a compile build, the moz.build stanzas produce the binary named
+# `UpdateSettings`; we just need it in the correct place.
+#
+# In an artifact build, we copy upstream artifacts from
+# `dist/update_framework_artifacts/UpdateSettings-localbuild.framework`
+
ifndef MOZ_WINCONSOLE
ifdef MOZ_DEBUG
MOZ_WINCONSOLE = 1
@@ -26,6 +32,11 @@ libs::
$(NSINSTALL) -D $(DIST)/bin/updater.app/Contents/MacOS
$(NSINSTALL) $(DIST)/bin/org.mozilla.updater $(DIST)/bin/updater.app/Contents/MacOS
$(NSINSTALL) -D $(DIST)/bin/updater.app/Contents/Frameworks
+ifneq (,$(COMPILE_ENVIRONMENT))
$(NSINSTALL) $(DIST)/bin/UpdateSettings $(DIST)/bin/updater.app/Contents/Frameworks/UpdateSettings.framework
+endif # COMPILE_ENVIRONMENT
+ifneq (,$(MOZ_ARTIFACT_BUILDS))
+ $(NSINSTALL) $(DIST)/update_framework_artifacts/UpdateSettings-localbuild.framework/UpdateSettings $(DIST)/bin/updater.app/Contents/Frameworks/UpdateSettings.framework
+endif # MOZ_ARTIFACT_BUILDS
$(NSINSTALL) $(srcdir)/macos-frameworks/UpdateSettings/Info.plist $(DIST)/bin/updater.app/Contents/Frameworks/UpdateSettings.framework/Resources
endif
diff --git a/toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/Makefile.in b/toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/Makefile.in
new file mode 100644
index 0000000000..2798eecd64
--- /dev/null
+++ b/toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/Makefile.in
@@ -0,0 +1,25 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+# 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/.
+
+include $(topsrcdir)/config/rules.mk
+
+# In a compile build, the moz.build stanzas produce a binary named
+# `UpdateSettings-localbuild`. We need to produce
+# `dist/update_framework_artifacts/UpdateSettings-localbuild.framework/UpdateSettings`
+# for consumption by artifact builds.
+#
+# In an artifact build, we already have upstream artifacts in
+# `dist/update_framework_artifacts/UpdateSettings-localbuild.framework`.
+
+ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
+libs::
+ifneq (,$(COMPILE_ENVIRONMENT))
+ rm -rf $(FINAL_TARGET)/UpdateSettings-localbuild.framework
+ $(NSINSTALL) -D $(FINAL_TARGET)/UpdateSettings-localbuild.framework
+ cp $(FINAL_TARGET)/UpdateSettings-localbuild UpdateSettings
+ $(NSINSTALL) UpdateSettings $(FINAL_TARGET)/UpdateSettings-localbuild.framework
+endif # COMPILE_ENVIRONMENT
+ $(NSINSTALL) $(srcdir)/../UpdateSettings/Info.plist $(FINAL_TARGET)/UpdateSettings-localbuild.framework/Resources
+endif # MOZ_WIDGET_TOOLKIT
diff --git a/toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/moz.build b/toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/moz.build
new file mode 100644
index 0000000000..ca3a0c9f1c
--- /dev/null
+++ b/toolkit/mozapps/update/updater/macos-frameworks/UpdateSettings-localbuild/moz.build
@@ -0,0 +1,18 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Framework("UpdateSettings-localbuild")
+FINAL_TARGET = "dist/update_framework_artifacts"
+
+DEFINES["ACCEPTED_MAR_CHANNEL_IDS"] = '""'
+
+UNIFIED_SOURCES += [
+ "../UpdateSettings/UpdateSettings.mm",
+]
+
+OS_LIBS += [
+ "-framework Foundation",
+]
diff --git a/toolkit/mozapps/update/updater/macos-frameworks/moz.build b/toolkit/mozapps/update/updater/macos-frameworks/moz.build
index 19fa11942e..cb49b680c0 100644
--- a/toolkit/mozapps/update/updater/macos-frameworks/moz.build
+++ b/toolkit/mozapps/update/updater/macos-frameworks/moz.build
@@ -7,7 +7,12 @@
with Files("**"):
BUG_COMPONENT = ("Toolkit", "Application Update")
-DIRS += ["UpdateSettings", "UpdateSettings-xpcshell", "UpdateSettings-WrongChannel"]
+DIRS += [
+ "UpdateSettings",
+ "UpdateSettings-localbuild",
+ "UpdateSettings-WrongChannel",
+ "UpdateSettings-xpcshell",
+]
EXPORTS += [
"UpdateSettingsUtil.h",
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index 084945dc44..81702d74bc 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -2992,7 +2992,7 @@ int NS_main(int argc, NS_tchar** argv) {
#ifdef MOZ_VERIFY_MAR_SIGNATURE
int rv = PopulategMARStrings();
if (rv == OK) {
- printf("Channels Allowed: %s\n", gMARStrings.MARChannelID.get());
+ printf("Channels Allowed: '%s'\n", gMARStrings.MARChannelID.get());
return 0;
}
printf("Error: %d\n", rv);