mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 10:33:33 +00:00
161 lines
5.7 KiB
JavaScript
161 lines
5.7 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent 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/. */
|
|
"use strict";
|
|
|
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
|
Cu.import("resource://gre/modules/AppConstants.jsm");
|
|
|
|
const RECOVERYSERVICE_CID = Components.ID("{b3caca5d-0bb0-48c6-912b-6be6cbf08832}");
|
|
const RECOVERYSERVICE_CONTRACTID = "@mozilla.org/recovery-service;1";
|
|
|
|
function log(msg) {
|
|
dump("-*- RecoveryService: " + msg + "\n");
|
|
}
|
|
|
|
const isGonk = AppConstants.platform === 'gonk';
|
|
|
|
if (isGonk) {
|
|
var librecovery = (function() {
|
|
let library;
|
|
try {
|
|
library = ctypes.open("librecovery.so");
|
|
} catch (e) {
|
|
log("Unable to open librecovery.so");
|
|
throw Cr.NS_ERROR_FAILURE;
|
|
}
|
|
// Bug 1163956, modify updatePath from ctyps.char.ptr to ctype.char.array(4096)
|
|
// align with librecovery.h. 4096 comes from PATH_MAX
|
|
let FotaUpdateStatus = new ctypes.StructType("FotaUpdateStatus", [
|
|
{ result: ctypes.int },
|
|
{ updatePath: ctypes.char.array(4096) }
|
|
]);
|
|
|
|
return {
|
|
factoryReset: library.declare("factoryReset",
|
|
ctypes.default_abi,
|
|
ctypes.int),
|
|
installFotaUpdate: library.declare("installFotaUpdate",
|
|
ctypes.default_abi,
|
|
ctypes.int,
|
|
ctypes.char.ptr,
|
|
ctypes.int),
|
|
|
|
FotaUpdateStatus: FotaUpdateStatus,
|
|
getFotaUpdateStatus: library.declare("getFotaUpdateStatus",
|
|
ctypes.default_abi,
|
|
ctypes.int,
|
|
FotaUpdateStatus.ptr)
|
|
};
|
|
})();
|
|
|
|
}
|
|
|
|
const gFactoryResetFile = "__post_reset_cmd__";
|
|
|
|
function RecoveryService() {}
|
|
|
|
RecoveryService.prototype = {
|
|
classID: RECOVERYSERVICE_CID,
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRecoveryService]),
|
|
classInfo: XPCOMUtils.generateCI({
|
|
classID: RECOVERYSERVICE_CID,
|
|
contractID: RECOVERYSERVICE_CONTRACTID,
|
|
interfaces: [Ci.nsIRecoveryService],
|
|
classDescription: "B2G Recovery Service"
|
|
}),
|
|
|
|
factoryReset: function RS_factoryReset(reason) {
|
|
if (!isGonk) {
|
|
Cr.NS_ERROR_FAILURE;
|
|
}
|
|
|
|
function doReset() {
|
|
// If this succeeds, then the device reboots and this never returns
|
|
if (librecovery.factoryReset() != 0) {
|
|
log("Error: Factory reset failed. Trying again after clearing cache.");
|
|
}
|
|
let cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
|
|
.getService(Ci.nsICacheStorageService);
|
|
cache.clear();
|
|
if (librecovery.factoryReset() != 0) {
|
|
log("Error: Factory reset failed again");
|
|
}
|
|
}
|
|
|
|
log("factoryReset " + reason);
|
|
let commands = [];
|
|
if (reason == "wipe") {
|
|
let volumeService = Cc["@mozilla.org/telephony/volume-service;1"]
|
|
.getService(Ci.nsIVolumeService);
|
|
let volNames = volumeService.getVolumeNames();
|
|
log("Found " + volNames.length + " volumes");
|
|
|
|
for (let i = 0; i < volNames.length; i++) {
|
|
let name = volNames.queryElementAt(i, Ci.nsISupportsString);
|
|
let volume = volumeService.getVolumeByName(name.data);
|
|
log("Got volume: " + name.data + " at " + volume.mountPoint);
|
|
commands.push("wipe " + volume.mountPoint);
|
|
}
|
|
} else if (reason == "root") {
|
|
commands.push("root");
|
|
}
|
|
|
|
if (commands.length > 0) {
|
|
Cu.import("resource://gre/modules/osfile.jsm");
|
|
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
|
dir.initWithPath("/persist");
|
|
var postResetFile = dir.exists() ?
|
|
OS.Path.join("/persist", gFactoryResetFile):
|
|
OS.Path.join("/cache", gFactoryResetFile);
|
|
let encoder = new TextEncoder();
|
|
let text = commands.join("\n");
|
|
let array = encoder.encode(text);
|
|
let promise = OS.File.writeAtomic(postResetFile, array,
|
|
{ tmpPath: postResetFile + ".tmp" });
|
|
|
|
promise.then(doReset, function onError(error) {
|
|
log("Error: " + error);
|
|
});
|
|
} else {
|
|
doReset();
|
|
}
|
|
},
|
|
|
|
installFotaUpdate: function RS_installFotaUpdate(updatePath) {
|
|
if (!isGonk) {
|
|
throw Cr.NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// If this succeeds, then the device reboots and this never returns
|
|
if (librecovery.installFotaUpdate(updatePath, updatePath.length) != 0) {
|
|
log("Error: FOTA install failed. Trying again after clearing cache.");
|
|
}
|
|
var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
|
cache.clear();
|
|
if (librecovery.installFotaUpdate(updatePath, updatePath.length) != 0) {
|
|
log("Error: FOTA install failed again");
|
|
}
|
|
},
|
|
|
|
getFotaUpdateStatus: function RS_getFotaUpdateStatus() {
|
|
let status = Ci.nsIRecoveryService.FOTA_UPDATE_UNKNOWN;
|
|
|
|
if (isGonk) {
|
|
let cStatus = librecovery.FotaUpdateStatus();
|
|
|
|
if (librecovery.getFotaUpdateStatus(cStatus.address()) == 0) {
|
|
status = cStatus.result;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
};
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RecoveryService]);
|