mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1181561 - Expose a Kill Switch enabling/disabling. r=dhylands, sr=sicking
This commit is contained in:
parent
21040381bc
commit
5c27fc8460
@ -23,6 +23,7 @@ Cu.import('resource://gre/modules/SystemUpdateService.jsm');
|
||||
Cu.import('resource://gre/modules/NetworkStatsService.jsm');
|
||||
Cu.import('resource://gre/modules/ResourceStatsService.jsm');
|
||||
#endif
|
||||
Cu.import('resource://gre/modules/KillSwitchMain.jsm');
|
||||
|
||||
// Identity
|
||||
Cu.import('resource://gre/modules/SignInToWebsite.jsm');
|
||||
|
@ -121,3 +121,7 @@ contract @mozilla.org/presentation-device/prompt;1 {4a300c26-e99b-4018-ab9b-c48c
|
||||
# PresentationRequestUIGlue.js
|
||||
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}
|
||||
|
116
b2g/components/KillSwitch.js
Normal file
116
b2g/components/KillSwitch.js
Normal file
@ -0,0 +1,116 @@
|
||||
/* 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]);
|
505
b2g/components/KillSwitchMain.jsm
Normal file
505
b2g/components/KillSwitchMain.jsm
Normal file
@ -0,0 +1,505 @@
|
||||
/* 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");
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
|
||||
Cu.import("resource://gre/modules/systemlibs.js");
|
||||
return libcutils;
|
||||
});
|
||||
#else
|
||||
this.libcutils = null;
|
||||
#endif
|
||||
|
||||
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");
|
||||
|
||||
let 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();
|
||||
}
|
@ -18,6 +18,7 @@ EXTRA_COMPONENTS += [
|
||||
'FxAccountsUIGlue.js',
|
||||
'HelperAppDialog.js',
|
||||
'InterAppCommUIGlue.js',
|
||||
'KillSwitch.js',
|
||||
'MailtoProtocolHandler.js',
|
||||
'MobileIdentityUIGlue.js',
|
||||
'OMAContentHandler.js',
|
||||
@ -70,6 +71,10 @@ EXTRA_JS_MODULES += [
|
||||
'WebappsUpdater.jsm',
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'KillSwitchMain.jsm'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
|
||||
EXTRA_JS_MODULES += [
|
||||
'GlobalSimulatorScreen.jsm'
|
||||
|
67
b2g/components/test/mochitest/file_loadserver.js
Normal file
67
b2g/components/test/mochitest/file_loadserver.js
Normal file
@ -0,0 +1,67 @@
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
let Cu = Components.utils;
|
||||
|
||||
// Stolen from SpecialPowers, since at this point we don't know we're in a test.
|
||||
let 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;
|
||||
});
|
||||
}
|
149
b2g/components/test/mochitest/killswitch.js
Normal file
149
b2g/components/test/mochitest/killswitch.js
Normal file
@ -0,0 +1,149 @@
|
||||
/* 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);
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
[DEFAULT]
|
||||
skip-if = toolkit != "gonk"
|
||||
support-files =
|
||||
permission_handler_chrome.js
|
||||
SandboxPromptTest.html
|
||||
@ -8,14 +7,27 @@ 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"
|
||||
[test_permission_deny.html]
|
||||
skip-if = toolkit != "gonk"
|
||||
[test_permission_gum_remember.html]
|
||||
skip-if = true # Bug 1019572 - frequent timeouts
|
||||
[test_sandbox_permission.html]
|
||||
skip-if = toolkit != "gonk"
|
||||
[test_screenshot.html]
|
||||
skip-if = toolkit != "gonk"
|
||||
[test_systemapp.html]
|
||||
skip-if = toolkit != "gonk"
|
||||
[test_presentation_device_prompt.html]
|
||||
skip-if = toolkit != "gonk"
|
||||
[test_permission_visibilitychange.html]
|
||||
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]
|
||||
|
92
b2g/components/test/mochitest/test_killswitch_basics.html
Normal file
92
b2g/components/test/mochitest/test_killswitch_basics.html
Normal file
@ -0,0 +1,92 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Enabling of killswitch feature</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
function testNotExposed(check) {
|
||||
ok(!("mozKillSwitch" in navigator),
|
||||
"mozKillSwitch not exposed in navigator: " + check);
|
||||
}
|
||||
|
||||
function testIsExposed() {
|
||||
ok(("mozKillSwitch" in navigator), "mozKillSwitch is exposed in navigator");
|
||||
ok(("enable" in navigator.mozKillSwitch), "mozKillSwitch has |enable|");
|
||||
ok(("disable" in navigator.mozKillSwitch), "mozKillSwitch has |disable|");
|
||||
}
|
||||
|
||||
function continueTests() {
|
||||
// Now we should have it!
|
||||
testIsExposed();
|
||||
finish();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SpecialPowers.removePermission("killswitch", document);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function alreadyHasPermission() {
|
||||
return SpecialPowers.hasPermission("killswitch", document);
|
||||
}
|
||||
|
||||
function addPermission() {
|
||||
var allow = SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
SpecialPowers.addPermission("killswitch", allow, document);
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function addPrefIgnoreWebIDL(next) {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.ignore_webidl_scope_checks", true],
|
||||
]}, next);
|
||||
}
|
||||
|
||||
function addPrefKillSwitch(next) {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.mozKillSwitch.enabled", true],
|
||||
]}, next);
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
if (alreadyHasPermission()) {
|
||||
continueTests();
|
||||
} else {
|
||||
// Make sure it's not exposed
|
||||
testNotExposed("webidl, pref, perm");
|
||||
|
||||
// Expose certified APIs
|
||||
addPrefIgnoreWebIDL(() => {
|
||||
// Still not exposed because not perm and pref
|
||||
testNotExposed("pref, perm");
|
||||
|
||||
// Add the kill switch pref
|
||||
addPrefKillSwitch(() => {
|
||||
// Still not exposed because not perm
|
||||
testNotExposed("perm");
|
||||
|
||||
// Will reload the page
|
||||
addPermission();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
startTests();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
65
b2g/components/test/mochitest/test_killswitch_disable.html
Normal file
65
b2g/components/test/mochitest/test_killswitch_disable.html
Normal file
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Disabling of killswitch feature</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js">
|
||||
</script>
|
||||
<script type="application/javascript" src="killswitch.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
var initialSettingsValues = {
|
||||
"lockscreen.locked": true,
|
||||
"lockscreen.lock-immediately": true
|
||||
};
|
||||
|
||||
var initialPrefsValues = {
|
||||
"b2g.killswitch.test": true
|
||||
};
|
||||
|
||||
var disabledSettingsExpected = {
|
||||
"lockscreen.locked": false,
|
||||
"lockscreen.lock-immediately": false
|
||||
};
|
||||
|
||||
var disabledPrefsExpected = {
|
||||
"b2g.killswitch.test": false
|
||||
};
|
||||
|
||||
function testDoAction() {
|
||||
return navigator.mozKillSwitch.disable();
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
setupSettings(disabledSettingsExpected);
|
||||
setupPrefs(initialPrefsValues);
|
||||
testSettingsInitial(() => {
|
||||
testPrefsInitial();
|
||||
testDoAction().then(() => {
|
||||
testSettingsExpected(disabledSettingsExpected, () => {
|
||||
testPrefsExpected(disabledPrefsExpected);
|
||||
finish();
|
||||
});
|
||||
}).catch(() => {
|
||||
ok(false, "KillSwitch promise failed");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
loadSettings();
|
||||
addPrefs();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
65
b2g/components/test/mochitest/test_killswitch_enable.html
Normal file
65
b2g/components/test/mochitest/test_killswitch_enable.html
Normal file
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Enabling of killswitch feature</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js">
|
||||
</script>
|
||||
<script type="application/javascript" src="killswitch.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
var initialSettingsValues = {
|
||||
"lockscreen.locked": false,
|
||||
"lockscreen.lock-immediately": false
|
||||
};
|
||||
|
||||
var initialPrefsValues = {
|
||||
"b2g.killswitch.test": false
|
||||
};
|
||||
|
||||
var enabledSettingsExpected = {
|
||||
"lockscreen.locked": true,
|
||||
"lockscreen.lock-immediately": true
|
||||
};
|
||||
|
||||
var enabledPrefsExpected = {
|
||||
"b2g.killswitch.test": true
|
||||
};
|
||||
|
||||
function testDoAction() {
|
||||
return navigator.mozKillSwitch.enable();
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
setupSettings(enabledSettingsExpected);
|
||||
setupPrefs(initialPrefsValues);
|
||||
testSettingsInitial(() => {
|
||||
testPrefsInitial();
|
||||
testDoAction().then(() => {
|
||||
testSettingsExpected(enabledSettingsExpected, () => {
|
||||
testPrefsExpected(enabledPrefsExpected);
|
||||
finish();
|
||||
});
|
||||
}).catch(() => {
|
||||
ok(false, "KillSwitch promise failed");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
loadSettings();
|
||||
addPrefs();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
425
b2g/components/test/unit/file_killswitch.js
Normal file
425
b2g/components/test/unit/file_killswitch.js
Normal file
@ -0,0 +1,425 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
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");
|
||||
|
||||
let 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();
|
||||
});
|
||||
});
|
||||
}
|
108
b2g/components/test/unit/test_killswitch.js
Normal file
108
b2g/components/test/unit/test_killswitch.js
Normal file
@ -0,0 +1,108 @@
|
||||
/* 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 {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();
|
||||
});
|
||||
|
||||
let aMessageNoPerm = {
|
||||
name: "KillSwitch:Enable",
|
||||
target: {
|
||||
assertPermission: function() {
|
||||
return false;
|
||||
},
|
||||
killChild: function() { }
|
||||
}
|
||||
};
|
||||
|
||||
let 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();
|
||||
});
|
||||
|
||||
let 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();
|
||||
});
|
||||
|
||||
let 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();
|
42
b2g/components/test/unit/test_killswitch_gonk.js
Normal file
42
b2g/components/test/unit/test_killswitch_gonk.js
Normal file
@ -0,0 +1,42 @@
|
||||
/* 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();
|
@ -41,3 +41,12 @@ 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))
|
||||
|
@ -961,6 +961,7 @@ 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
|
||||
|
@ -497,6 +497,12 @@ this.PermissionsTable = { geolocation: {
|
||||
trusted: DENY_ACTION,
|
||||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"killswitch": {
|
||||
app: DENY_ACTION,
|
||||
trusted: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
}
|
||||
};
|
||||
|
||||
|
24
dom/webidl/KillSwitch.webidl
Normal file
24
dom/webidl/KillSwitch.webidl
Normal file
@ -0,0 +1,24 @@
|
||||
/* -*- 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<any> enable();
|
||||
Promise<any> disable();
|
||||
};
|
@ -276,6 +276,7 @@ WEBIDL_FILES = [
|
||||
'KeyboardEvent.webidl',
|
||||
'KeyEvent.webidl',
|
||||
'KeyframeEffect.webidl',
|
||||
'KillSwitch.webidl',
|
||||
'LegacyQueryInterface.webidl',
|
||||
'LinkStyle.webidl',
|
||||
'ListBoxObject.webidl',
|
||||
|
@ -5073,3 +5073,5 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user