From af5fac74cc69d49d0d36d7e72daf4a8067514901 Mon Sep 17 00:00:00 2001 From: Alexandre Lissy Date: Fri, 6 May 2016 11:49:41 +0200 Subject: [PATCH] Bug 1284455 - Kill KillSwitch API r=me MozReview-Commit-ID: H3gY78tc1zw --HG-- extra : rebase_source : 703a9c189ae5f01d62533d338fea9202d3b47986 --- b2g/chrome/content/shell.js | 2 - b2g/components/B2GComponents.manifest | 4 - b2g/components/KillSwitch.js | 116 --- b2g/components/KillSwitchMain.jsm | 506 ------------ b2g/components/PersistentDataBlock.jsm | 766 ------------------ b2g/components/moz.build | 3 - .../test/mochitest/file_loadserver.js | 67 -- b2g/components/test/mochitest/killswitch.js | 149 ---- b2g/components/test/mochitest/mochitest.ini | 5 - .../mochitest/test_killswitch_basics.html | 92 --- .../mochitest/test_killswitch_disable.html | 65 -- .../mochitest/test_killswitch_enable.html | 65 -- b2g/components/test/unit/file_killswitch.js | 425 ---------- .../test/unit/file_persistentdatablock.js | 412 ---------- b2g/components/test/unit/test_killswitch.js | 108 --- .../test/unit/test_killswitch_gonk.js | 42 - .../unit/test_persistentdatablock_gonk.js | 21 - b2g/components/test/unit/xpcshell.ini | 18 - b2g/installer/package-manifest.in | 1 - dom/apps/PermissionsTable.jsm | 6 - dom/webidl/KillSwitch.webidl | 24 - dom/webidl/moz.build | 1 - modules/libpref/init/all.js | 2 - 23 files changed, 2900 deletions(-) delete mode 100644 b2g/components/KillSwitch.js delete mode 100644 b2g/components/KillSwitchMain.jsm delete mode 100644 b2g/components/PersistentDataBlock.jsm delete mode 100644 b2g/components/test/mochitest/file_loadserver.js delete mode 100644 b2g/components/test/mochitest/killswitch.js delete mode 100644 b2g/components/test/mochitest/test_killswitch_basics.html delete mode 100644 b2g/components/test/mochitest/test_killswitch_disable.html delete mode 100644 b2g/components/test/mochitest/test_killswitch_enable.html delete mode 100644 b2g/components/test/unit/file_killswitch.js delete mode 100644 b2g/components/test/unit/file_persistentdatablock.js delete mode 100644 b2g/components/test/unit/test_killswitch.js delete mode 100644 b2g/components/test/unit/test_killswitch_gonk.js delete mode 100644 b2g/components/test/unit/test_persistentdatablock_gonk.js delete mode 100644 dom/webidl/KillSwitch.webidl diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index 3f6a2d5d5bfa..e206f0e6ded1 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -22,8 +22,6 @@ if (isGonk) { Cu.import('resource://gre/modules/ResourceStatsService.jsm'); } -Cu.import('resource://gre/modules/KillSwitchMain.jsm'); - // Identity Cu.import('resource://gre/modules/SignInToWebsite.jsm'); SignInToWebsiteController.init(); diff --git a/b2g/components/B2GComponents.manifest b/b2g/components/B2GComponents.manifest index 40068547a8fc..99b7812e6b13 100644 --- a/b2g/components/B2GComponents.manifest +++ b/b2g/components/B2GComponents.manifest @@ -118,10 +118,6 @@ contract @mozilla.org/presentation-device/prompt;1 {4a300c26-e99b-4018-ab9b-c48c component {ccc8a839-0b64-422b-8a60-fb2af0e376d0} PresentationRequestUIGlue.js contract @mozilla.org/presentation/requestuiglue;1 {ccc8a839-0b64-422b-8a60-fb2af0e376d0} -# KillSwitch.js -component {b6eae5c6-971c-4772-89e5-5df626bf3f09} KillSwitch.js -contract @mozilla.org/moz-kill-switch;1 {b6eae5c6-971c-4772-89e5-5df626bf3f09} - # SystemMessageInternal.js component {70589ca5-91ac-4b9e-b839-d6a88167d714} SystemMessageInternal.js contract @mozilla.org/system-message-internal;1 {70589ca5-91ac-4b9e-b839-d6a88167d714} diff --git a/b2g/components/KillSwitch.js b/b2g/components/KillSwitch.js deleted file mode 100644 index 6f4649ca1ed3..000000000000 --- a/b2g/components/KillSwitch.js +++ /dev/null @@ -1,116 +0,0 @@ -/* 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 DEBUG = false; - -function debug(s) { - dump("-*- KillSwitch.js: " + s + "\n"); -} - -const {interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "Services", - "resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "cpmm", - "@mozilla.org/childprocessmessagemanager;1", - "nsIMessageSender"); - -const KILLSWITCH_CID = "{b6eae5c6-971c-4772-89e5-5df626bf3f09}"; -const KILLSWITCH_CONTRACTID = "@mozilla.org/moz-kill-switch;1"; - -const kEnableKillSwitch = "KillSwitch:Enable"; -const kEnableKillSwitchOK = "KillSwitch:Enable:OK"; -const kEnableKillSwitchKO = "KillSwitch:Enable:KO"; - -const kDisableKillSwitch = "KillSwitch:Disable"; -const kDisableKillSwitchOK = "KillSwitch:Disable:OK"; -const kDisableKillSwitchKO = "KillSwitch:Disable:KO"; - -function KillSwitch() { - this._window = null; -} - -KillSwitch.prototype = { - - __proto__: DOMRequestIpcHelper.prototype, - - init: function(aWindow) { - DEBUG && debug("init"); - this._window = aWindow; - this.initDOMRequestHelper(this._window); - }, - - enable: function() { - DEBUG && debug("KillSwitch: enable"); - - cpmm.addMessageListener(kEnableKillSwitchOK, this); - cpmm.addMessageListener(kEnableKillSwitchKO, this); - return this.createPromise((aResolve, aReject) => { - cpmm.sendAsyncMessage(kEnableKillSwitch, { - requestID: this.getPromiseResolverId({ - resolve: aResolve, - reject: aReject - }) - }); - }); - }, - - disable: function() { - DEBUG && debug("KillSwitch: disable"); - - cpmm.addMessageListener(kDisableKillSwitchOK, this); - cpmm.addMessageListener(kDisableKillSwitchKO, this); - return this.createPromise((aResolve, aReject) => { - cpmm.sendAsyncMessage(kDisableKillSwitch, { - requestID: this.getPromiseResolverId({ - resolve: aResolve, - reject: aReject - }) - }); - }); - }, - - receiveMessage: function(message) { - DEBUG && debug("Received: " + message.name); - - cpmm.removeMessageListener(kEnableKillSwitchOK, this); - cpmm.removeMessageListener(kEnableKillSwitchKO, this); - cpmm.removeMessageListener(kDisableKillSwitchOK, this); - cpmm.removeMessageListener(kDisableKillSwitchKO, this); - - let req = this.takePromiseResolver(message.data.requestID); - - switch (message.name) { - case kEnableKillSwitchKO: - case kDisableKillSwitchKO: - req.reject(false); - break; - - case kEnableKillSwitchOK: - case kDisableKillSwitchOK: - req.resolve(true); - break; - - default: - DEBUG && debug("Unrecognized message: " + message.name); - break; - } - }, - - classID : Components.ID(KILLSWITCH_CID), - contractID : KILLSWITCH_CONTRACTID, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIKillSwitch, - Ci.nsIDOMGlobalPropertyInitializer, - Ci.nsIObserver, - Ci.nsIMessageListener, - Ci.nsISupportsWeakReference]), -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([KillSwitch]); diff --git a/b2g/components/KillSwitchMain.jsm b/b2g/components/KillSwitchMain.jsm deleted file mode 100644 index f9da97d60b27..000000000000 --- a/b2g/components/KillSwitchMain.jsm +++ /dev/null @@ -1,506 +0,0 @@ -/* 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"; - -this.EXPORTED_SYMBOLS = [ "KillSwitchMain" ]; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/AppConstants.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "settings", - "@mozilla.org/settingsService;1", - "nsISettingsService"); - -XPCOMUtils.defineLazyServiceGetter(this, "ppmm", - "@mozilla.org/parentprocessmessagemanager;1", - "nsIMessageBroadcaster"); - -XPCOMUtils.defineLazyGetter(this, "permMgr", function() { - return Cc["@mozilla.org/permissionmanager;1"] - .getService(Ci.nsIPermissionManager); -}); - -if (AppConstants.platform === "gonk") { - XPCOMUtils.defineLazyGetter(this, "libcutils", function () { - Cu.import("resource://gre/modules/systemlibs.js"); - return libcutils; - }); -} else { - this.libcutils = null; -} - -const DEBUG = false; - -const kEnableKillSwitch = "KillSwitch:Enable"; -const kEnableKillSwitchOK = "KillSwitch:Enable:OK"; -const kEnableKillSwitchKO = "KillSwitch:Enable:KO"; - -const kDisableKillSwitch = "KillSwitch:Disable"; -const kDisableKillSwitchOK = "KillSwitch:Disable:OK"; -const kDisableKillSwitchKO = "KillSwitch:Disable:KO"; - -const kMessages = [kEnableKillSwitch, kDisableKillSwitch]; - -const kXpcomShutdownObserverTopic = "xpcom-shutdown"; - -const kProperty = "persist.moz.killswitch"; - -const kUserValues = - OS.Path.join(OS.Constants.Path.profileDir, "killswitch.json"); - -var inParent = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime) - .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; - -function debug(aStr) { - dump("--*-- KillSwitchMain: " + aStr + "\n"); -} - -this.KillSwitchMain = { - _ksState: null, - _libcutils: null, - - _enabledValues: { - // List of settings to set to a specific value - settings: { - "debugger.remote-mode": "disabled", - "developer.menu.enabled": false, - "devtools.unrestricted": false, - "lockscreen.enabled": true, - "lockscreen.locked": true, - "lockscreen.lock-immediately": true, - "tethering.usb.enabled": false, - "tethering.wifi.enabled": false, - "ums.enabled": false - }, - - // List of preferences to set to a specific value - prefs: { - "b2g.killswitch.test": true - }, - - // List of Android properties to set to a specific value - properties: { - "persist.sys.usb.config": "none" // will change sys.usb.config and sys.usb.state - }, - - // List of Android services to control - services: { - "adbd": "stop" - } - }, - - init: function() { - DEBUG && debug("init"); - if (libcutils) { - this._libcutils = libcutils; - } - - kMessages.forEach(m => { - ppmm.addMessageListener(m, this); - }); - - Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false); - - this.readStateProperty(); - }, - - uninit: function() { - kMessages.forEach(m => { - ppmm.removeMessageListener(m, this); - }); - - Services.obs.removeObserver(this, kXpcomShutdownObserverTopic); - }, - - checkLibcUtils: function() { - DEBUG && debug("checkLibcUtils"); - if (!this._libcutils) { - debug("No proper libcutils binding, aborting."); - throw Cr.NS_ERROR_NO_INTERFACE; - } - - return true; - }, - - readStateProperty: function() { - DEBUG && debug("readStateProperty"); - try { - this.checkLibcUtils(); - } catch (ex) { - return; - } - - this._ksState = - this._libcutils.property_get(kProperty, "false") === "true"; - }, - - writeStateProperty: function() { - DEBUG && debug("writeStateProperty"); - try { - this.checkLibcUtils(); - } catch (ex) { - return; - } - - this._libcutils.property_set(kProperty, this._ksState.toString()); - }, - - getPref(name, value) { - let rv = undefined; - - try { - switch (typeof value) { - case "boolean": - rv = Services.prefs.getBoolPref(name, value); - break; - - case "number": - rv = Services.prefs.getIntPref(name, value); - break; - - case "string": - rv = Services.prefs.getCharPref(name, value); - break; - - default: - debug("Unexpected pref type " + value); - break; - } - } catch (ex) { - } - - return rv; - }, - - setPref(name, value) { - switch (typeof value) { - case "boolean": - Services.prefs.setBoolPref(name, value); - break; - - case "number": - Services.prefs.setIntPref(name, value); - break; - - case "string": - Services.prefs.setCharPref(name, value); - break; - - default: - debug("Unexpected pref type " + value); - break; - } - }, - - doEnable: function() { - return new Promise((resolve, reject) => { - // Make sure that the API cannot do a new |enable()| call once the - // feature has been enabled, otherwise we will overwrite the user values. - if (this._ksState) { - reject(true); - return; - } - - this.saveUserValues().then(() => { - DEBUG && debug("Toggling settings: " + - JSON.stringify(this._enabledValues.settings)); - - let lock = settings.createLock(); - for (let key of Object.keys(this._enabledValues.settings)) { - lock.set(key, this._enabledValues.settings[key], this); - } - - DEBUG && debug("Toggling prefs: " + - JSON.stringify(this._enabledValues.prefs)); - - for (let key of Object.keys(this._enabledValues.prefs)) { - this.setPref(key, this._enabledValues.prefs[key]); - } - - DEBUG && debug("Toggling properties: " + - JSON.stringify(this._enabledValues.properties)); - - for (let key of Object.keys(this._enabledValues.properties)) { - this._libcutils.property_set(key, this._enabledValues.properties[key]); - } - - DEBUG && debug("Toggling services: " + - JSON.stringify(this._enabledValues.services)); - - for (let key of Object.keys(this._enabledValues.services)) { - let value = this._enabledValues.services[key]; - if (value !== "start" && value !== "stop") { - debug("Unexpected service " + key + " value:" + value); - } - - this._libcutils.property_set("ctl." + value, key); - } - - this._ksState = true; - this.writeStateProperty(); - - resolve(true); - }).catch(err => { - DEBUG && debug("doEnable: " + err); - - reject(false); - }); - }); - }, - - saveUserValues: function() { - return new Promise((resolve, reject) => { - try { - this.checkLibcUtils(); - } catch (ex) { - reject("nolibcutils"); - } - - let _userValues = { - settings: { }, - prefs: { }, - properties: { } - }; - - // Those will be sync calls - for (let key of Object.keys(this._enabledValues.prefs)) { - _userValues.prefs[key] = - this.getPref(key, this._enabledValues.prefs[key]); - } - - for (let key of Object.keys(this._enabledValues.properties)) { - _userValues.properties[key] = this._libcutils.property_get(key); - } - - let self = this; - let getCallback = { - handleAbort: function(m) { - DEBUG && debug("getCallback: handleAbort: m=" + m); - reject(m); - }, - - handleError: function(m) { - DEBUG && debug("getCallback: handleError: m=" + m); - reject(m); - }, - - handle: function(n, v) { - DEBUG && debug("getCallback: handle: n=" + n + " ; v=" + v); - - if (self._pendingSettingsGet) { - // We have received a settings callback value for saving user data - let pending = self._pendingSettingsGet.indexOf(n); - if (pending !== -1) { - _userValues.settings[n] = v; - self._pendingSettingsGet.splice(pending, 1); - } - - if (self._pendingSettingsGet.length === 0) { - delete self._pendingSettingsGet; - let payload = JSON.stringify(_userValues); - DEBUG && debug("Dumping to " + kUserValues + ": " + payload); - OS.File.writeAtomic(kUserValues, payload).then( - function writeOk() { - resolve(true); - }, - function writeNok(err) { - reject("write error"); - } - ); - } - } - } - }; - - // For settings we have to wait all the callbacks to come back before - // we can resolve or reject - this._pendingSettingsGet = []; - let lock = settings.createLock(); - for (let key of Object.keys(this._enabledValues.settings)) { - this._pendingSettingsGet.push(key); - lock.get(key, getCallback); - } - }); - }, - - doDisable: function() { - return new Promise((resolve, reject) => { - this.restoreUserValues().then(() => { - this._ksState = false; - this.writeStateProperty(); - - resolve(true); - }).catch(err => { - DEBUG && debug("doDisable: " + err); - - reject(false); - }); - }); - }, - - restoreUserValues: function() { - return new Promise((resolve, reject) => { - try { - this.checkLibcUtils(); - } catch (ex) { - reject("nolibcutils"); - } - - OS.File.read(kUserValues, { encoding: "utf-8" }).then(content => { - let values = JSON.parse(content); - - for (let key of Object.keys(values.prefs)) { - this.setPref(key, values.prefs[key]); - } - - for (let key of Object.keys(values.properties)) { - this._libcutils.property_set(key, values.properties[key]); - } - - let self = this; - let saveCallback = { - handleAbort: function(m) { - DEBUG && debug("saveCallback: handleAbort: m=" + m); - reject(m); - }, - - handleError: function(m) { - DEBUG && debug("saveCallback: handleError: m=" + m); - reject(m); - }, - - handle: function(n, v) { - DEBUG && debug("saveCallback: handle: n=" + n + " ; v=" + v); - - if (self._pendingSettingsSet) { - // We have received a settings callback value for setting user data - let pending = self._pendingSettingsSet.indexOf(n); - if (pending !== -1) { - self._pendingSettingsSet.splice(pending, 1); - } - - if (self._pendingSettingsSet.length === 0) { - delete self._pendingSettingsSet; - DEBUG && debug("Restored from " + kUserValues + ": " + JSON.stringify(values)); - resolve(values); - } - } - } - }; - - // For settings we have to wait all the callbacks to come back before - // we can resolve or reject - this._pendingSettingsSet = []; - let lock = settings.createLock(); - for (let key of Object.keys(values.settings)) { - this._pendingSettingsSet.push(key); - lock.set(key, values.settings[key], saveCallback); - } - }).catch(err => { - reject(err); - }); - }); - }, - - // Settings Callbacks - handle: function(aName, aValue) { - DEBUG && debug("handle: aName=" + aName + " ; aValue=" + aValue); - // We don't have to do anything for now. - }, - - handleAbort: function(aMessage) { - debug("handleAbort: " + JSON.stringify(aMessage)); - throw Cr.NS_ERROR_ABORT; - }, - - handleError: function(aMessage) { - debug("handleError: " + JSON.stringify(aMessage)); - throw Cr.NS_ERROR_FAILURE; - }, - - // addObserver - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case kXpcomShutdownObserverTopic: - this.uninit(); - break; - - default: - DEBUG && debug("Wrong observer topic: " + aTopic); - break; - } - }, - - // addMessageListener - receiveMessage: function(aMessage) { - let hasPermission = aMessage.target.assertPermission("killswitch"); - DEBUG && debug("hasPermission: " + hasPermission); - - if (!hasPermission) { - debug("Message " + aMessage.name + " from a process with no killswitch perm."); - aMessage.target.killChild(); - throw Cr.NS_ERROR_NOT_AVAILABLE; - return; - } - - function returnMessage(name, data) { - if (aMessage.target) { - data.requestID = aMessage.data.requestID; - try { - aMessage.target.sendAsyncMessage(name, data); - } catch (e) { - if (DEBUG) debug("Return message failed, " + name + ": " + e); - } - } - } - - switch (aMessage.name) { - case kEnableKillSwitch: - this.doEnable().then( - () => { - returnMessage(kEnableKillSwitchOK, {}); - }, - err => { - debug("doEnable failed: " + err); - returnMessage(kEnableKillSwitchKO, {}); - } - ); - break; - case kDisableKillSwitch: - this.doDisable().then( - () => { - returnMessage(kDisableKillSwitchOK, {}); - }, - err => { - debug("doDisable failed: " + err); - returnMessage(kDisableKillSwitchKO, {}); - } - ); - break; - - default: - debug("Unsupported message: " + aMessage.name); - aMessage.target && aMessage.target.killChild(); - throw Cr.NS_ERROR_ILLEGAL_VALUE; - return; - break; - } - } -}; - -// This code should ALWAYS be living only on the parent side. -if (!inParent) { - debug("KillSwitchMain should only be living on parent side."); - throw Cr.NS_ERROR_ABORT; -} else { - this.KillSwitchMain.init(); -} diff --git a/b2g/components/PersistentDataBlock.jsm b/b2g/components/PersistentDataBlock.jsm deleted file mode 100644 index a26efe56d82e..000000000000 --- a/b2g/components/PersistentDataBlock.jsm +++ /dev/null @@ -1,766 +0,0 @@ -/* 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/. */ - -/** - * The Persistent Partition has this layout: - * - * Bytes: 32 4 4 1 - * Fields: [[DIGEST][MAGIC][DATA_LENGTH][ DATA ][OEM_UNLOCK_ENABLED]] - * - */ - -"use strict"; - -const DEBUG = false; - -this.EXPORTED_SYMBOLS = [ "PersistentDataBlock" ]; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; -// This is a marker that will be written after digest in the partition. -const PARTITION_MAGIC = 0x19901873; -// This is the limit in Android because of issues with Binder if blocks are > 100k -// We dont really have this issues because we don't use Binder, but let's stick -// to Android implementation. -const MAX_DATA_BLOCK_SIZE = 1024 * 100; -const DIGEST_SIZE_BYTES = 32; -const HEADER_SIZE_BYTES = 8; -const PARTITION_MAGIC_SIZE_BYTES = 4; -const DATA_SIZE_BYTES = 4; -const OEM_UNLOCK_ENABLED_BYTES = 1; -// The position of the Digest -const DIGEST_OFFSET = 0; -const XPCOM_SHUTDOWN_OBSERVER_TOPIC = "xpcom-shutdown"; -// This property will have the path to the persistent partition -const PERSISTENT_DATA_BLOCK_PROPERTY = "ro.frp.pst"; -const OEM_UNLOCK_PROPERTY = "sys.oem_unlock_allowed"; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm"); - -XPCOMUtils.defineLazyGetter(this, "libcutils", function () { - Cu.import("resource://gre/modules/systemlibs.js"); - return libcutils; -}); - -var inParent = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime) - .processType === Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; - -function log(str) { - dump("PersistentDataBlock.jsm: " + str + "\n"); -} - -function debug(str) { - DEBUG && log(str); -} - -function toHexString(data) { - function toHexChar(charCode) { - return ("0" + charCode.toString(16).slice(-2)); - } - let hexString = ""; - if (typeof data === "string") { - hexString = Array.from(data, (c, i) => toHexChar(data.charCodeAt(i))).join(""); - } else if (data instanceof Array) { - hexString = data.map(toHexChar).join(""); - } - return hexString; -} - -function arr2bstr(arr) { - let bstr = ""; - for (let i = 0; i < arr.length; i++) { - bstr += String.fromCharCode(arr[i]); - } - return bstr; -} - -this.PersistentDataBlock = { - - /** - * libc funcionality. Accessed via ctypes - */ - _libc: { - handler: null, - open: function() {}, - close: function() {}, - ioctl: function() {} - }, - - /** - * Component to access property_get/set functions - */ - _libcutils: null, - - /** - * The size of a device block. This is assigned by querying the kernel. - */ - _blockDeviceSize: -1, - - /** - * Data block file - */ - _dataBlockFile: "", - - /** - * Change the behavior of the class for some methods to testing mode. This will fake the return value of some - * methods realted to native operations with block devices. - */ - _testing: false, - - /* - * *** USE ONLY FOR TESTING *** - * This component will interface between Gecko and a special secure partition with no formatting, a raw partition. - * This interaction requires a specific partition layout structure which emulators don't have so far. So for - * our unit tests to pass, we need a way for some methods to behave differently. This method will change this - * behavior at runtime so some low-level platform-specific operations will be faked: - * - Getting the size of a partition: We can use any partition to get the size, is up to the test to choose - * which partition to use. But, in testing mode we use files instead of partitions, so we need to fake the - * return value of this method in this case. - * - Wipping a partition: This will fully remove the partition as well as it filesystem type, so we cannot - * test it on any existing emulator partition. Testing mode will skip this operation. - * - * @param enabled {Bool} Set testing mode. See _testing property. - */ - setTestingMode: function(enabled) { - this._testing = enabled || false; - }, - - /** - * Initialize the class. - * - */ - init: function(mode) { - debug("init()"); - - if (libcutils) { - this._libcutils = libcutils; - } - - if (!this.ctypes) { - Cu.import("resource://gre/modules/ctypes.jsm", this); - } - - if (this._libc.handler === null) { - if (AppConstants.platform != "gonk") { - log("This component requires Gonk!"); - throw Cr.NS_ERROR_ABORT; - } - - try { - this._libc.handler = this.ctypes.open(this.ctypes.libraryName("c")); - this._libc.close = this._libc.handler.declare("close", - this.ctypes.default_abi, - this.ctypes.int, - this.ctypes.int - ); - this._libc.open = this._libc.handler.declare("open", - this.ctypes.default_abi, - this.ctypes.int, - this.ctypes.char.ptr, - this.ctypes.int - ); - this._libc.ioctl = this._libc.handler.declare("ioctl", - this.ctypes.default_abi, - this.ctypes.int, - this.ctypes.int, - this.ctypes.unsigned_long, - this.ctypes.unsigned_long.ptr); - - } catch(ex) { - log("Unable to open libc.so: ex = " + ex); - throw Cr.NS_ERROR_FAILURE; - } - } - - this._dataBlockFile = this._libcutils.property_get(PERSISTENT_DATA_BLOCK_PROPERTY); - if (this._dataBlockFile === null) { - log("init: ERROR: property " + PERSISTENT_DATA_BLOCK_PROPERTY + " doesn't exist!"); - throw Cr.NS_ERROR_FAILURE; - } - - Services.obs.addObserver(this, XPCOM_SHUTDOWN_OBSERVER_TOPIC, false); - }, - - uninit: function() { - debug("uninit()"); - this._libc.handler.close(); - Services.obs.removeObserver(this, XPCOM_SHUTDOWN_OBSERVER_TOPIC); - }, - - _checkLibcUtils: function() { - debug("_checkLibcUtils"); - if (!this._libcutils) { - log("No proper libcutils binding, aborting."); - throw Cr.NS_ERROR_NO_INTERFACE; - } - - return true; - }, - - /** - * Callback mehtod for addObserver - */ - observe: function(aSubject, aTopic, aData) { - debug("observe()"); - switch (aTopic) { - case XPCOM_SHUTDOWN_OBSERVER_TOPIC: - this.uninit(); - break; - - default: - log("Wrong observer topic: " + aTopic); - break; - } - }, - - /** - * This method will format the persistent partition if it detects manipulation (digest calculation will fail) - * or if the OEM Unlock Enabled byte is set to true. - * We need to call this method on every boot. - */ - start: function() { - debug("start()"); - return this._enforceChecksumValidity().then(() => { - return this._formatIfOemUnlockEnabled().then(() => { - return Promise.resolve(true); - }) - }).catch(ex => { - return Promise.reject(ex); - }); - }, - - /** - * Computes the digest of the entire data block. - * The digest is saved in the first 32 bytes of the block. - * - * @param isStoredDigestReturned {Bool} Tells the function to return the stored digest as well as the calculated. - * True means to return stored digest and the calculated - * False means to return just the calculated one - * - * @return Promise {Object} The calculated digest into the "calculated" property, and the stored - * digest into the "stored" property. - */ - _computeDigest: function (isStoredDigestReturned) { - debug("_computeDigest()"); - let digest = {calculated: "", stored: ""}; - let partition; - debug("_computeDigest: _dataBlockFile = " + this._dataBlockFile); - return OS.File.open(this._dataBlockFile, {existing:true, append:false, read:true}).then(_partition => { - partition = _partition; - return partition.read(DIGEST_SIZE_BYTES); - }).then(digestDataRead => { - // If storedDigest is passed as a parameter, the caller will likely compare the - // one is already stored in the partition with the one we are going to compute later. - if (isStoredDigestReturned === true) { - debug("_computeDigest: get stored digest from the partition"); - digest.stored = arr2bstr(digestDataRead); - } - return partition.read(); - }).then(data => { - // Calculate Digest with the data retrieved after the digest - let hasher = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash); - hasher.init(hasher.SHA256); - hasher.update(data, data.byteLength); - digest.calculated = hasher.finish(false); - debug("_computeDigest(): Digest = " + toHexString(digest.calculated) + - "(" + digest.calculated.length + ")"); - return partition.close(); - }).then(() => { - return Promise.resolve(digest); - }).catch(ex => { - log("_computeDigest(): Failed to read partition: ex = " + ex); - return Promise.reject(ex); - }); - }, - - /** - * Returns the size of a block from the undelaying filesystem - * - * @return {Number} The size of the block - */ - _getBlockDeviceSize: function() { - debug("_getBlockDeviceSize()"); - - // See _testing property - if (this._testing === true) { - debug("_getBlockDeviceSize: No real block device size in testing mode!. Returning 1024."); - return 1024; - } - - if (AppConstants.platform != "gonk") { - log("_getBlockDeviceSize: ERROR: This feature is only supported in Gonk!"); - return -1; - } - - const O_READONLY = 0; - const O_NONBLOCK = 1 << 11; - /* Getting the correct values for ioctl() operations by reading the headers is not a trivial task, so - * the better way to get the values below is by writting a simple test aplication in C that will - * print the values to the output. - * 32bits and 64bits value for ioctl() BLKGETSIZE64 operation is different. So we will fallback in - * case ioctl() returns ENOTTY (22). */ - const BLKGETSIZE64_32_BITS = 0x80041272; - const BLKGETSIZE64_64_BITS = 0x80081272; - const ENOTTY = 25; - - debug("_getBlockDeviceSize: _dataBlockFile = " + this._dataBlockFile); - let fd = this._libc.open(this._dataBlockFile, O_READONLY | O_NONBLOCK); - if (fd < 0) { - log("_getBlockDeviceSize: couldn't open partition!: errno = " + this.ctypes.errno); - throw Cr.NS_ERROR_FAILURE; - } - - let size = new this.ctypes.unsigned_long(); - let sizeAddress = size.address(); - let ret = this._libc.ioctl(fd, BLKGETSIZE64_32_BITS, sizeAddress); - if (ret < 0) { - if (this.ctypes.errno === ENOTTY) { - log("_getBlockDeviceSize: errno is ENOTTY, falling back to 64 bit version of BLKGETSIZE64..."); - ret = this._libc.ioctl(fd, BLKGETSIZE64_64_BITS, sizeAddress); - if (ret < 0) { - this._libc.close(fd); - log("_getBlockDeviceSize: BLKGETSIZE64 failed again!. errno = " + this.ctypes.errno); - throw Cr.NS_ERROR_FAILURE; - } - } else { - this._libc.close(fd); - log("_getBlockDeviceSize: couldn't get block device size!: errno = " + this.ctypes.errno); - throw Cr.NS_ERROR_FAILURE; - } - } - this._libc.close(fd); - debug("_getBlockDeviceSize: size =" + size.value); - return size.value; - }, - - /** - * Sets the byte into the partition which represents the OEM Unlock Enabled feature. - * A value of "1" means that the user doesn't want to enable KillSwitch. - * The byte is the last one byte into the device block. - * - * @param isSetOemUnlockEnabled {bool} If true, sets the OEM Unlock Enabled byte to 1. - * Otherwise, sets it to 0. - */ - _doSetOemUnlockEnabled: function(isSetOemUnlockEnabled) { - debug("_doSetOemUnlockEnabled()"); - let partition; - return OS.File.open(this._dataBlockFile, {existing:true, append:false, write:true}).then(_partition => { - partition = _partition; - return partition.setPosition(this._getBlockDeviceSize() - OEM_UNLOCK_ENABLED_BYTES, OS.File.POS_START); - }).then(() => { - return partition.write(new Uint8Array([ isSetOemUnlockEnabled === true ? 1 : 0 ])); - }).then(bytesWrittenLength => { - if (bytesWrittenLength != 1) { - log("_doSetOemUnlockEnabled: Error writting OEM Unlock Enabled byte!"); - return Promise.reject(); - } - return partition.close(); - }).then(() => { - let oemUnlockByte = (isSetOemUnlockEnabled === true ? "1" : "0"); - debug("_doSetOemUnlockEnabled: OEM unlock enabled written to " + oemUnlockByte); - this._libcutils.property_set(OEM_UNLOCK_PROPERTY, oemUnlockByte); - return Promise.resolve(); - }).catch(ex => { - return Promise.reject(ex); - }); - }, - - /** - * Computes the digest by reading the entire block of data and write it to the digest field - * - * @return true Promise Operation succeed - * @return false Promise Operation failed - */ - _computeAndWriteDigest: function() { - debug("_computeAndWriteDigest()"); - let digest; - let partition; - return this._computeDigest().then(_digest => { - digest = _digest; - return OS.File.open(this._dataBlockFile, {write:true, existing:true, append:false}); - }).then(_partition => { - partition = _partition; - return partition.setPosition(DIGEST_OFFSET, OS.File.POS_START); - }).then(() => { - return partition.write(new Uint8Array(Array.from(digest.calculated, (c, i) => digest.calculated.charCodeAt(i)))); - }).then(bytesWrittenLength => { - if (bytesWrittenLength != DIGEST_SIZE_BYTES) { - log("_computeAndWriteDigest: Error writting digest to partition!. Expected: " + DIGEST_SIZE_BYTES + " Written: " + bytesWrittenLength); - return Promise.reject(); - } - return partition.close(); - }).then(() => { - debug("_computeAndWriteDigest: digest written to partition"); - return Promise.resolve(true); - }).catch(ex => { - log("_computeAndWriteDigest: Couldn't write digest in the persistent partion. ex = " + ex ); - return Promise.reject(ex); - }); - }, - - /** - * Formats the persistent partition if the OEM Unlock Enabled field is set to true, and - * write the Unlock Property accordingly. - * - * @return true Promise OEM Unlock was enabled, so the partition has been formated - * @return false Promise OEM Unlock was disabled, so the partition hasn't been formated - */ - _formatIfOemUnlockEnabled: function () { - debug("_formatIfOemUnlockEnabled()"); - return this.getOemUnlockEnabled().then(enabled => { - this._libcutils.property_set(OEM_UNLOCK_PROPERTY,(enabled === true ? "1" : "0")); - if (enabled === true) { - return this._formatPartition(true); - } - return Promise.resolve(false); - }).then(result => { - if (result === false) { - return Promise.resolve(false); - } else { - return Promise.resolve(true); - } - }).catch(ex => { - log("_formatIfOemUnlockEnabled: An error ocurred!. ex = " + ex); - return Promise.reject(ex); - }); - }, - - /** - * Formats the persistent data partition with the proper structure. - * - * @param isSetOemUnlockEnabled {bool} If true, writes a "1" in the OEM Unlock Enabled field (last - * byte of the block). If false, writes a "0". - * - * @return Promise - */ - _formatPartition: function(isSetOemUnlockEnabled) { - debug("_formatPartition()"); - let partition; - return OS.File.open(this._dataBlockFile, {write:true, existing:true, append:false}).then(_partition => { - partition = _partition; - return partition.write(new Uint8Array(DIGEST_SIZE_BYTES)); - }).then(bytesWrittenLength => { - if (bytesWrittenLength != DIGEST_SIZE_BYTES) { - log("_formatPartition Error writting zero-digest!. Expected: " + DIGEST_SIZE_BYTES + " Written: " + bytesWrittenLength); - return Promise.reject(); - } - return partition.write(new Uint32Array([PARTITION_MAGIC])); - }).then(bytesWrittenLength => { - if (bytesWrittenLength != PARTITION_MAGIC_SIZE_BYTES) { - log("_formatPartition Error writting magic number!. Expected: " + PARTITION_MAGIC_SIZE_BYTES + " Written: " + bytesWrittenLength); - return Promise.reject(); - } - return partition.write(new Uint8Array(DATA_SIZE_BYTES)); - }).then(bytesWrittenLength => { - if (bytesWrittenLength != DATA_SIZE_BYTES) { - log("_formatPartition Error writting data size!. Expected: " + DATA_SIZE_BYTES + " Written: " + bytesWrittenLength); - return Promise.reject(); - } - return partition.close(); - }).then(() => { - return this._doSetOemUnlockEnabled(isSetOemUnlockEnabled); - }).then(() => { - return this._computeAndWriteDigest(); - }).then(() => { - return Promise.resolve(); - }).catch(ex => { - log("_formatPartition: Failed to format block device!: ex = " + ex); - return Promise.reject(ex); - }); - }, - - /** - * Check digest validity. If it's not valid, formats the persistent partition - * - * @return true Promise The checksum is valid so the promise is resolved to true - * @return false Promise The checksum is not valid, so the partition is going to be - * formatted and the OEM Unlock Enabled field written to 0 (false). - */ - _enforceChecksumValidity: function() { - debug("_enforceChecksumValidity"); - return this._computeDigest(true).then(digest => { - if (digest.stored != digest.calculated) { - log("_enforceChecksumValidity: Validation failed! Stored digest: " + toHexString(digest.stored) + - " is not the same as the calculated one: " + toHexString(digest.calculated)); - return Promise.reject(); - } - debug("_enforceChecksumValidity: Digest computation succeed."); - return Promise.resolve(true); - }).catch(ex => { - log("_enforceChecksumValidity: Digest computation failed: ex = " + ex); - log("_enforceChecksumValidity: Formatting FRP partition..."); - return this._formatPartition(false).then(() => { - return Promise.resolve(false); - }).catch(ex => { - log("_enforceChecksumValidity: Error ocurred while formating the partition!: ex = " + ex); - return Promise.reject(ex); - }); - }); - }, - - /** - * Reads the entire data field - * - * @return bytes Promise A promise resolved with the bytes read - */ - read: function() { - debug("read()"); - let partition; - let bytes; - let dataSize; - return this.getDataFieldSize().then(_dataSize => { - dataSize = _dataSize; - return OS.File.open(this._dataBlockFile, {read:true, existing:true, append:false}); - }).then(_partition => { - partition = _partition; - return partition.setPosition(DIGEST_SIZE_BYTES + HEADER_SIZE_BYTES, OS.File.POS_START); - }).then(() => { - return partition.read(dataSize); - }).then(_bytes => { - bytes = _bytes; - if (bytes.byteLength < dataSize) { - log("read: Failed to read entire data block. Bytes read: " + bytes.byteLength + "/" + dataSize); - return Promise.reject(); - } - return partition.close(); - }).then(() => { - return Promise.resolve(bytes); - }).catch(ex => { - log("read: Failed to read entire data block. Exception: " + ex); - return Promise.reject(ex); - }); - }, - - /** - * Writes an entire block to the persistent partition - * - * @param data {Uint8Array} - * - * @return Promise Promise resolved to the number of bytes written. - */ - write: function(data) { - debug("write()"); - // Ensure that we don't overwrite digest/magic/data-length and the last byte - let maxBlockSize = this._getBlockDeviceSize() - (DIGEST_SIZE_BYTES + HEADER_SIZE_BYTES + 1); - if (data.byteLength > maxBlockSize) { - log("write: Couldn't write more than " + maxBlockSize + " bytes to the partition. " + - maxBlockSize + " bytes given."); - return Promise.reject(); - } - - let partition; - return OS.File.open(this._dataBlockFile, {write:true, existing:true, append:false}).then(_partition => { - let digest = new Uint8Array(DIGEST_SIZE_BYTES); - let magic = new Uint8Array((new Uint32Array([PARTITION_MAGIC])).buffer); - let dataLength = new Uint8Array((new Uint32Array([data.byteLength])).buffer); - let bufferToWrite = new Uint8Array(digest.byteLength + magic.byteLength + dataLength.byteLength + data.byteLength ); - let offset = 0; - bufferToWrite.set(digest, offset); - offset += digest.byteLength; - bufferToWrite.set(magic, offset); - offset += magic.byteLength; - bufferToWrite.set(dataLength, offset); - offset += dataLength.byteLength; - bufferToWrite.set(data, offset); - partition = _partition; - return partition.write(bufferToWrite); - }).then(bytesWrittenLength => { - let expectedWrittenLength = DIGEST_SIZE_BYTES + HEADER_SIZE_BYTES + data.byteLength; - if (bytesWrittenLength != expectedWrittenLength) { - log("write: Error writting data to partition!: Expected: " + expectedWrittenLength + " Written: " + bytesWrittenLength); - return Promise.reject(); - } - return partition.close(); - }).then(() => { - return this._computeAndWriteDigest(); - }).then(couldComputeAndWriteDigest => { - if (couldComputeAndWriteDigest === true) { - return Promise.resolve(data.byteLength); - } else { - log("write: Failed to compute and write the digest"); - return Promise.reject(); - } - }).catch(ex => { - log("write: Failed to write to the persistent partition: ex = " + ex); - return Promise.reject(ex); - }); - }, - - /** - * Wipes the persistent partition. - * - * @return Promise If no errors, the promise is resolved - */ - wipe: function() { - debug("wipe()"); - - if (this._testing === true) { - log("wipe: No wipe() funcionality in testing mode"); - return Promise.resolve(); - } - - if (AppConstants.platform != "gonk") { - log("wipe: ERROR: This feature is only supported in Gonk!"); - return Promise.reject(); - } - - const O_READONLY = 0; - const O_RDWR = 2; - const O_NONBLOCK = 1 << 11; - // This constant value is the same under 32 and 64 bits arch. - const BLKSECDISCARD = 0x127D; - // This constant value is the same under 32 and 64 bits arch. - const BLKDISCARD = 0x1277; - - return new Promise((resolve, reject) => { - let range = new this.ctypes.unsigned_long(); - let rangeAddress = range.address(); - let blockDeviceLength = this._getBlockDeviceSize(); - range[0] = 0; - range[1] = blockDeviceLength; - if (range[1] === 0) { - log("wipe: Block device size is 0!"); - return reject(); - } - let fd = this._libc.open(this._dataBlockFile, O_RDWR); - if (fd < 0) { - log("wipe: ERROR couldn't open partition!: error = " + this.ctypes.errno); - return reject(); - } - let ret = this._libc.ioctl(fd, BLKSECDISCARD, rangeAddress); - if (ret < 0) { - log("wipe: Something went wrong secure discarding block: errno: " + this.ctypes.errno + ": Falling back to non-secure discarding..."); - ret = this._libc.ioctl(fd, BLKDISCARD, rangeAddress); - if (ret < 0) { - this._libc.close(fd); - log("wipe: CRITICAL: non-secure discarding failed too!!: errno: " + this.ctypes.errno); - return reject(); - } else { - this._libc.close(fd); - log("wipe: non-secure discard used and succeed"); - return resolve(); - } - } - this._libc.close(fd); - log("wipe: secure discard succeed"); - return resolve(); - }); - }, - - /** - * Set the OEM Unlock Enabled field (one byte at the end of the partition), to 1 or 0 depending on - * the input parameter. - * - * @param enabled {bool} If enabled, we write a 1 in the last byte of the partition. - * - * @return Promise - * - */ - setOemUnlockEnabled: function(enabled) { - debug("setOemUnlockEnabled()"); - return this._doSetOemUnlockEnabled(enabled).then(() => { - return this._computeAndWriteDigest(); - }).then(() => { - return Promise.resolve(); - }).catch(ex => { - return Promise.reject(ex); - }); - }, - - /** - * Gets the byte from the partition which represents the OEM Unlock Enabled state. - * - * @return true Promise The user didn't activate KillSwitch. - * @return false Promise The user did activate KillSwitch. - */ - getOemUnlockEnabled: function() { - log("getOemUnlockEnabled()"); - let ret = false; - let partition; - return OS.File.open(this._dataBlockFile, {existing:true, append:false, read:true}).then(_partition => { - partition = _partition; - return partition.setPosition(this._getBlockDeviceSize() - OEM_UNLOCK_ENABLED_BYTES, OS.File.POS_START); - }).then(() => { - return partition.read(OEM_UNLOCK_ENABLED_BYTES); - }).then(data => { - debug("getOemUnlockEnabled: OEM unlock enabled byte = '" + data[0] + "'"); - ret = (data[0] === 1 ? true : false); - return partition.close(); - }).then(() => { - return Promise.resolve(ret); - }).catch(ex => { - log("getOemUnlockEnabled: Error reading OEM unlock enabled byte from partition: ex = " + ex); - return Promise.reject(ex); - }); - }, - - /** - * Gets the size of the data block by reading the data-length field - * - * @return Promise A promise resolved to the number of bytes os the data field. - */ - getDataFieldSize: function() { - debug("getDataFieldSize()"); - let partition - let dataLength = 0; - return OS.File.open(this._dataBlockFile, {read:true, existing:true, append:false}).then(_partition => { - partition = _partition; - // Skip the digest field - return partition.setPosition(DIGEST_SIZE_BYTES, OS.File.POS_START); - }).then(() => { - // Read the Magic field - return partition.read(PARTITION_MAGIC_SIZE_BYTES); - }).then(_magic => { - let magic = new Uint32Array(_magic.buffer)[0]; - if (magic === PARTITION_MAGIC) { - return partition.read(PARTITION_MAGIC_SIZE_BYTES); - } else { - log("getDataFieldSize: ERROR: Invalid Magic number!"); - return Promise.reject(); - } - }).then(_dataLength => { - if (_dataLength) { - dataLength = new Uint32Array(_dataLength.buffer)[0]; - } - return partition.close(); - }).then(() => { - if (dataLength && dataLength != 0) { - return Promise.resolve(dataLength); - } else { - return Promise.reject(); - } - }).catch(ex => { - log("getDataFieldSize: Couldn't get data field size: ex = " + ex); - return Promise.reject(ex); - }); - }, - - /** - * Gets the maximum possible size of a data field - * - * @return Promise A Promise resolved to the maximum number of bytes allowed for the data field - * - */ - getMaximumDataBlockSize: function() { - debug("getMaximumDataBlockSize()"); - return new Promise((resolve, reject) => { - let actualSize = this._getBlockDeviceSize() - HEADER_SIZE_BYTES - OEM_UNLOCK_ENABLED_BYTES; - resolve(actualSize <= MAX_DATA_BLOCK_SIZE ? actualSize : MAX_DATA_BLOCK_SIZE); - }); - } - -}; - -// This code should ALWAYS be living only on the parent side. -if (!inParent) { - log("PersistentDataBlock should only be living on parent side."); - throw Cr.NS_ERROR_ABORT; -} else { - this.PersistentDataBlock.init(); -} diff --git a/b2g/components/moz.build b/b2g/components/moz.build index 16175d752218..71e99513d31b 100644 --- a/b2g/components/moz.build +++ b/b2g/components/moz.build @@ -16,7 +16,6 @@ EXTRA_COMPONENTS += [ 'FilePicker.js', 'FxAccountsUIGlue.js', 'HelperAppDialog.js', - 'KillSwitch.js', 'MailtoProtocolHandler.js', 'MobileIdentityUIGlue.js', 'OMAContentHandler.js', @@ -62,12 +61,10 @@ EXTRA_JS_MODULES += [ 'ErrorPage.jsm', 'Frames.jsm', 'FxAccountsMgmtService.jsm', - 'KillSwitchMain.jsm', 'LogCapture.jsm', 'LogParser.jsm', 'LogShake.jsm', 'OrientationChangeHandler.jsm', - 'PersistentDataBlock.jsm', 'SafeMode.jsm', 'Screenshot.jsm', 'SignInToWebsite.jsm', diff --git a/b2g/components/test/mochitest/file_loadserver.js b/b2g/components/test/mochitest/file_loadserver.js deleted file mode 100644 index 2e111272b43b..000000000000 --- a/b2g/components/test/mochitest/file_loadserver.js +++ /dev/null @@ -1,67 +0,0 @@ -var Ci = Components.interfaces; -var Cc = Components.classes; -var Cu = Components.utils; - -// Stolen from SpecialPowers, since at this point we don't know we're in a test. -var isMainProcess = function() { - try { - return Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime) - .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; - } catch (e) { } - return true; -}; - -var fakeLibcUtils = { - _props_: {}, - property_set: function(name, value) { - dump("property_set('" + name + "', '" + value+ "' [" + (typeof value) + "]);\n"); - this._props_[name] = value; - }, - property_get: function(name, defaultValue) { - dump("property_get('" + name + "', '" + defaultValue+ "');\n"); - if (Object.keys(this._props_).indexOf(name) !== -1) { - return this._props_[name]; - } else { - return defaultValue; - } - } -}; - -var kUserValues; - -function installUserValues(next) { - var fakeValues = { - settings: { - "lockscreen.locked": false, - "lockscreen.lock-immediately": false - }, - prefs: { - "b2g.killswitch.test": false - }, - properties: { - "dalvik.vm.heapmaxfree": "32m", - "dalvik.vm.isa.arm.features": "fdiv", - "dalvik.vm.lockprof.threshold": "5000", - "net.bt.name": "BTAndroid", - "dalvik.vm.stack-trace-file": "/data/anr/stack-traces.txt" - } - }; - - OS.File.writeAtomic(kUserValues, - JSON.stringify(fakeValues)).then(() => { - next(); - }); -} - -if (isMainProcess()) { - Cu.import("resource://gre/modules/SettingsRequestManager.jsm"); - Cu.import("resource://gre/modules/osfile.jsm"); - Cu.import("resource://gre/modules/KillSwitchMain.jsm"); - - kUserValues = OS.Path.join(OS.Constants.Path.profileDir, "killswitch.json"); - - installUserValues(() => { - KillSwitchMain._libcutils = fakeLibcUtils; - }); -} diff --git a/b2g/components/test/mochitest/killswitch.js b/b2g/components/test/mochitest/killswitch.js deleted file mode 100644 index 73c3fcc20dd2..000000000000 --- a/b2g/components/test/mochitest/killswitch.js +++ /dev/null @@ -1,149 +0,0 @@ -/* 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"; - -function setupSettings(target) { - ok((Object.keys(initialSettingsValues).length > 0), "Has at least one setting"); - - Object.keys(initialSettingsValues).forEach(k => { - ok(Object.keys(target).indexOf(k) !== -1, "Same settings set"); - }); - - var lock = navigator.mozSettings.createLock(); - lock.set(initialSettingsValues); -} - -function testSettingsInitial(next) { - var promises = []; - for (var setting in initialSettingsValues) { - promises.push(navigator.mozSettings.createLock().get(setting)); - } - - Promise.all(promises).then(values => { - values.forEach(set => { - var key = Object.keys(set)[0]; - var value = set[key]; - is(value, initialSettingsValues[key], "Value of " + key + " is initial one"); - }); - next(); - }); -} - -function testSettingsExpected(target, next) { - var promises = []; - for (var setting in initialSettingsValues) { - promises.push(navigator.mozSettings.createLock().get(setting)); - } - - Promise.all(promises).then(values => { - values.forEach(set => { - var key = Object.keys(set)[0]; - var value = set[key]; - is(value, target[key], "Value of " + key + " is expected one"); - }); - next(); - }); -} - -function testSetPrefValue(prefName, prefValue) { - switch (typeof prefValue) { - case "boolean": - SpecialPowers.setBoolPref(prefName, prefValue); - break; - - case "number": - SpecialPowers.setIntPref(prefName, prefValue); - break; - - case "string": - SpecialPowers.setCharPref(prefName, prefValue); - break; - - default: - is(false, "Unexpected pref type"); - break; - } -} - -function testGetPrefValue(prefName, prefValue) { - var rv = undefined; - - switch (typeof prefValue) { - case "boolean": - rv = SpecialPowers.getBoolPref(prefName); - break; - - case "number": - rv = SpecialPowers.getIntPref(prefName); - break; - - case "string": - rv = SpecialPowers.getCharPref(prefName); - break; - - default: - is(false, "Unexpected pref type"); - break; - } - - return rv; -} - -function setupPrefs(target) { - ok((Object.keys(initialPrefsValues).length > 0), "Has at least one pref"); - - Object.keys(initialPrefsValues).forEach(k => { - ok(Object.keys(target).indexOf(k) !== -1, "Same pref set"); - }); - - Object.keys(initialPrefsValues).forEach(key => { - testSetPrefValue(key, initialPrefsValues[key]); - }); -} - -function testPrefsInitial() { - Object.keys(initialPrefsValues).forEach(key => { - var value = testGetPrefValue(key, initialPrefsValues[key]); - is(value, initialPrefsValues[key], "Value of " + key + " is initial one"); - }); -} - -function testPrefsExpected(target) { - Object.keys(target).forEach(key => { - var value = testGetPrefValue(key, target[key]); - is(value, target[key], "Value of " + key + " is initial one"); - }); -} - -function finish() { - SpecialPowers.removePermission("killswitch", document); - SimpleTest.finish(); -} - -function addPermissions() { - if (SpecialPowers.hasPermission("killswitch", document)) { - startTests(); - } else { - var allow = SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION; - [ "killswitch", "settings-api-read", "settings-api-write", - "settings-read", "settings-write", "settings-clear" - ].forEach(perm => { - SpecialPowers.addPermission(perm, allow, document); - }); - window.location.reload(); - } -} - -function loadSettings() { - var url = SimpleTest.getTestFileURL("file_loadserver.js"); - var script = SpecialPowers.loadChromeScript(url); -} - -function addPrefs() { - SpecialPowers.pushPrefEnv({"set": [ - ["dom.ignore_webidl_scope_checks", true], - ["dom.mozKillSwitch.enabled", true], - ]}, addPermissions); -} diff --git a/b2g/components/test/mochitest/mochitest.ini b/b2g/components/test/mochitest/mochitest.ini index 80f64926b50e..97df32ea2bcf 100644 --- a/b2g/components/test/mochitest/mochitest.ini +++ b/b2g/components/test/mochitest/mochitest.ini @@ -7,8 +7,6 @@ support-files = systemapp_helper.js presentation_prompt_handler_chrome.js presentation_ui_glue_handler_chrome.js - file_loadserver.js - killswitch.js [test_filepicker_path.html] skip-if = toolkit != "gonk" @@ -28,6 +26,3 @@ skip-if = toolkit != "gonk" skip-if = toolkit != "gonk" [test_presentation_request_ui_glue.html] skip-if = toolkit != "gonk" -[test_killswitch_basics.html] -[test_killswitch_disable.html] -[test_killswitch_enable.html] diff --git a/b2g/components/test/mochitest/test_killswitch_basics.html b/b2g/components/test/mochitest/test_killswitch_basics.html deleted file mode 100644 index 76bb55db7cbc..000000000000 --- a/b2g/components/test/mochitest/test_killswitch_basics.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Enabling of killswitch feature - - - - -

- -
-  
-
- - diff --git a/b2g/components/test/mochitest/test_killswitch_disable.html b/b2g/components/test/mochitest/test_killswitch_disable.html deleted file mode 100644 index 44b29f391a67..000000000000 --- a/b2g/components/test/mochitest/test_killswitch_disable.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - Disabling of killswitch feature - - - - - -

- -
-  
-
- - diff --git a/b2g/components/test/mochitest/test_killswitch_enable.html b/b2g/components/test/mochitest/test_killswitch_enable.html deleted file mode 100644 index 2606f1be485d..000000000000 --- a/b2g/components/test/mochitest/test_killswitch_enable.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - Enabling of killswitch feature - - - - - -

- -
-  
-
- - diff --git a/b2g/components/test/unit/file_killswitch.js b/b2g/components/test/unit/file_killswitch.js deleted file mode 100644 index 0507e9ba7ae6..000000000000 --- a/b2g/components/test/unit/file_killswitch.js +++ /dev/null @@ -1,425 +0,0 @@ -/* 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"; - -var {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); - -var kUserValues; - -function run_test() { - do_get_profile(); - Cu.import("resource://gre/modules/KillSwitchMain.jsm"); - - check_enabledValues(); - run_next_test(); -} - -function check_enabledValues() { - let expected = { - settings: { - "debugger.remote-mode": "disabled", - "developer.menu.enabled": false, - "devtools.unrestricted": false, - "lockscreen.enabled": true, - "lockscreen.locked": true, - "lockscreen.lock-immediately": true, - "tethering.usb.enabled": false, - "tethering.wifi.enabled": false, - "ums.enabled": false - }, - prefs: { - "b2g.killswitch.test": true - }, - properties: { - "persist.sys.usb.config": "none" - }, - services: { - "adbd": "stop" - } - }; - - for (let key of Object.keys(KillSwitchMain._enabledValues.settings)) { - strictEqual(expected.settings[key], - KillSwitchMain._enabledValues.settings[key], - "setting " + key); - } - - for (let key of Object.keys(KillSwitchMain._enabledValues.prefs)) { - strictEqual(expected.prefs[key], - KillSwitchMain._enabledValues.prefs[key], - "pref " + key); - } - - for (let key of Object.keys(KillSwitchMain._enabledValues.properties)) { - strictEqual(expected.properties[key], - KillSwitchMain._enabledValues.properties[key], - "proprety " + key); - } - - for (let key of Object.keys(KillSwitchMain._enabledValues.services)) { - strictEqual(expected.services[key], - KillSwitchMain._enabledValues.services[key], - "service " + key); - } -} - -add_test(function test_prepareTestValues() { - if (("adbd" in KillSwitchMain._enabledValues.services)) { - strictEqual(KillSwitchMain._enabledValues.services["adbd"], "stop"); - - // We replace those for the test because on Gonk we will loose the control - KillSwitchMain._enabledValues.settings = { - "lockscreen.locked": true, - "lockscreen.lock-immediately": true - }; - KillSwitchMain._enabledValues.services = {}; - KillSwitchMain._enabledValues.properties = { - "dalvik.vm.heapmaxfree": "8m", - "dalvik.vm.isa.arm.features": "div", - "dalvik.vm.lockprof.threshold": "500", - "net.bt.name": "Android", - "dalvik.vm.stack-trace-file": "/data/anr/traces.txt" - } - } - - kUserValues = OS.Path.join(OS.Constants.Path.profileDir, "killswitch.json"); - run_next_test(); -}); - -function reset_status() { - KillSwitchMain._ksState = undefined; - KillSwitchMain._libcutils.property_set("persist.moz.killswitch", "undefined"); -} - -function install_common_tests() { - add_test(function test_readStateProperty() { - KillSwitchMain._libcutils.property_set("persist.moz.killswitch", "false"); - KillSwitchMain.readStateProperty(); - strictEqual(KillSwitchMain._ksState, false); - - KillSwitchMain._libcutils.property_set("persist.moz.killswitch", "true"); - KillSwitchMain.readStateProperty(); - strictEqual(KillSwitchMain._ksState, true); - - run_next_test(); - }); - - add_test(function test_writeStateProperty() { - KillSwitchMain._ksState = false; - KillSwitchMain.writeStateProperty(); - let state = KillSwitchMain._libcutils.property_get("persist.moz.killswitch"); - strictEqual(state, "false"); - - KillSwitchMain._ksState = true; - KillSwitchMain.writeStateProperty(); - state = KillSwitchMain._libcutils.property_get("persist.moz.killswitch"); - strictEqual(state, "true"); - - run_next_test(); - }); - - add_test(function test_doEnable() { - reset_status(); - - let enable = KillSwitchMain.doEnable(); - ok(enable, "should have a Promise"); - - enable.then(() => { - strictEqual(KillSwitchMain._ksState, true); - let state = KillSwitchMain._libcutils.property_get("persist.moz.killswitch"); - strictEqual(state, "true"); - - run_next_test(); - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - }); - - add_test(function test_enableMessage() { - reset_status(); - - let listener = { - assertPermission: function() { - return true; - }, - sendAsyncMessage: function(name, data) { - strictEqual(name, "KillSwitch:Enable:OK"); - strictEqual(data.requestID, 1); - - let state = KillSwitchMain._libcutils.property_get("persist.moz.killswitch"); - strictEqual(state, "true"); - - run_next_test(); - } - }; - - KillSwitchMain.receiveMessage({ - name: "KillSwitch:Enable", - target: listener, - data: { - requestID: 1 - } - }); - }); - - add_test(function test_saveUserValues_prepare() { - reset_status(); - - OS.File.exists(kUserValues).then(e => { - if (e) { - OS.File.remove(kUserValues).then(() => { - run_next_test(); - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - } else { - run_next_test(); - } - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - }); - - add_test(function test_saveUserValues() { - reset_status(); - - let expectedValues = Object.assign({}, KillSwitchMain._enabledValues); - - // Reset _enabledValues so we check properly that the dumped state - // is the current device state - KillSwitchMain._enabledValues = { - settings: { - "lockscreen.locked": false, - "lockscreen.lock-immediately": false - }, - prefs: { - "b2g.killswitch.test": false - }, - properties: { - "dalvik.vm.heapmaxfree": "32m", - "dalvik.vm.isa.arm.features": "fdiv", - "dalvik.vm.lockprof.threshold": "5000", - "net.bt.name": "BTAndroid", - "dalvik.vm.stack-trace-file": "/data/anr/stack-traces.txt" - }, - services: {} - }; - - KillSwitchMain.saveUserValues().then(e => { - ok(e, "should have succeeded"); - - OS.File.read(kUserValues, { encoding: "utf-8" }).then(content => { - let obj = JSON.parse(content); - - deepEqual(obj.settings, expectedValues.settings); - notDeepEqual(obj.settings, KillSwitchMain._enabledValues.settings); - - deepEqual(obj.prefs, expectedValues.prefs); - notDeepEqual(obj.prefs, KillSwitchMain._enabledValues.prefs); - - deepEqual(obj.properties, expectedValues.properties); - notDeepEqual(obj.properties, KillSwitchMain._enabledValues.properties); - - run_next_test(); - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - }); - - add_test(function test_saveUserValues_cleaup() { - reset_status(); - - OS.File.exists(kUserValues).then(e => { - if (e) { - OS.File.remove(kUserValues).then(() => { - ok(true, "should have had a file"); - run_next_test(); - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - } else { - ok(false, "should have had a file"); - run_next_test(); - } - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - }); - - add_test(function test_restoreUserValues_prepare() { - reset_status(); - - let fakeValues = { - settings: { - "lockscreen.locked": false, - "lockscreen.lock-immediately": false - }, - prefs: { - "b2g.killswitch.test": false - }, - properties: { - "dalvik.vm.heapmaxfree": "32m", - "dalvik.vm.isa.arm.features": "fdiv", - "dalvik.vm.lockprof.threshold": "5000", - "net.bt.name": "BTAndroid", - "dalvik.vm.stack-trace-file": "/data/anr/stack-traces.txt" - } - }; - - OS.File.exists(kUserValues).then(e => { - if (!e) { - OS.File.writeAtomic(kUserValues, - JSON.stringify(fakeValues)).then(() => { - ok(true, "success writing file"); - run_next_test(); - }, err => { - ok(false, "error writing file"); - run_next_test(); - }); - } else { - ok(false, "file should not have been there"); - run_next_test(); - } - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - }); - - add_test(function test_restoreUserValues() { - reset_status(); - - KillSwitchMain.restoreUserValues().then(e => { - ok(e, "should have succeeded"); - - strictEqual(e.settings["lockscreen.locked"], false); - strictEqual(e.settings["lockscreen.lock-immediately"], false); - - strictEqual(e.prefs["b2g.killswitch.test"], false); - - strictEqual( - e.properties["dalvik.vm.heapmaxfree"], - "32m"); - strictEqual( - e.properties["dalvik.vm.isa.arm.features"], - "fdiv"); - strictEqual( - e.properties["dalvik.vm.lockprof.threshold"], - "5000"); - strictEqual( - e.properties["net.bt.name"], - "BTAndroid"); - strictEqual( - e.properties["dalvik.vm.stack-trace-file"], - "/data/anr/stack-traces.txt"); - - strictEqual( - KillSwitchMain._libcutils.property_get("dalvik.vm.heapmaxfree"), - "32m"); - strictEqual( - KillSwitchMain._libcutils.property_get("dalvik.vm.isa.arm.features"), - "fdiv"); - strictEqual( - KillSwitchMain._libcutils.property_get("dalvik.vm.lockprof.threshold"), - "5000"); - strictEqual( - KillSwitchMain._libcutils.property_get("net.bt.name"), - "BTAndroid"); - strictEqual( - KillSwitchMain._libcutils.property_get("dalvik.vm.stack-trace-file"), - "/data/anr/stack-traces.txt"); - - run_next_test(); - }).catch(err => { - ok(false, "should not have had an error"); - run_next_test(); - }); - }); - - add_test(function test_doDisable() { - reset_status(); - - let disable = KillSwitchMain.doDisable() - ok(disable, "should have a Promise"); - - disable.then(() => { - strictEqual(KillSwitchMain._ksState, false); - let state = KillSwitchMain._libcutils.property_get("persist.moz.killswitch"); - strictEqual(state, "false"); - - run_next_test(); - }).catch(err => { - ok(false, "should have succeeded"); - run_next_test(); - }); - }); - - add_test(function test_disableMessage() { - reset_status(); - - let listener = { - assertPermission: function() { - return true; - }, - sendAsyncMessage: function(name, data) { - strictEqual(name, "KillSwitch:Disable:OK"); - strictEqual(data.requestID, 2); - - let state = KillSwitchMain._libcutils.property_get("persist.moz.killswitch"); - strictEqual(state, "false"); - - run_next_test(); - } - }; - - KillSwitchMain.receiveMessage({ - name: "KillSwitch:Disable", - target: listener, - data: { - requestID: 2 - } - }); - }); - - add_test(function test_doEnable_only_once() { - reset_status(); - - let firstEnable = KillSwitchMain.doEnable(); - ok(firstEnable, "should have a first Promise"); - - firstEnable.then(() => { - let secondEnable = KillSwitchMain.doEnable(); - ok(secondEnable, "should have a second Promise"); - - secondEnable.then(() => { - ok(false, "second enable should have not succeeded"); - run_next_test(); - }).catch(err => { - strictEqual(err, true, "second enable should reject(true);"); - run_next_test(); - }); - - }).catch(err => { - ok(false, "first enable should have succeeded"); - run_next_test(); - }); - }); -} diff --git a/b2g/components/test/unit/file_persistentdatablock.js b/b2g/components/test/unit/file_persistentdatablock.js deleted file mode 100644 index 6ce3072ac3a9..000000000000 --- a/b2g/components/test/unit/file_persistentdatablock.js +++ /dev/null @@ -1,412 +0,0 @@ -/* 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"; - -var {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); -// This constants must be synced with the ones in PersistentDataBlock.jsm -const PARTITION_MAGIC = 0x19901873; -const DIGEST_SIZE_BYTES = 32; -const PARTITION_MAGIC_SIZE_BYTES = 4; -const DATA_SIZE_BYTES = 4; -const OEM_UNLOCK_ENABLED_BYTES = 1; - -const CACHE_PARTITION = "/dev/block/mtdblock2"; -const PARTITION_FAKE_FILE = "/data/local/tmp/frp.test"; -const CACHE_PARTITION_SIZE = 69206016; - -function log(str) { - do_print("head_persistentdatablock: " + str + "\n"); -} - -function toHexString(data) { - function toHexChar(charCode) { - return ("0" + charCode.toString(16).slice(-2)); - } - let hexString = ""; - if (typeof data === "string") { - hexString = Array.from(data, (c, i) => toHexChar(data.charCodeAt(i))).join(""); - } else if (data instanceof Array) { - hexString = data.map(toHexChar).join(""); - } - return hexString; -} - -function _prepareConfig(_args) { - let args = _args || {}; - // This digest has been previously calculated given the data to be written later, and setting the OEM Unlocked Enabled byte - // to 1. If we need different values, some tests will fail because this precalculated digest won't be valid then. - args.digest = args.digest || new Uint8Array([0x00, 0x41, 0x7e, 0x5f, 0xe2, 0xdd, 0xaa, 0xed, 0x11, 0x90, 0x0e, 0x1d, 0x26, - 0x10, 0x30, 0xbd, 0x44, 0x9e, 0xcc, 0x4b, 0x65, 0xbe, 0x2e, 0x99, 0x9f, 0x86, - 0xf0, 0xfc, 0x5b, 0x33, 0x00, 0xd0]); - args.dataLength = args.dataLength || 6; - args.data = args.data || new Uint8Array(["P", "A", "S", "S", "W", "D"]); - args.oem = args.oem === undefined ? true : args.oem; - args.oemUnlockAllowed = args.oemUnlockAllowed === undefined ? true : args.oemUnlockAllowed; - - log("_prepareConfig: args.digest = " + args.digest); - log("_prepareConfig: args.dataLength = " + args.dataLength); - log("_prepareConfig: args.data = " + args.data); - log("_prepareConfig: args.oem = " + args.oem); - log("_prepareConfig: args.oemUnlockAllowed = " + args.oemUnlockAllowed); - - /* This function will be called after passing all native stuff tests, so we will write into a file instead of a real - * partition. Obviously, there are some native operations like getting the device block size or wipping, that will not - * work in a regular file, so we need to fake them. */ - PersistentDataBlock._libcutils.property_set("sys.oem_unlock_allowed", args.oemUnlockAllowed === true ? "true" : "false"); - PersistentDataBlock.setTestingMode(true); - PersistentDataBlock._dataBlockFile = PARTITION_FAKE_FILE; - // Create the test file with the same structure as the partition will be - let tempFile; - return OS.File.open(PersistentDataBlock._dataBlockFile, {write:true, append:false, truncate: true}).then(_tempFile => { - log("_prepareConfig: Writing DIGEST..."); - tempFile = _tempFile; - return tempFile.write(args.digest); - }).then(bytes => { - log("_prepareConfig: Writing the magic: " + PARTITION_MAGIC); - return tempFile.write(new Uint32Array([PARTITION_MAGIC])); - }).then(bytes => { - log("_prepareConfig: Writing the length of data field"); - return tempFile.write(new Uint32Array([args.dataLength])); - }).then(bytes => { - log("_prepareConfig: Writing the data field"); - let data = new Uint8Array(PersistentDataBlock._getBlockDeviceSize() - - (DIGEST_SIZE_BYTES + PARTITION_MAGIC_SIZE_BYTES + DATA_SIZE_BYTES + OEM_UNLOCK_ENABLED_BYTES)); - data.set(args.data); - return tempFile.write(data); - }).then(bytes => { - return tempFile.write(new Uint8Array([ args.oem === true ? 1 : 0 ])); - }).then(bytes => { - return tempFile.close(); - }).then(() =>{ - return Promise.resolve(true); - }).catch(ex => { - log("_prepareConfig: ERROR: ex = " + ex); - return Promise.reject(ex); - }); -} - -function utils_getByteAt(pos) { - let file; - let byte; - return OS.File.open(PersistentDataBlock._dataBlockFile, {read:true, existing:true, append:false}).then(_file => { - file = _file; - return file.setPosition(pos, OS.File.POS_START); - }).then(() => { - return file.read(1); - }).then(_byte => { - byte = _byte; - return file.close(); - }).then(() => { - return Promise.resolve(byte[0]); - }).catch(ex => { - return Promise.reject(ex); - }); -} - -function utils_getHeader() { - let file; - let header = {}; - return OS.File.open(PersistentDataBlock._dataBlockFile, {read:true, existing:true, append:false}).then(_file => { - file = _file; - return file.read(DIGEST_SIZE_BYTES); - }).then(digest => { - header.digest = digest; - return file.read(PARTITION_MAGIC_SIZE_BYTES); - }).then(magic => { - header.magic = magic; - return file.read(DATA_SIZE_BYTES); - }).then(dataLength => { - header.dataLength = dataLength; - return file.close(); - }).then(() => { - return Promise.resolve(header); - }).catch(ex => { - return Promise.reject(ex); - }); -} - -function utils_getData() { - let file; - let data; - return OS.File.open(PersistentDataBlock._dataBlockFile, {read:true, existing:true, append:false}).then(_file => { - file = _file; - return file.setPosition(DIGEST_SIZE_BYTES + PARTITION_MAGIC_SIZE_BYTES, OS.File.POS_START); - }).then(() => { - return file.read(4); - }).then(_dataLength => { - let dataLength = new Uint32Array(_dataLength.buffer); - log("utils_getData: dataLength = " + dataLength[0]); - return file.read(dataLength[0]); - }).then(_data => { - data = _data; - return file.close(); - }).then(() => { - return Promise.resolve(data); - }).catch(ex => { - return Promise.reject(ex); - }); -} - -function _installTests() { - // Native operation tests go first - add_test(function test_getBlockDeviceSize() { - // We will use emulator /cache partition to get it's size. - PersistentDataBlock._dataBlockFile = CACHE_PARTITION; - // Disable testing mode for this specific test because we can get the size of a real block device, - // but we need to flip to testing mode after this test because we use files instead of partitions - // and we cannot run this operation on files. - PersistentDataBlock.setTestingMode(false); - let blockSize = PersistentDataBlock._getBlockDeviceSize(); - ok(blockSize !== CACHE_PARTITION_SIZE, "test_getBlockDeviceSize: Block device size should be greater than 0"); - run_next_test(); - }); - - add_test(function test_wipe() { - // Turning into testing mode again. - PersistentDataBlock.setTestingMode(true); - PersistentDataBlock.wipe().then(() => { - // We don't evaluate anything because in testing mode we always return ok! - run_next_test(); - }).catch(ex => { - // ... something went really really bad if this happens. - ok(false, "test_wipe failed!: ex: " + ex); - }); - }); - // - - add_test(function test_computeDigest() { - _prepareConfig().then(() => { - PersistentDataBlock._computeDigest().then(digest => { - // So in order to update this value in a future (should only happens if the partition data is changed), you just need - // to launch this test manually, see the result in the logs and update this constant with that value. - const _EXPECTED_VALUE = "0004107e05f0e20dd0aa0ed0110900e01d0260100300bd04409e0cc04b0650be02e09909f0860f00fc05b033000d0"; - let calculatedValue = toHexString(digest.calculated); - strictEqual(calculatedValue, _EXPECTED_VALUE); - run_next_test(); - }).catch(ex => { - ok(false, "test_computeDigest failed!: ex: " + ex); - }); - }); - }); - - add_test(function test_getDataFieldSize() { - PersistentDataBlock.getDataFieldSize().then(dataFieldLength => { - log("test_getDataFieldSize: dataFieldLength is " + dataFieldLength); - strictEqual(dataFieldLength, 6); - run_next_test(); - }).catch(ex => { - ok(false, "test_getOemUnlockedEnabled failed: ex:" + ex); - }); - }); - - add_test(function test_setOemUnlockedEnabledToTrue() { - PersistentDataBlock.setOemUnlockEnabled(true).then(() => { - return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); - }).then(byte => { - log("test_setOemUnlockedEnabledToTrue: byte = " + byte ); - strictEqual(byte, 1); - run_next_test(); - }).catch(ex => { - ok(false, "test_setOemUnlockedEnabledToTrue failed!: ex: " + ex); - }); - }); - - add_test(function test_setOemUnlockedEnabledToFalse() { - PersistentDataBlock.setOemUnlockEnabled(false).then(() => { - return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); - }).then(byte => { - log("test_setOemUnlockedEnabledToFalse: byte = " + byte ); - strictEqual(byte, 0); - run_next_test(); - }).catch(ex => { - ok(false, "test_setOemUnlockedEnabledToFalse failed!: ex: " + ex); - }); - }); - - add_test(function test_getOemUnlockedEnabledWithTrue() { - // We first need to set the OEM Unlock Enabled byte to true so we can test - // the getter properly - PersistentDataBlock.setOemUnlockEnabled(true).then(() => { - return PersistentDataBlock.getOemUnlockEnabled().then(enabled => { - log("test_getOemUnlockedEnabledWithTrue: enabled is " + enabled); - ok(enabled === true, "test_getOemUnlockedEnabledWithTrue: enabled value should be true"); - run_next_test(); - }).catch(ex => { - ok(false, "test_getOemUnlockedEnabledWithTrue failed: ex:" + ex); - }); - }).catch(ex => { - ok(false, "test_getOemUnlockedEnabledWithTrue failed: An error ocurred while setting the OEM Unlock Enabled byte to true: ex:" + ex); - }); - }); - - add_test(function test_getOemUnlockedEnabledWithFalse() { - // We first need to set the OEM Unlock Enabled byte to false so we can test - // the getter properly - PersistentDataBlock.setOemUnlockEnabled(false).then(() => { - return PersistentDataBlock.getOemUnlockEnabled().then(enabled => { - log("test_getOemUnlockedEnabledWithFalse: enabled is " + enabled); - ok(enabled === false, "test_getOemUnlockedEnabledWithFalse: enabled value should be false"); - run_next_test(); - }).catch(ex => { - ok(false, "test_getOemUnlockedEnabledWithFalse failed: ex:" + ex); - }); - }).catch(ex => { - ok(false, "test_getOemUnlockedEnabledWithFalse failed: An error ocurred while setting the OEM Unlock Enabled byte to false: ex:" + ex); - }); - }); - - add_test(function test_computeAndWriteDigest() { - PersistentDataBlock._computeAndWriteDigest().then(() => { - return utils_getHeader(); - }).then(header => { - log("test_computeAndWriteDigest: header = " + header); - let magicRead = new Uint32Array(header.magic.buffer); - let magicSupposed = new Uint32Array([PARTITION_MAGIC]); - strictEqual(magicRead[0], magicSupposed[0]); - let dataLength = new Uint32Array([header.dataLength]); - strictEqual(header.dataLength[0], 6); - run_next_test(); - }).catch(ex => { - ok(false, "test_computeAndWriteDigest failed!: ex: " + ex); - }); - }); - - add_test(function test_formatIfOemUnlockEnabledWithTrue() { - _prepareConfig({oem:true}).then(() => { - return PersistentDataBlock._formatIfOemUnlockEnabled(); - }).then(result => { - ok(result === true, "test_formatIfOemUnlockEnabledWithTrue: result should be true"); - return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); - }).then(byte => { - // Check if the OEM Unlock Enabled byte is 1 - strictEqual(byte, 1); - run_next_test(); - }).catch(ex => { - ok(false, "test_formatIfOemUnlockEnabledWithTrue failed!: ex: " + ex); - }); - }); - - add_test(function test_formatIfOemUnlockEnabledWithFalse() { - _prepareConfig({oem:false}).then(() => { - return PersistentDataBlock._formatIfOemUnlockEnabled(); - }).then(result => { - log("test_formatIfOemUnlockEnabledWithFalse: result = " + result); - ok(result === false, "test_formatIfOemUnlockEnabledWithFalse: result should be false"); - return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); - }).then(byte => { - // Check if the OEM Unlock Enabled byte is 0 - strictEqual(byte, 0); - run_next_test(); - }).catch(ex => { - ok(false, "test_formatIfOemUnlockEnabledWithFalse failed!: ex: " + ex); - }); - }); - - add_test(function test_formatPartition() { - // Restore a fullfilled partition so we can check if formatting works... - _prepareConfig({oem:true}).then(() => { - return PersistentDataBlock._formatPartition(true); - }).then(() => { - return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); - }).then(byte => { - // Check if the last byte is 1 - strictEqual(byte, 1); - return utils_getHeader(); - }).then(header => { - // The Magic number should exists in a formatted partition - let magicRead = new Uint32Array(header.magic.buffer); - let magicSupposed = new Uint32Array([PARTITION_MAGIC]); - strictEqual(magicRead[0], magicSupposed[0]); - // In a formatted partition, the digest field is always 32 bytes of zeros. - let digestSupposed = new Uint8Array(DIGEST_SIZE_BYTES); - strictEqual(header.digest.join(""), "94227253995810864198417798821014713171138121254110134189198178208133167236184116199"); - return PersistentDataBlock._formatPartition(false); - }).then(() => { - return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); - }).then(byte => { - // In this case OEM Unlock enabled byte should be set to 0 because we passed false to the _formatPartition method before. - strictEqual(byte, 0); - run_next_test(); - }).catch(ex => { - ok(false, "test_formatPartition failed!: ex: " + ex); - }); - }); - - add_test(function test_enforceChecksumValidityWithValidChecksum() { - // We need a valid partition layout to pass this test - _prepareConfig().then(() => { - PersistentDataBlock._enforceChecksumValidity().then(() => { - ok(true, "test_enforceChecksumValidityWithValidChecksum passed"); - run_next_test(); - }).catch(ex => { - ok(false, "test_enforceChecksumValidityWithValidChecksum failed!: ex: " + ex); - }); - }); - }); - - add_test(function test_enforceChecksumValidityWithInvalidChecksum() { - var badDigest = new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1C, 0x1D, 0x1E, 0x1F, 0x20]); - // We need a valid partition layout to pass this test - _prepareConfig({digest: badDigest}).then(() => { - PersistentDataBlock._enforceChecksumValidity().then(() => { - return utils_getHeader(); - }).then(header => { - // Check that we have a valid magic after formatting - let magicRead = new Uint32Array(header.magic.buffer)[0]; - let magicSupposed = new Uint32Array([PARTITION_MAGIC])[0]; - strictEqual(magicRead, magicSupposed); - // Data length field should be 0, because we formatted the partition - let dataLengthRead = new Uint32Array(header.dataLength.buffer)[0]; - strictEqual(dataLengthRead, 0); - run_next_test(); - }).catch(ex => { - ok(false, "test_enforceChecksumValidityWithValidChecksum failed!: ex: " + ex); - }); - }); - }); - - add_test(function test_read() { - // Before reading, let's write some bytes of data first. - PersistentDataBlock.write(new Uint8Array([1,2,3,4])).then(() => { - PersistentDataBlock.read().then(bytes => { - log("test_read: bytes (in hex): " + toHexString(bytes)); - strictEqual(bytes[0], 1); - strictEqual(bytes[1], 2); - strictEqual(bytes[2], 3); - strictEqual(bytes[3], 4); - run_next_test(); - }).catch(ex => { - ok(false, "test_read failed!: ex: " + ex); - }); - }); - - }); - - add_test(function test_write() { - let data = new Uint8Array(['1','2','3','4','5']); - PersistentDataBlock.write(data).then(bytesWrittenLength => { - log("test_write: bytesWrittenLength = " + bytesWrittenLength); - return utils_getData(); - }).then(data => { - strictEqual(data[0], 1); - strictEqual(data[1], 2); - strictEqual(data[2], 3); - strictEqual(data[3], 4); - strictEqual(data[4], 5); - run_next_test(); - }).catch(ex => { - ok(false, "test_write failed!: ex: " + ex); - }); - }); -} diff --git a/b2g/components/test/unit/test_killswitch.js b/b2g/components/test/unit/test_killswitch.js deleted file mode 100644 index c7d4a448de5b..000000000000 --- a/b2g/components/test/unit/test_killswitch.js +++ /dev/null @@ -1,108 +0,0 @@ -/* 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"; - -var {results: Cr} = Components; - -// Trivial test just to make sure we have no syntax error -add_test(function test_ksm_ok() { - ok(KillSwitchMain, "KillSwitchMain object exists"); - - run_next_test(); -}); - -var aMessageNoPerm = { - name: "KillSwitch:Enable", - target: { - assertPermission: function() { - return false; - }, - killChild: function() { } - } -}; - -var aMessageWithPerm = { - name: "KillSwitch:Enable", - target: { - assertPermission: function() { - return true; - } - }, - data: { - requestID: 0 - } -}; - -add_test(function test_sendMessageWithoutPerm() { - try { - KillSwitchMain.receiveMessage(aMessageNoPerm); - ok(false, "Should have failed"); - } catch (ex) { - // strictEqual(ex, Cr.NS_ERROR_NOT_AVAILABLE); - } - run_next_test(); -}); - -add_test(function test_sendMessageWithPerm() { - let rv = KillSwitchMain.receiveMessage(aMessageWithPerm); - strictEqual(rv, undefined); - run_next_test(); -}); - -var uMessage = { - name: "KillSwitch:WTF", - target: { - assertPermission: function() { - return true; - }, - killChild: function() { } - } -}; - -add_test(function test_sendUnknownMessage() { - try { - KillSwitchMain.receiveMessage(uMessage); - ok(false, "Should have failed"); - } catch (ex) { - strictEqual(ex, Cr.NS_ERROR_ILLEGAL_VALUE); - } - run_next_test(); -}); - -var fakeLibcUtils = { - _props_: {}, - property_set: function(name, value) { - dump("property_set('" + name + "', '" + value+ "' [" + (typeof value) + "]);\n"); - this._props_[name] = value; - }, - property_get: function(name, defaultValue) { - dump("property_get('" + name + "', '" + defaultValue+ "');\n"); - if (Object.keys(this._props_).indexOf(name) !== -1) { - return this._props_[name]; - } else { - return defaultValue; - } - } -}; - -add_test(function test_nolibcutils() { - KillSwitchMain._libcutils = null; - try { - KillSwitchMain.checkLibcUtils(); - ok(false, "Should have failed"); - } catch (ex) { - strictEqual(ex, Cr.NS_ERROR_NO_INTERFACE); - } - run_next_test(); -}); - -add_test(function test_install_fakelibcutils() { - KillSwitchMain._libcutils = fakeLibcUtils; - let rv = KillSwitchMain.checkLibcUtils(); - strictEqual(rv, true); - run_next_test(); -}); - -install_common_tests(); diff --git a/b2g/components/test/unit/test_killswitch_gonk.js b/b2g/components/test/unit/test_killswitch_gonk.js deleted file mode 100644 index bf6d89d73f58..000000000000 --- a/b2g/components/test/unit/test_killswitch_gonk.js +++ /dev/null @@ -1,42 +0,0 @@ -/* 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/. */ - -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyGetter(this, "libcutils", function () { - Cu.import("resource://gre/modules/systemlibs.js"); - return libcutils; -}); - -// Trivial test just to make sure we have no syntax error -add_test(function test_ksm_ok() { - ok(KillSwitchMain, "KillSwitchMain object exists"); - - run_next_test(); -}); - -add_test(function test_has_libcutils() { - let rv = KillSwitchMain.checkLibcUtils(); - strictEqual(rv, true); - run_next_test(); -}); - -add_test(function test_libcutils_works() { - KillSwitchMain._libcutils.property_set("ro.moz.ks_test", "wesh"); - let rv_ks_get = KillSwitchMain._libcutils.property_get("ro.moz.ks_test"); - strictEqual(rv_ks_get, "wesh") - let rv_sys_get = libcutils.property_get("ro.moz.ks_test") - strictEqual(rv_sys_get, "wesh") - - KillSwitchMain._libcutils.property_set("ro.moz.ks_test2", "123456789"); - rv_ks_get = KillSwitchMain._libcutils.property_get("ro.moz.ks_test2"); - strictEqual(rv_ks_get, "123456789") - rv_sys_get = libcutils.property_get("ro.moz.ks_test2") - strictEqual(rv_sys_get, "123456789") - - run_next_test(); -}); - -install_common_tests(); diff --git a/b2g/components/test/unit/test_persistentdatablock_gonk.js b/b2g/components/test/unit/test_persistentdatablock_gonk.js deleted file mode 100644 index 067eb83e3344..000000000000 --- a/b2g/components/test/unit/test_persistentdatablock_gonk.js +++ /dev/null @@ -1,21 +0,0 @@ -/* 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/. */ - -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyGetter(this, "libcutils", function () { - Cu.import("resource://gre/modules/systemlibs.js"); - return libcutils; -}); - -function run_test() { - do_get_profile(); - Cu.import("resource://gre/modules/PersistentDataBlock.jsm"); - // We need to point to a valid partition for some of the tests. This is the /cache - // partition in the emulator (x86-KitaKat). - run_next_test(); -} - -_installTests(); diff --git a/b2g/components/test/unit/xpcshell.ini b/b2g/components/test/unit/xpcshell.ini index 9716e7264f96..ca3df5bf610d 100644 --- a/b2g/components/test/unit/xpcshell.ini +++ b/b2g/components/test/unit/xpcshell.ini @@ -47,21 +47,3 @@ head = head_logshake_gonk.js skip-if = (toolkit != "gonk") [test_aboutserviceworkers.js] - -[test_killswitch.js] -head = file_killswitch.js -skip-if = (toolkit == "gonk") - -[test_killswitch_gonk.js] -head = file_killswitch.js -# Bug 1193677: disable on B2G ICS Emulator for intermittent failures with IndexedDB -skip-if = ((toolkit != "gonk") || (toolkit == "gonk" && debug)) - -[test_persistentdatablock_gonk.js] -# can be slow because of what the test does, so let's give it some more time -# to avoid intermittents: bug 1235290 -requesttimeoutfactor = 2 -head = file_persistentdatablock.js -skip-if = (toolkit != "gonk") - - diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 7e0ab05b4d4a..8e97297a559b 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -889,7 +889,6 @@ bin/libfreebl_32int64_3.so @RESPATH@/components/B2GAppMigrator.js @RESPATH@/components/B2GPresentationDevicePrompt.js @RESPATH@/components/PresentationRequestUIGlue.js -@RESPATH@/components/KillSwitch.js #ifndef MOZ_WIDGET_GONK @RESPATH@/components/SimulatorScreen.js diff --git a/dom/apps/PermissionsTable.jsm b/dom/apps/PermissionsTable.jsm index e3f936bef541..2acb433fb70d 100644 --- a/dom/apps/PermissionsTable.jsm +++ b/dom/apps/PermissionsTable.jsm @@ -502,12 +502,6 @@ this.PermissionsTable = { geolocation: { app: DENY_ACTION, privileged: DENY_ACTION, certified: ALLOW_ACTION - }, - "killswitch": { - app: DENY_ACTION, - trusted: DENY_ACTION, - privileged: DENY_ACTION, - certified: ALLOW_ACTION } }; diff --git a/dom/webidl/KillSwitch.webidl b/dom/webidl/KillSwitch.webidl deleted file mode 100644 index 99e1276fa5bd..000000000000 --- a/dom/webidl/KillSwitch.webidl +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. - */ - -/** - * This API is intended to lock the device in a way that it has no value - * anymore for a thief. A side effect is also protecting user's data. This - * means that we expect the device to be: - * - locked so that only the legitimate user can unlock it - * - unable to communitate via ADB, Devtools, MTP and/or UMS, ... - * - unable to go into recovery or fastboot mode to avoid flashing anything - */ - -[JSImplementation="@mozilla.org/moz-kill-switch;1", - NavigatorProperty="mozKillSwitch", - AvailableIn="CertifiedApps", - CheckAnyPermissions="killswitch", - Pref="dom.mozKillSwitch.enabled"] -interface KillSwitch { - Promise enable(); - Promise disable(); -}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index bd71e6f50a63..7e9620f14d7f 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -287,7 +287,6 @@ WEBIDL_FILES = [ 'KeyboardEvent.webidl', 'KeyEvent.webidl', 'KeyframeEffect.webidl', - 'KillSwitch.webidl', 'LegacyQueryInterface.webidl', 'LinkStyle.webidl', 'ListBoxObject.webidl', diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index b08d8f28e10a..62a9b5f0b3b9 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5429,8 +5429,6 @@ pref("media.useAudioChannelAPI", false); // Expose Request.context. Currently disabled since the spec is in flux. pref("dom.requestcontext.enabled", false); -pref("dom.mozKillSwitch.enabled", false); - pref("toolkit.pageThumbs.screenSizeDivisor", 7); pref("toolkit.pageThumbs.minWidth", 0); pref("toolkit.pageThumbs.minHeight", 0);