зеркало из https://github.com/mozilla/gecko-dev.git
Merge b2g-inbound to m-c a=merge
This commit is contained in:
Коммит
c3fdde7659
|
@ -671,6 +671,44 @@ SettingsListener.observe("accessibility.screenreader", false, function(value) {
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// =================== Low-precision buffer ======================
|
||||||
|
(function setupLowPrecisionSettings() {
|
||||||
|
// The gaia setting layers.low-precision maps to two gecko prefs
|
||||||
|
SettingsListener.observe('layers.low-precision', null, function(value) {
|
||||||
|
if (value !== null) {
|
||||||
|
// Update gecko from the new Gaia setting
|
||||||
|
Services.prefs.setBoolPref('layers.low-precision-buffer', value);
|
||||||
|
Services.prefs.setBoolPref('layers.progressive-paint', value);
|
||||||
|
} else {
|
||||||
|
// Update gaia setting from gecko value
|
||||||
|
try {
|
||||||
|
let prefValue = Services.prefs.getBoolPref('layers.low-precision-buffer');
|
||||||
|
let setting = { 'layers.low-precision': prefValue };
|
||||||
|
window.navigator.mozSettings.createLock().set(setting);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Unable to read pref layers.low-precision-buffer: ' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// The gaia setting layers.low-opacity maps to a string gecko pref (0.5/1.0)
|
||||||
|
SettingsListener.observe('layers.low-opacity', null, function(value) {
|
||||||
|
if (value !== null) {
|
||||||
|
// Update gecko from the new Gaia setting
|
||||||
|
Services.prefs.setCharPref('layers.low-precision-opacity', value ? '0.5' : '1.0');
|
||||||
|
} else {
|
||||||
|
// Update gaia setting from gecko value
|
||||||
|
try {
|
||||||
|
let prefValue = Services.prefs.getCharPref('layers.low-precision-opacity');
|
||||||
|
let setting = { 'layers.low-opacity': (prefValue == '0.5') };
|
||||||
|
window.navigator.mozSettings.createLock().set(setting);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Unable to read pref layers.low-precision-opacity: ' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
// =================== Various simple mapping ======================
|
// =================== Various simple mapping ======================
|
||||||
let settingsToObserve = {
|
let settingsToObserve = {
|
||||||
'app.update.channel': {
|
'app.update.channel': {
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
|
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
"remote": "",
|
"remote": "",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "d7d92199ea7e8f850ca0c6f0514bf596f178a16f",
|
"revision": "4024e28dbc44b11d3297378484c2474dcee425fa",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="449d632c69b1a4bd5101d07d18f76799d3fd5f38"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c527178b78a5bc85b76f89d6ba7f0bb464963b79"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d61daef8fca7d6f335f659a8967bad423770e634"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
|
|
|
@ -8,10 +8,10 @@ const Cu = Components.utils;
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
|
|
||||||
// This module exposes a subset of the functionnalities of the parent DOM
|
// This module exposes a subset of the functionalities of the parent DOM
|
||||||
// Registry to content processes, to be be used from the AppsService component.
|
// Registry to content processes, to be used from the AppsService component.
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["DOMApplicationRegistry"];
|
this.EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "WrappedManifestCache"];
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
@ -20,54 +20,324 @@ function debug(s) {
|
||||||
//dump("-*- AppsServiceChild.jsm: " + s + "\n");
|
//dump("-*- AppsServiceChild.jsm: " + s + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const APPS_IPC_MSG_NAMES = [
|
||||||
|
"Webapps:AddApp",
|
||||||
|
"Webapps:RemoveApp",
|
||||||
|
"Webapps:UpdateApp",
|
||||||
|
"Webapps:CheckForUpdate:Return:KO",
|
||||||
|
"Webapps:FireEvent",
|
||||||
|
"Webapps:UpdateState"
|
||||||
|
];
|
||||||
|
|
||||||
|
// A simple cache for the wrapped manifests.
|
||||||
|
this.WrappedManifestCache = {
|
||||||
|
_cache: { },
|
||||||
|
|
||||||
|
// Gets an entry from the cache, and populates the cache if needed.
|
||||||
|
get: function mcache_get(aManifestURL, aManifest, aWindow, aInnerWindowID) {
|
||||||
|
if (!aManifest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(aManifestURL in this._cache)) {
|
||||||
|
this._cache[aManifestURL] = { };
|
||||||
|
}
|
||||||
|
|
||||||
|
let winObjs = this._cache[aManifestURL];
|
||||||
|
if (!(aInnerWindowID in winObjs)) {
|
||||||
|
winObjs[aInnerWindowID] = Cu.cloneInto(aManifest, aWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return winObjs[aInnerWindowID];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Invalidates an entry in the cache.
|
||||||
|
evict: function mcache_evict(aManifestURL, aInnerWindowID) {
|
||||||
|
debug("Evicting manifest " + aManifestURL + " window ID " +
|
||||||
|
aInnerWindowID);
|
||||||
|
if (aManifestURL in this._cache) {
|
||||||
|
let winObjs = this._cache[aManifestURL];
|
||||||
|
if (aInnerWindowID in winObjs) {
|
||||||
|
delete winObjs[aInnerWindowID];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(winObjs).length == 0) {
|
||||||
|
delete this._cache[aManifestURL];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
observe: function(aSubject, aTopic, aData) {
|
||||||
|
// Clear the cache on memory pressure.
|
||||||
|
this._cache = { };
|
||||||
|
Cu.forceGC();
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
Services.obs.addObserver(this, "memory-pressure", false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.WrappedManifestCache.init();
|
||||||
|
|
||||||
|
|
||||||
|
// DOMApplicationRegistry keeps a cache containing a list of apps in the device.
|
||||||
|
// This information is updated with the data received from the main process and
|
||||||
|
// it is queried by the DOM objects to set their state.
|
||||||
|
// This module handle all the messages broadcasted from the parent process,
|
||||||
|
// including DOM events, which are dispatched to the corresponding DOM objects.
|
||||||
|
|
||||||
this.DOMApplicationRegistry = {
|
this.DOMApplicationRegistry = {
|
||||||
|
// DOMApps will hold a list of arrays of weak references to
|
||||||
|
// mozIDOMApplication objects indexed by manifest URL.
|
||||||
|
DOMApps: {},
|
||||||
|
|
||||||
|
ready: false,
|
||||||
|
webapps: null,
|
||||||
|
|
||||||
init: function init() {
|
init: function init() {
|
||||||
debug("init");
|
|
||||||
this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
|
this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||||
.getService(Ci.nsISyncMessageSender);
|
.getService(Ci.nsISyncMessageSender);
|
||||||
|
|
||||||
["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
|
APPS_IPC_MSG_NAMES.forEach((function(aMsgName) {
|
||||||
this.cpmm.addMessageListener(aMsgName, this);
|
this.cpmm.addMessageListener(aMsgName, this);
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
// We need to prime the cache with the list of apps.
|
this.cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
|
||||||
// XXX shoud we do this async and block callers if it's not yet there?
|
messages: APPS_IPC_MSG_NAMES
|
||||||
this.webapps = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
|
});
|
||||||
|
|
||||||
|
// We need to prime the cache with the list of apps.
|
||||||
|
let list = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
|
||||||
|
this.webapps = list.webapps;
|
||||||
// We need a fast mapping from localId -> app, so we add an index.
|
// We need a fast mapping from localId -> app, so we add an index.
|
||||||
|
// We also add the manifest to the app object.
|
||||||
this.localIdIndex = { };
|
this.localIdIndex = { };
|
||||||
for (let id in this.webapps) {
|
for (let id in this.webapps) {
|
||||||
let app = this.webapps[id];
|
let app = this.webapps[id];
|
||||||
this.localIdIndex[app.localId] = app;
|
this.localIdIndex[app.localId] = app;
|
||||||
|
app.manifest = list.manifests[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||||
},
|
},
|
||||||
|
|
||||||
observe: function(aSubject, aTopic, aData) {
|
observe: function(aSubject, aTopic, aData) {
|
||||||
// cpmm.addMessageListener causes the DOMApplicationRegistry object to live
|
// cpmm.addMessageListener causes the DOMApplicationRegistry object to
|
||||||
// forever if we don't clean up properly.
|
// live forever if we don't clean up properly.
|
||||||
this.webapps = null;
|
this.webapps = null;
|
||||||
["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
|
this.DOMApps = null;
|
||||||
|
|
||||||
|
APPS_IPC_MSG_NAMES.forEach((aMsgName) => {
|
||||||
this.cpmm.removeMessageListener(aMsgName, this);
|
this.cpmm.removeMessageListener(aMsgName, this);
|
||||||
}).bind(this));
|
});
|
||||||
|
|
||||||
|
this.cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
|
||||||
|
APPS_IPC_MSG_NAMES)
|
||||||
},
|
},
|
||||||
|
|
||||||
receiveMessage: function receiveMessage(aMessage) {
|
receiveMessage: function receiveMessage(aMessage) {
|
||||||
debug("Received " + aMessage.name + " message.");
|
debug("Received " + aMessage.name + " message.");
|
||||||
let msg = aMessage.json;
|
let msg = aMessage.data;
|
||||||
switch (aMessage.name) {
|
switch (aMessage.name) {
|
||||||
case "Webapps:AddApp":
|
case "Webapps:AddApp":
|
||||||
this.webapps[msg.id] = msg.app;
|
this.webapps[msg.id] = msg.app;
|
||||||
this.localIdIndex[msg.app.localId] = msg.app;
|
this.localIdIndex[msg.app.localId] = msg.app;
|
||||||
|
if (msg.manifest) {
|
||||||
|
this.webapps[msg.id].manifest = msg.manifest;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "Webapps:RemoveApp":
|
case "Webapps:RemoveApp":
|
||||||
|
delete this.DOMApps[this.webapps[msg.id].manifestURL];
|
||||||
delete this.localIdIndex[this.webapps[msg.id].localId];
|
delete this.localIdIndex[this.webapps[msg.id].localId];
|
||||||
delete this.webapps[msg.id];
|
delete this.webapps[msg.id];
|
||||||
break;
|
break;
|
||||||
|
case "Webapps:UpdateApp":
|
||||||
|
let app = this.webapps[msg.oldId];
|
||||||
|
if (!app) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.app) {
|
||||||
|
for (let prop in msg.app) {
|
||||||
|
app[prop] = msg.app[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.webapps[msg.newId] = app;
|
||||||
|
this.localIdIndex[app.localId] = app;
|
||||||
|
delete this.webapps[msg.oldId];
|
||||||
|
|
||||||
|
let apps = this.DOMApps[msg.app.manifestURL];
|
||||||
|
if (!apps) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < apps.length; i++) {
|
||||||
|
let domApp = apps[i].get();
|
||||||
|
if (!domApp || domApp._window === null) {
|
||||||
|
apps.splice(i, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
domApp._proxy = new Proxy(domApp, {
|
||||||
|
get: function(target, prop) {
|
||||||
|
if (!DOMApplicationRegistry.webapps[msg.newId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return DOMApplicationRegistry.webapps[msg.newId][prop];
|
||||||
|
},
|
||||||
|
set: function(target, prop, val) {
|
||||||
|
if (!DOMApplicationRegistry.webapps[msg.newId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DOMApplicationRegistry.webapps[msg.newId][prop] = val;
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Webapps:FireEvent":
|
||||||
|
this._fireEvent(aMessage);
|
||||||
|
break;
|
||||||
|
case "Webapps:UpdateState":
|
||||||
|
this._updateState(msg);
|
||||||
|
break;
|
||||||
|
case "Webapps:CheckForUpdate:Return:KO":
|
||||||
|
let DOMApps = this.DOMApps[msg.manifestURL];
|
||||||
|
if (!DOMApps || !msg.requestID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DOMApps.forEach((DOMApp) => {
|
||||||
|
let domApp = DOMApp.get();
|
||||||
|
if (domApp && msg.requestID) {
|
||||||
|
domApp._fireRequestResult(aMessage, true /* aIsError */);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mozIDOMApplication management
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Every time a DOM app is created, we save a weak reference to it that will
|
||||||
|
// be used to dispatch events and fire request results.
|
||||||
|
addDOMApp: function(aApp, aManifestURL, aId) {
|
||||||
|
let weakRef = Cu.getWeakReference(aApp);
|
||||||
|
|
||||||
|
if (!this.DOMApps[aManifestURL]) {
|
||||||
|
this.DOMApps[aManifestURL] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let apps = this.DOMApps[aManifestURL];
|
||||||
|
|
||||||
|
// Get rid of dead weak references.
|
||||||
|
for (let i = 0; i < apps.length; i++) {
|
||||||
|
let app = apps[i].get();
|
||||||
|
if (!app || app._window === null) {
|
||||||
|
apps.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apps.push(weakRef);
|
||||||
|
|
||||||
|
// Each DOM app contains a proxy object used to build their state. We
|
||||||
|
// return the handler for this proxy object with traps to get and set
|
||||||
|
// app properties kept in the DOMApplicationRegistry app cache.
|
||||||
|
return {
|
||||||
|
get: function(target, prop) {
|
||||||
|
if (!DOMApplicationRegistry.webapps[aId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return DOMApplicationRegistry.webapps[aId][prop];
|
||||||
|
},
|
||||||
|
set: function(target, prop, val) {
|
||||||
|
if (!DOMApplicationRegistry.webapps[aId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DOMApplicationRegistry.webapps[aId][prop] = val;
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_fireEvent: function(aMessage) {
|
||||||
|
let msg = aMessage.data;
|
||||||
|
debug("_fireEvent " + JSON.stringify(msg));
|
||||||
|
if (!this.DOMApps || !msg.manifestURL || !msg.eventType) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let DOMApps = this.DOMApps[msg.manifestURL];
|
||||||
|
if (!DOMApps) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The parent might ask childs to trigger more than one event in one
|
||||||
|
// shot, so in order to avoid needless IPC we allow an array for the
|
||||||
|
// 'eventType' IPC message field.
|
||||||
|
if (!Array.isArray(msg.eventType)) {
|
||||||
|
msg.eventType = [msg.eventType];
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMApps.forEach((DOMApp) => {
|
||||||
|
let domApp = DOMApp.get();
|
||||||
|
if (!domApp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
msg.eventType.forEach((aEventType) => {
|
||||||
|
if ('on' + aEventType in domApp) {
|
||||||
|
domApp._fireEvent(aEventType);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (msg.requestID) {
|
||||||
|
aMessage.data.result = msg.manifestURL;
|
||||||
|
domApp._fireRequestResult(aMessage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateState: function(aMessage) {
|
||||||
|
if (!this.DOMApps || !aMessage.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let app = this.webapps[aMessage.id];
|
||||||
|
if (!app) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aMessage.app) {
|
||||||
|
for (let prop in aMessage.app) {
|
||||||
|
app[prop] = aMessage.app[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("error" in aMessage) {
|
||||||
|
app.downloadError = aMessage.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aMessage.manifest) {
|
||||||
|
app.manifest = aMessage.manifest;
|
||||||
|
// Evict the wrapped manifest cache for all the affected DOM objects.
|
||||||
|
let DOMApps = this.DOMApps[app.manifestURL];
|
||||||
|
if (!DOMApps) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DOMApps.forEach((DOMApp) => {
|
||||||
|
let domApp = DOMApp.get();
|
||||||
|
if (!domApp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WrappedManifestCache.evict(app.manifestURL, domApp.innerWindowID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nsIAppsService API
|
||||||
|
*/
|
||||||
getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
|
getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
|
||||||
debug("getAppByManifestURL " + aManifestURL);
|
debug("getAppByManifestURL " + aManifestURL);
|
||||||
return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
|
return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
|
||||||
|
@ -89,7 +359,7 @@ this.DOMApplicationRegistry = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getAppByLocalId: function getAppByLocalId(aLocalId) {
|
getAppByLocalId: function getAppByLocalId(aLocalId) {
|
||||||
debug("getAppByLocalId " + aLocalId);
|
debug("getAppByLocalId " + aLocalId + " - ready: " + this.ready);
|
||||||
let app = this.localIdIndex[aLocalId];
|
let app = this.localIdIndex[aLocalId];
|
||||||
if (!app) {
|
if (!app) {
|
||||||
debug("Ouch, No app!");
|
debug("Ouch, No app!");
|
||||||
|
|
|
@ -12,6 +12,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
||||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||||
|
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||||
"@mozilla.org/childprocessmessagemanager;1",
|
"@mozilla.org/childprocessmessagemanager;1",
|
||||||
|
@ -278,50 +279,9 @@ WebappsRegistry.prototype = {
|
||||||
* mozIDOMApplication object
|
* mozIDOMApplication object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// A simple cache for the wrapped manifests.
|
|
||||||
let manifestCache = {
|
|
||||||
_cache: { },
|
|
||||||
|
|
||||||
// Gets an entry from the cache, and populates the cache if needed.
|
|
||||||
get: function mcache_get(aManifestURL, aManifest, aWindow, aInnerWindowID) {
|
|
||||||
if (!(aManifestURL in this._cache)) {
|
|
||||||
this._cache[aManifestURL] = { };
|
|
||||||
}
|
|
||||||
|
|
||||||
let winObjs = this._cache[aManifestURL];
|
|
||||||
if (!(aInnerWindowID in winObjs)) {
|
|
||||||
winObjs[aInnerWindowID] = Cu.cloneInto(aManifest, aWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
return winObjs[aInnerWindowID];
|
|
||||||
},
|
|
||||||
|
|
||||||
// Invalidates an entry in the cache.
|
|
||||||
evict: function mcache_evict(aManifestURL, aInnerWindowID) {
|
|
||||||
if (aManifestURL in this._cache) {
|
|
||||||
let winObjs = this._cache[aManifestURL];
|
|
||||||
if (aInnerWindowID in winObjs) {
|
|
||||||
delete winObjs[aInnerWindowID];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(winObjs).length == 0) {
|
|
||||||
delete this._cache[aManifestURL];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
observe: function(aSubject, aTopic, aData) {
|
|
||||||
// Clear the cache on memory pressure.
|
|
||||||
this._cache = { };
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
Services.obs.addObserver(this, "memory-pressure", false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function createApplicationObject(aWindow, aApp) {
|
function createApplicationObject(aWindow, aApp) {
|
||||||
let app = Cc["@mozilla.org/webapps/application;1"].createInstance(Ci.mozIDOMApplication);
|
let app = Cc["@mozilla.org/webapps/application;1"]
|
||||||
|
.createInstance(Ci.mozIDOMApplication);
|
||||||
app.wrappedJSObject.init(aWindow, aApp);
|
app.wrappedJSObject.init(aWindow, aApp);
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
@ -334,27 +294,12 @@ WebappsApplication.prototype = {
|
||||||
__proto__: DOMRequestIpcHelper.prototype,
|
__proto__: DOMRequestIpcHelper.prototype,
|
||||||
|
|
||||||
init: function(aWindow, aApp) {
|
init: function(aWindow, aApp) {
|
||||||
|
let proxyHandler = DOMApplicationRegistry.addDOMApp(this,
|
||||||
|
aApp.manifestURL,
|
||||||
|
aApp.id);
|
||||||
|
this._proxy = new Proxy(this, proxyHandler);
|
||||||
|
|
||||||
this._window = aWindow;
|
this._window = aWindow;
|
||||||
let principal = this._window.document.nodePrincipal;
|
|
||||||
this._appStatus = principal.appStatus;
|
|
||||||
this.origin = aApp.origin;
|
|
||||||
this._manifest = aApp.manifest;
|
|
||||||
this._updateManifest = aApp.updateManifest;
|
|
||||||
this.manifestURL = aApp.manifestURL;
|
|
||||||
this.receipts = aApp.receipts;
|
|
||||||
this.installOrigin = aApp.installOrigin;
|
|
||||||
this.installTime = aApp.installTime;
|
|
||||||
this.installState = aApp.installState || "installed";
|
|
||||||
this.removable = aApp.removable;
|
|
||||||
this.lastUpdateCheck = aApp.lastUpdateCheck ? aApp.lastUpdateCheck
|
|
||||||
: Date.now();
|
|
||||||
this.updateTime = aApp.updateTime ? aApp.updateTime
|
|
||||||
: aApp.installTime;
|
|
||||||
this.progress = NaN;
|
|
||||||
this.downloadAvailable = aApp.downloadAvailable;
|
|
||||||
this.downloading = aApp.downloading;
|
|
||||||
this.readyToApplyDownload = aApp.readyToApplyDownload;
|
|
||||||
this.downloadSize = aApp.downloadSize || 0;
|
|
||||||
|
|
||||||
this._onprogress = null;
|
this._onprogress = null;
|
||||||
this._ondownloadsuccess = null;
|
this._ondownloadsuccess = null;
|
||||||
|
@ -362,40 +307,83 @@ WebappsApplication.prototype = {
|
||||||
this._ondownloadavailable = null;
|
this._ondownloadavailable = null;
|
||||||
this._ondownloadapplied = null;
|
this._ondownloadapplied = null;
|
||||||
|
|
||||||
this._downloadError = null;
|
this.initDOMRequestHelper(aWindow);
|
||||||
|
},
|
||||||
|
|
||||||
this.initDOMRequestHelper(aWindow, [
|
get _appStatus() {
|
||||||
{ name: "Webapps:CheckForUpdate:Return:KO", weakRef: true },
|
return this._proxy.appStatus;
|
||||||
{ name: "Webapps:Connect:Return:OK", weakRef: true },
|
},
|
||||||
{ name: "Webapps:Connect:Return:KO", weakRef: true },
|
|
||||||
{ name: "Webapps:FireEvent", weakRef: true },
|
|
||||||
{ name: "Webapps:GetConnections:Return:OK", weakRef: true },
|
|
||||||
{ name: "Webapps:UpdateState", weakRef: true }
|
|
||||||
]);
|
|
||||||
|
|
||||||
cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
|
get downloadAvailable() {
|
||||||
messages: ["Webapps:FireEvent",
|
return this._proxy.downloadAvailable;
|
||||||
"Webapps:UpdateState"],
|
},
|
||||||
app: {
|
|
||||||
id: this.id,
|
get downloading() {
|
||||||
manifestURL: this.manifestURL,
|
return this._proxy.downloading;
|
||||||
installState: this.installState,
|
},
|
||||||
downloading: this.downloading
|
|
||||||
}
|
get downloadSize() {
|
||||||
});
|
return this._proxy.downloadSize;
|
||||||
|
},
|
||||||
|
|
||||||
|
get installOrigin() {
|
||||||
|
return this._proxy.installOrigin;
|
||||||
|
},
|
||||||
|
|
||||||
|
get installState() {
|
||||||
|
return this._proxy.installState;
|
||||||
|
},
|
||||||
|
|
||||||
|
get installTime() {
|
||||||
|
return this._proxy.installTime;
|
||||||
|
},
|
||||||
|
|
||||||
|
get lastUpdateCheck() {
|
||||||
|
return this._proxy.lastUpdateCheck;
|
||||||
|
},
|
||||||
|
|
||||||
|
get manifestURL() {
|
||||||
|
return this._proxy.manifestURL;
|
||||||
|
},
|
||||||
|
|
||||||
|
get origin() {
|
||||||
|
return this._proxy.origin;
|
||||||
|
},
|
||||||
|
|
||||||
|
get progress() {
|
||||||
|
return this._proxy.progress;
|
||||||
|
},
|
||||||
|
|
||||||
|
get readyToApplyDownload() {
|
||||||
|
return this._proxy.readyToApplyDownload;
|
||||||
|
},
|
||||||
|
|
||||||
|
get receipts() {
|
||||||
|
return this._proxy.receipts;
|
||||||
|
},
|
||||||
|
|
||||||
|
set receipts(aReceipts) {
|
||||||
|
this._proxy.receipts = aReceipts;
|
||||||
|
},
|
||||||
|
|
||||||
|
get removable() {
|
||||||
|
return this._proxy.removable;
|
||||||
|
},
|
||||||
|
|
||||||
|
get updateTime() {
|
||||||
|
return this._proxy.updateTime;
|
||||||
},
|
},
|
||||||
|
|
||||||
get manifest() {
|
get manifest() {
|
||||||
return manifestCache.get(this.manifestURL,
|
return WrappedManifestCache.get(this.manifestURL,
|
||||||
this._manifest,
|
this._proxy.manifest,
|
||||||
this._window,
|
this._window,
|
||||||
this.innerWindowID);
|
this.innerWindowID);
|
||||||
},
|
},
|
||||||
|
|
||||||
get updateManifest() {
|
get updateManifest() {
|
||||||
return this.updateManifest =
|
return this._proxy.updateManifest ?
|
||||||
this._updateManifest ? Cu.cloneInto(this._updateManifest, this._window)
|
Cu.cloneInto(this._proxy.updateManifest, this._window) : null;
|
||||||
: null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
set onprogress(aCallback) {
|
set onprogress(aCallback) {
|
||||||
|
@ -440,10 +428,10 @@ WebappsApplication.prototype = {
|
||||||
|
|
||||||
get downloadError() {
|
get downloadError() {
|
||||||
// Only return DOMError when we have an error.
|
// Only return DOMError when we have an error.
|
||||||
if (!this._downloadError) {
|
if (!this._proxy.downloadError) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new this._window.DOMError(this._downloadError);
|
return new this._window.DOMError(this._proxy.downloadError);
|
||||||
},
|
},
|
||||||
|
|
||||||
download: function() {
|
download: function() {
|
||||||
|
@ -485,12 +473,11 @@ WebappsApplication.prototype = {
|
||||||
BrowserElementPromptService.getBrowserElementChildForWindow(this._window);
|
BrowserElementPromptService.getBrowserElementChildForWindow(this._window);
|
||||||
if (browserChild) {
|
if (browserChild) {
|
||||||
this.addMessageListeners("Webapps:ClearBrowserData:Return");
|
this.addMessageListeners("Webapps:ClearBrowserData:Return");
|
||||||
browserChild.messageManager.sendAsyncMessage(
|
browserChild.messageManager.sendAsyncMessage("Webapps:ClearBrowserData", {
|
||||||
"Webapps:ClearBrowserData",
|
manifestURL: this.manifestURL,
|
||||||
{ manifestURL: this.manifestURL,
|
oid: this._id,
|
||||||
oid: this._id,
|
requestID: this.getRequestId(request)
|
||||||
requestID: this.getRequestId(request) }
|
});
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
Services.DOMRequest.fireErrorAsync(request, "NO_CLEARABLE_BROWSER");
|
Services.DOMRequest.fireErrorAsync(request, "NO_CLEARABLE_BROWSER");
|
||||||
}
|
}
|
||||||
|
@ -498,28 +485,33 @@ WebappsApplication.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
connect: function(aKeyword, aRules) {
|
connect: function(aKeyword, aRules) {
|
||||||
|
this.addMessageListeners(["Webapps:Connect:Return:OK",
|
||||||
|
"Webapps:Connect:Return:KO"]);
|
||||||
return this.createPromise(function (aResolve, aReject) {
|
return this.createPromise(function (aResolve, aReject) {
|
||||||
cpmm.sendAsyncMessage("Webapps:Connect",
|
cpmm.sendAsyncMessage("Webapps:Connect", {
|
||||||
{ keyword: aKeyword,
|
keyword: aKeyword,
|
||||||
rules: aRules,
|
rules: aRules,
|
||||||
manifestURL: this.manifestURL,
|
manifestURL: this.manifestURL,
|
||||||
outerWindowID: this._id,
|
outerWindowID: this._id,
|
||||||
requestID: this.getPromiseResolverId({
|
requestID: this.getPromiseResolverId({
|
||||||
resolve: aResolve,
|
resolve: aResolve,
|
||||||
reject: aReject
|
reject: aReject
|
||||||
})});
|
})
|
||||||
|
});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
getConnections: function() {
|
getConnections: function() {
|
||||||
|
this.addMessageListeners("Webapps:GetConnections:Return:OK");
|
||||||
return this.createPromise(function (aResolve, aReject) {
|
return this.createPromise(function (aResolve, aReject) {
|
||||||
cpmm.sendAsyncMessage("Webapps:GetConnections",
|
cpmm.sendAsyncMessage("Webapps:GetConnections", {
|
||||||
{ manifestURL: this.manifestURL,
|
manifestURL: this.manifestURL,
|
||||||
outerWindowID: this._id,
|
outerWindowID: this._id,
|
||||||
requestID: this.getPromiseResolverId({
|
requestID: this.getPromiseResolverId({
|
||||||
resolve: aResolve,
|
resolve: aResolve,
|
||||||
reject: aReject
|
reject: aReject
|
||||||
})});
|
})
|
||||||
|
});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -568,12 +560,7 @@ WebappsApplication.prototype = {
|
||||||
|
|
||||||
uninit: function() {
|
uninit: function() {
|
||||||
this._onprogress = null;
|
this._onprogress = null;
|
||||||
cpmm.sendAsyncMessage("Webapps:UnregisterForMessages", [
|
WrappedManifestCache.evict(this.manifestURL, this.innerWindowID);
|
||||||
"Webapps:FireEvent",
|
|
||||||
"Webapps:UpdateState"
|
|
||||||
]);
|
|
||||||
|
|
||||||
manifestCache.evict(this.manifestURL, this.innerWindowID);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_fireEvent: function(aName) {
|
_fireEvent: function(aName) {
|
||||||
|
@ -590,22 +577,16 @@ WebappsApplication.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateState: function(aMsg) {
|
_fireRequestResult: function(aMessage, aIsError) {
|
||||||
if (aMsg.app) {
|
let req;
|
||||||
for (let prop in aMsg.app) {
|
let msg = aMessage.data;
|
||||||
this[prop] = aMsg.app[prop];
|
req = this.takeRequest(msg.requestID);
|
||||||
}
|
if (!req) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intentional use of 'in' so we unset the error if this is explicitly null.
|
aIsError ? Services.DOMRequest.fireError(req, msg.error)
|
||||||
if ('error' in aMsg) {
|
: Services.DOMRequest.fireSuccess(req, msg.result);
|
||||||
this._downloadError = aMsg.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aMsg.manifest) {
|
|
||||||
this._manifest = aMsg.manifest;
|
|
||||||
manifestCache.evict(this.manifestURL, this.innerWindowID);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
receiveMessage: function(aMessage) {
|
receiveMessage: function(aMessage) {
|
||||||
|
@ -619,10 +600,7 @@ WebappsApplication.prototype = {
|
||||||
req = this.takeRequest(msg.requestID);
|
req = this.takeRequest(msg.requestID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ondownload* callbacks should be triggered on all app instances
|
if (msg.oid !== this._id || !req) {
|
||||||
if ((msg.oid != this._id || !req) &&
|
|
||||||
aMessage.name !== "Webapps:FireEvent" &&
|
|
||||||
aMessage.name !== "Webapps:UpdateState") {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,51 +615,13 @@ WebappsApplication.prototype = {
|
||||||
"Webapps:Launch:Return:KO"]);
|
"Webapps:Launch:Return:KO"]);
|
||||||
Services.DOMRequest.fireSuccess(req, null);
|
Services.DOMRequest.fireSuccess(req, null);
|
||||||
break;
|
break;
|
||||||
case "Webapps:CheckForUpdate:Return:KO":
|
|
||||||
Services.DOMRequest.fireError(req, msg.error);
|
|
||||||
break;
|
|
||||||
case "Webapps:FireEvent":
|
|
||||||
if (msg.manifestURL != this.manifestURL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The parent might ask childs to trigger more than one event in one
|
|
||||||
// shot, so in order to avoid needless IPC we allow an array for the
|
|
||||||
// 'eventType' IPC message field.
|
|
||||||
if (!Array.isArray(msg.eventType)) {
|
|
||||||
msg.eventType = [msg.eventType];
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.eventType.forEach((aEventType) => {
|
|
||||||
// If we are in a successful state clear any past errors.
|
|
||||||
if (aEventType === 'downloadapplied' ||
|
|
||||||
aEventType === 'downloadsuccess') {
|
|
||||||
this._downloadError = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("_on" + aEventType in this) {
|
|
||||||
this._fireEvent(aEventType);
|
|
||||||
} else {
|
|
||||||
dump("Unsupported event type " + aEventType + "\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (req) {
|
|
||||||
Services.DOMRequest.fireSuccess(req, this.manifestURL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "Webapps:UpdateState":
|
|
||||||
if (msg.manifestURL != this.manifestURL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateState(msg);
|
|
||||||
break;
|
|
||||||
case "Webapps:ClearBrowserData:Return":
|
case "Webapps:ClearBrowserData:Return":
|
||||||
this.removeMessageListeners(aMessage.name);
|
this.removeMessageListeners(aMessage.name);
|
||||||
Services.DOMRequest.fireSuccess(req, null);
|
Services.DOMRequest.fireSuccess(req, null);
|
||||||
break;
|
break;
|
||||||
case "Webapps:Connect:Return:OK":
|
case "Webapps:Connect:Return:OK":
|
||||||
|
this.removeMessageListeners(["Webapps:Connect:Return:OK",
|
||||||
|
"Webapps:Connect:Return:KO"]);
|
||||||
let messagePorts = [];
|
let messagePorts = [];
|
||||||
msg.messagePortIDs.forEach((aPortID) => {
|
msg.messagePortIDs.forEach((aPortID) => {
|
||||||
let port = new this._window.MozInterAppMessagePort(aPortID);
|
let port = new this._window.MozInterAppMessagePort(aPortID);
|
||||||
|
@ -690,9 +630,12 @@ WebappsApplication.prototype = {
|
||||||
req.resolve(messagePorts);
|
req.resolve(messagePorts);
|
||||||
break;
|
break;
|
||||||
case "Webapps:Connect:Return:KO":
|
case "Webapps:Connect:Return:KO":
|
||||||
|
this.removeMessageListeners(["Webapps:Connect:Return:OK",
|
||||||
|
"Webapps:Connect:Return:KO"]);
|
||||||
req.reject("No connections registered");
|
req.reject("No connections registered");
|
||||||
break;
|
break;
|
||||||
case "Webapps:GetConnections:Return:OK":
|
case "Webapps:GetConnections:Return:OK":
|
||||||
|
this.removeMessageListeners(aMessage.name);
|
||||||
let connections = [];
|
let connections = [];
|
||||||
msg.connections.forEach((aConnection) => {
|
msg.connections.forEach((aConnection) => {
|
||||||
let connection =
|
let connection =
|
||||||
|
@ -805,7 +748,6 @@ WebappsApplicationMgmt.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
uninstall: function(aApp) {
|
uninstall: function(aApp) {
|
||||||
dump("-- webapps.js uninstall " + aApp.manifestURL + "\n");
|
|
||||||
let request = this.createRequest();
|
let request = this.createRequest();
|
||||||
cpmm.sendAsyncMessage("Webapps:Uninstall", { origin: aApp.origin,
|
cpmm.sendAsyncMessage("Webapps:Uninstall", { origin: aApp.origin,
|
||||||
manifestURL: aApp.manifestURL,
|
manifestURL: aApp.manifestURL,
|
||||||
|
@ -874,12 +816,8 @@ WebappsApplicationMgmt.prototype = {
|
||||||
break;
|
break;
|
||||||
case "Webapps:Uninstall:Broadcast:Return:OK":
|
case "Webapps:Uninstall:Broadcast:Return:OK":
|
||||||
if (this._onuninstall) {
|
if (this._onuninstall) {
|
||||||
let detail = {
|
|
||||||
manifestURL: msg.manifestURL,
|
|
||||||
origin: msg.origin
|
|
||||||
};
|
|
||||||
let event = new this._window.MozApplicationEvent("applicationuninstall",
|
let event = new this._window.MozApplicationEvent("applicationuninstall",
|
||||||
{ application : createApplicationObject(this._window, detail) });
|
{ application : createApplicationObject(this._window, msg) });
|
||||||
this._onuninstall.handleEvent(event);
|
this._onuninstall.handleEvent(event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -908,7 +846,5 @@ WebappsApplicationMgmt.prototype = {
|
||||||
classDescription: "Webapps Application Mgmt"})
|
classDescription: "Webapps Application Mgmt"})
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestCache.init();
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry,
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry,
|
||||||
WebappsApplication]);
|
WebappsApplication]);
|
||||||
|
|
|
@ -179,6 +179,7 @@ this.DOMApplicationRegistry = {
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
cpmm.addMessageListener("Activities:Register:OK", this);
|
cpmm.addMessageListener("Activities:Register:OK", this);
|
||||||
|
cpmm.addMessageListener("Activities:Register:KO", this);
|
||||||
|
|
||||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||||
Services.obs.addObserver(this, "memory-pressure", false);
|
Services.obs.addObserver(this, "memory-pressure", false);
|
||||||
|
@ -275,9 +276,15 @@ this.DOMApplicationRegistry = {
|
||||||
return this._registryStarted.promise;
|
return this._registryStarted.promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// The registry will be safe to clone when this promise is resolved.
|
||||||
|
_safeToClone: Promise.defer(),
|
||||||
|
|
||||||
// Notify we are done with registering apps and save a copy of the registry.
|
// Notify we are done with registering apps and save a copy of the registry.
|
||||||
_registryReady: Promise.defer(),
|
_registryReady: Promise.defer(),
|
||||||
notifyAppsRegistryReady: function notifyAppsRegistryReady() {
|
notifyAppsRegistryReady: function notifyAppsRegistryReady() {
|
||||||
|
// Usually this promise will be resolved earlier, but just in case,
|
||||||
|
// resolve it here also.
|
||||||
|
this._safeToClone.resolve();
|
||||||
this._registryReady.resolve();
|
this._registryReady.resolve();
|
||||||
Services.obs.notifyObservers(this, "webapps-registry-ready", null);
|
Services.obs.notifyObservers(this, "webapps-registry-ready", null);
|
||||||
this._saveApps();
|
this._saveApps();
|
||||||
|
@ -287,6 +294,10 @@ this.DOMApplicationRegistry = {
|
||||||
return this._registryReady.promise;
|
return this._registryReady.promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get safeToClone() {
|
||||||
|
return this._safeToClone.promise;
|
||||||
|
},
|
||||||
|
|
||||||
// Ensure that the .to property in redirects is a relative URL.
|
// Ensure that the .to property in redirects is a relative URL.
|
||||||
sanitizeRedirects: function sanitizeRedirects(aSource) {
|
sanitizeRedirects: function sanitizeRedirects(aSource) {
|
||||||
if (!aSource) {
|
if (!aSource) {
|
||||||
|
@ -962,6 +973,7 @@ this.DOMApplicationRegistry = {
|
||||||
this._registerInterAppConnections(manifest, app);
|
this._registerInterAppConnections(manifest, app);
|
||||||
appsToRegister.push({ manifest: manifest, app: app });
|
appsToRegister.push({ manifest: manifest, app: app });
|
||||||
});
|
});
|
||||||
|
this._safeToClone.resolve();
|
||||||
this._registerActivitiesForApps(appsToRegister, aRunUpdate);
|
this._registerActivitiesForApps(appsToRegister, aRunUpdate);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1089,88 +1101,114 @@ this.DOMApplicationRegistry = {
|
||||||
let mm = aMessage.target;
|
let mm = aMessage.target;
|
||||||
msg.mm = mm;
|
msg.mm = mm;
|
||||||
|
|
||||||
|
let processedImmediately = true;
|
||||||
|
|
||||||
|
// There are two kind of messages: the messages that only make sense once the
|
||||||
|
// registry is ready, and those that can (or have to) be treated as soon as
|
||||||
|
// they're received.
|
||||||
switch (aMessage.name) {
|
switch (aMessage.name) {
|
||||||
case "Webapps:Install": {
|
case "Activities:Register:KO":
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
dump("Activities didn't register correctly!");
|
||||||
Services.obs.notifyObservers(mm, "webapps-runtime-install", JSON.stringify(msg));
|
case "Activities:Register:OK":
|
||||||
#else
|
// Activities:Register:OK is special because it's one way the registryReady
|
||||||
this.doInstall(msg, mm);
|
// promise can be resolved.
|
||||||
#endif
|
// XXX: What to do when the activities registration failed? At this point
|
||||||
|
// just act as if nothing happened.
|
||||||
|
this.notifyAppsRegistryReady();
|
||||||
break;
|
break;
|
||||||
}
|
case "Webapps:GetList":
|
||||||
case "Webapps:GetSelf":
|
// GetList is special because it's synchronous. So far so well, it's the
|
||||||
this.getSelf(msg, mm);
|
// only synchronous message, if we get more at some point they should get
|
||||||
|
// this treatment also.
|
||||||
|
return this.doGetList();
|
||||||
|
case "child-process-shutdown":
|
||||||
|
this.removeMessageListener(["Webapps:Internal:AllMessages"], mm);
|
||||||
break;
|
break;
|
||||||
case "Webapps:Uninstall":
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
|
||||||
Services.obs.notifyObservers(mm, "webapps-runtime-uninstall", JSON.stringify(msg));
|
|
||||||
#else
|
|
||||||
this.doUninstall(msg, mm);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case "Webapps:Launch":
|
|
||||||
this.doLaunch(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:CheckInstalled":
|
|
||||||
this.checkInstalled(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:GetInstalled":
|
|
||||||
this.getInstalled(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:GetNotInstalled":
|
|
||||||
this.getNotInstalled(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:GetAll":
|
|
||||||
this.doGetAll(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:InstallPackage": {
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
|
||||||
Services.obs.notifyObservers(mm, "webapps-runtime-install-package", JSON.stringify(msg));
|
|
||||||
#else
|
|
||||||
this.doInstallPackage(msg, mm);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "Webapps:RegisterForMessages":
|
case "Webapps:RegisterForMessages":
|
||||||
this.addMessageListener(msg.messages, msg.app, mm);
|
this.addMessageListener(msg.messages, msg.app, mm);
|
||||||
break;
|
break;
|
||||||
case "Webapps:UnregisterForMessages":
|
case "Webapps:UnregisterForMessages":
|
||||||
this.removeMessageListener(msg, mm);
|
this.removeMessageListener(msg, mm);
|
||||||
break;
|
break;
|
||||||
case "child-process-shutdown":
|
default:
|
||||||
this.removeMessageListener(["Webapps:Internal:AllMessages"], mm);
|
processedImmediately = false;
|
||||||
break;
|
|
||||||
case "Webapps:GetList":
|
|
||||||
this.addMessageListener(["Webapps:AddApp", "Webapps:RemoveApp"], null, mm);
|
|
||||||
return this.webapps;
|
|
||||||
case "Webapps:Download":
|
|
||||||
this.startDownload(msg.manifestURL);
|
|
||||||
break;
|
|
||||||
case "Webapps:CancelDownload":
|
|
||||||
this.cancelDownload(msg.manifestURL);
|
|
||||||
break;
|
|
||||||
case "Webapps:CheckForUpdate":
|
|
||||||
this.checkForUpdate(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:ApplyDownload":
|
|
||||||
this.applyDownload(msg.manifestURL);
|
|
||||||
break;
|
|
||||||
case "Activities:Register:OK":
|
|
||||||
this.notifyAppsRegistryReady();
|
|
||||||
break;
|
|
||||||
case "Webapps:Install:Return:Ack":
|
|
||||||
this.onInstallSuccessAck(msg.manifestURL);
|
|
||||||
break;
|
|
||||||
case "Webapps:AddReceipt":
|
|
||||||
this.addReceipt(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:RemoveReceipt":
|
|
||||||
this.removeReceipt(msg, mm);
|
|
||||||
break;
|
|
||||||
case "Webapps:ReplaceReceipt":
|
|
||||||
this.replaceReceipt(msg, mm);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (processedImmediately) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all the rest (asynchronous), we wait till the registry is ready
|
||||||
|
// before processing the message.
|
||||||
|
this.registryReady.then( () => {
|
||||||
|
switch (aMessage.name) {
|
||||||
|
case "Webapps:Install": {
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
Services.obs.notifyObservers(mm, "webapps-runtime-install", JSON.stringify(msg));
|
||||||
|
#else
|
||||||
|
this.doInstall(msg, mm);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Webapps:GetSelf":
|
||||||
|
this.getSelf(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:Uninstall":
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
Services.obs.notifyObservers(mm, "webapps-runtime-uninstall", JSON.stringify(msg));
|
||||||
|
#else
|
||||||
|
this.doUninstall(msg, mm);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case "Webapps:Launch":
|
||||||
|
this.doLaunch(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:CheckInstalled":
|
||||||
|
this.checkInstalled(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:GetInstalled":
|
||||||
|
this.getInstalled(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:GetNotInstalled":
|
||||||
|
this.getNotInstalled(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:GetAll":
|
||||||
|
this.doGetAll(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:InstallPackage": {
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
Services.obs.notifyObservers(mm, "webapps-runtime-install-package", JSON.stringify(msg));
|
||||||
|
#else
|
||||||
|
this.doInstallPackage(msg, mm);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Webapps:Download":
|
||||||
|
this.startDownload(msg.manifestURL);
|
||||||
|
break;
|
||||||
|
case "Webapps:CancelDownload":
|
||||||
|
this.cancelDownload(msg.manifestURL);
|
||||||
|
break;
|
||||||
|
case "Webapps:CheckForUpdate":
|
||||||
|
this.checkForUpdate(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:ApplyDownload":
|
||||||
|
this.applyDownload(msg.manifestURL);
|
||||||
|
break;
|
||||||
|
case "Webapps:Install:Return:Ack":
|
||||||
|
this.onInstallSuccessAck(msg.manifestURL);
|
||||||
|
break;
|
||||||
|
case "Webapps:AddReceipt":
|
||||||
|
this.addReceipt(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:RemoveReceipt":
|
||||||
|
this.removeReceipt(msg, mm);
|
||||||
|
break;
|
||||||
|
case "Webapps:ReplaceReceipt":
|
||||||
|
this.replaceReceipt(msg, mm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getAppInfo: function getAppInfo(aAppId) {
|
getAppInfo: function getAppInfo(aAppId) {
|
||||||
|
@ -1245,6 +1283,38 @@ this.DOMApplicationRegistry = {
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full list of apps and manifests.
|
||||||
|
*/
|
||||||
|
doGetList: function() {
|
||||||
|
let tmp = [];
|
||||||
|
|
||||||
|
let res = {};
|
||||||
|
let done = false;
|
||||||
|
|
||||||
|
// We allow cloning the registry when the local processing has been done.
|
||||||
|
this.safeToClone.then( () => {
|
||||||
|
for (let id in this.webapps) {
|
||||||
|
tmp.push({ id: id });
|
||||||
|
}
|
||||||
|
this._readManifests(tmp).then(
|
||||||
|
function(manifests) {
|
||||||
|
manifests.forEach((item) => {
|
||||||
|
res[item.id] = item.manifest;
|
||||||
|
});
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
let thread = Services.tm.currentThread;
|
||||||
|
while (!done) {
|
||||||
|
thread.processNextEvent(/* mayWait */ true);
|
||||||
|
}
|
||||||
|
return { webapps: this.webapps, manifests: res };
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
doLaunch: function (aData, aMm) {
|
doLaunch: function (aData, aMm) {
|
||||||
this.launch(
|
this.launch(
|
||||||
aData.manifestURL,
|
aData.manifestURL,
|
||||||
|
@ -1330,7 +1400,7 @@ this.DOMApplicationRegistry = {
|
||||||
downloading: false
|
downloading: false
|
||||||
},
|
},
|
||||||
error: error,
|
error: error,
|
||||||
manifestURL: app.manifestURL,
|
id: app.id
|
||||||
})
|
})
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloaderror",
|
eventType: "downloaderror",
|
||||||
|
@ -1361,7 +1431,7 @@ this.DOMApplicationRegistry = {
|
||||||
if (!app.downloadAvailable) {
|
if (!app.downloadAvailable) {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
error: "NO_DOWNLOAD_AVAILABLE",
|
error: "NO_DOWNLOAD_AVAILABLE",
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloaderror",
|
eventType: "downloaderror",
|
||||||
|
@ -1409,7 +1479,7 @@ this.DOMApplicationRegistry = {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifest: jsonManifest,
|
manifest: jsonManifest,
|
||||||
manifestURL: aManifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloadsuccess",
|
eventType: "downloadsuccess",
|
||||||
|
@ -1463,7 +1533,7 @@ this.DOMApplicationRegistry = {
|
||||||
|
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifestURL: aManifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloadsuccess",
|
eventType: "downloadsuccess",
|
||||||
|
@ -1565,7 +1635,7 @@ this.DOMApplicationRegistry = {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifest: newManifest,
|
manifest: newManifest,
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloadapplied",
|
eventType: "downloadapplied",
|
||||||
|
@ -1604,7 +1674,7 @@ this.DOMApplicationRegistry = {
|
||||||
installState: aApp.installState,
|
installState: aApp.installState,
|
||||||
progress: 0
|
progress: 0
|
||||||
},
|
},
|
||||||
manifestURL: aApp.manifestURL
|
id: aApp.id
|
||||||
});
|
});
|
||||||
let cacheUpdate = updateSvc.scheduleAppUpdate(
|
let cacheUpdate = updateSvc.scheduleAppUpdate(
|
||||||
appcacheURI, docURI, aApp.localId, false, aProfileDir);
|
appcacheURI, docURI, aApp.localId, false, aProfileDir);
|
||||||
|
@ -1654,6 +1724,7 @@ this.DOMApplicationRegistry = {
|
||||||
debug("checkForUpdate for " + aData.manifestURL);
|
debug("checkForUpdate for " + aData.manifestURL);
|
||||||
|
|
||||||
function sendError(aError) {
|
function sendError(aError) {
|
||||||
|
debug("checkForUpdate error " + aError);
|
||||||
aData.error = aError;
|
aData.error = aError;
|
||||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
||||||
}
|
}
|
||||||
|
@ -1683,8 +1754,7 @@ this.DOMApplicationRegistry = {
|
||||||
// then we can't have an update.
|
// then we can't have an update.
|
||||||
if (app.origin.startsWith("app://") &&
|
if (app.origin.startsWith("app://") &&
|
||||||
app.manifestURL.startsWith("app://")) {
|
app.manifestURL.startsWith("app://")) {
|
||||||
aData.error = "NOT_UPDATABLE";
|
sendError("NOT_UPDATABLE");
|
||||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1701,8 +1771,7 @@ this.DOMApplicationRegistry = {
|
||||||
if (onlyCheckAppCache) {
|
if (onlyCheckAppCache) {
|
||||||
// Bail out for packaged apps.
|
// Bail out for packaged apps.
|
||||||
if (app.origin.startsWith("app://")) {
|
if (app.origin.startsWith("app://")) {
|
||||||
aData.error = "NOT_UPDATABLE";
|
sendError("NOT_UPDATABLE");
|
||||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1710,8 +1779,7 @@ this.DOMApplicationRegistry = {
|
||||||
this._readManifests([{ id: id }]).then((aResult) => {
|
this._readManifests([{ id: id }]).then((aResult) => {
|
||||||
let manifest = aResult[0].manifest;
|
let manifest = aResult[0].manifest;
|
||||||
if (!manifest.appcache_path) {
|
if (!manifest.appcache_path) {
|
||||||
aData.error = "NOT_UPDATABLE";
|
sendError("NOT_UPDATABLE");
|
||||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1727,7 +1795,7 @@ this.DOMApplicationRegistry = {
|
||||||
this._saveApps().then(() => {
|
this._saveApps().then(() => {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloadavailable",
|
eventType: "downloadavailable",
|
||||||
|
@ -1736,8 +1804,7 @@ this.DOMApplicationRegistry = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
aData.error = "NOT_UPDATABLE";
|
sendError("NOT_UPDATABLE");
|
||||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1797,7 +1864,7 @@ this.DOMApplicationRegistry = {
|
||||||
: "downloadapplied";
|
: "downloadapplied";
|
||||||
aMm.sendAsyncMessage("Webapps:UpdateState", {
|
aMm.sendAsyncMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
aMm.sendAsyncMessage("Webapps:FireEvent", {
|
aMm.sendAsyncMessage("Webapps:FireEvent", {
|
||||||
eventType: eventType,
|
eventType: eventType,
|
||||||
|
@ -1824,7 +1891,7 @@ this.DOMApplicationRegistry = {
|
||||||
: "downloadapplied";
|
: "downloadapplied";
|
||||||
aMm.sendAsyncMessage("Webapps:UpdateState", {
|
aMm.sendAsyncMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
aMm.sendAsyncMessage("Webapps:FireEvent", {
|
aMm.sendAsyncMessage("Webapps:FireEvent", {
|
||||||
eventType: eventType,
|
eventType: eventType,
|
||||||
|
@ -1933,7 +2000,7 @@ this.DOMApplicationRegistry = {
|
||||||
|
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: aApp,
|
app: aApp,
|
||||||
manifestURL: aApp.manifestURL
|
id: aApp.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloadavailable",
|
eventType: "downloadavailable",
|
||||||
|
@ -1999,7 +2066,7 @@ this.DOMApplicationRegistry = {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: aApp,
|
app: aApp,
|
||||||
manifest: aApp.manifest,
|
manifest: aApp.manifest,
|
||||||
manifestURL: aApp.manifestURL
|
id: aApp.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloadapplied",
|
eventType: "downloadapplied",
|
||||||
|
@ -2033,7 +2100,7 @@ this.DOMApplicationRegistry = {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: aApp,
|
app: aApp,
|
||||||
manifest: aApp.manifest,
|
manifest: aApp.manifest,
|
||||||
manifestURL: aApp.manifestURL
|
id: aApp.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: eventType,
|
eventType: eventType,
|
||||||
|
@ -2464,7 +2531,8 @@ this.DOMApplicationRegistry = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this._saveApps().then(() => {
|
this._saveApps().then(() => {
|
||||||
this.broadcastMessage("Webapps:AddApp", { id: app.id, app: app });
|
this.broadcastMessage("Webapps:AddApp",
|
||||||
|
{ id: app.id, app: app, manifest: aManifest });
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -2564,6 +2632,8 @@ this.DOMApplicationRegistry = {
|
||||||
// saved in the registry.
|
// saved in the registry.
|
||||||
yield this._saveApps();
|
yield this._saveApps();
|
||||||
|
|
||||||
|
aData.isPackage ? appObject.updateManifest = jsonManifest :
|
||||||
|
appObject.manifest = jsonManifest;
|
||||||
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
|
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
|
||||||
|
|
||||||
if (!aData.isPackage) {
|
if (!aData.isPackage) {
|
||||||
|
@ -2646,7 +2716,8 @@ this.DOMApplicationRegistry = {
|
||||||
delete this._manifestCache[aId];
|
delete this._manifestCache[aId];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.broadcastMessage("Webapps:AddApp", { id: aId, app: aNewApp });
|
this.broadcastMessage("Webapps:AddApp",
|
||||||
|
{ id: aId, app: aNewApp, manifest: aManifest });
|
||||||
Services.obs.notifyObservers(null, "webapps-installed",
|
Services.obs.notifyObservers(null, "webapps-installed",
|
||||||
JSON.stringify({ manifestURL: aNewApp.manifestURL }));
|
JSON.stringify({ manifestURL: aNewApp.manifestURL }));
|
||||||
|
|
||||||
|
@ -2806,7 +2877,7 @@ this.DOMApplicationRegistry = {
|
||||||
// Clear any previous download errors.
|
// Clear any previous download errors.
|
||||||
error: null,
|
error: null,
|
||||||
app: aOldApp,
|
app: aOldApp,
|
||||||
manifestURL: aNewApp.manifestURL
|
id: aId
|
||||||
});
|
});
|
||||||
|
|
||||||
let zipFile = yield this._getPackage(requestChannel, aId, aOldApp, aNewApp);
|
let zipFile = yield this._getPackage(requestChannel, aId, aOldApp, aNewApp);
|
||||||
|
@ -2821,7 +2892,7 @@ this.DOMApplicationRegistry = {
|
||||||
// We send an "applied" event right away so code awaiting that event
|
// We send an "applied" event right away so code awaiting that event
|
||||||
// can proceed to access the app. We also throw an error to alert
|
// can proceed to access the app. We also throw an error to alert
|
||||||
// the caller that the package wasn't downloaded.
|
// the caller that the package wasn't downloaded.
|
||||||
this._sendAppliedEvent(aNewApp, aOldApp, aId);
|
this._sendAppliedEvent(aOldApp);
|
||||||
throw new Error("PACKAGE_UNCHANGED");
|
throw new Error("PACKAGE_UNCHANGED");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2957,7 +3028,7 @@ this.DOMApplicationRegistry = {
|
||||||
app: {
|
app: {
|
||||||
progress: aProgress
|
progress: aProgress
|
||||||
},
|
},
|
||||||
manifestURL: aNewApp.manifestURL
|
id: aNewApp.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "progress",
|
eventType: "progress",
|
||||||
|
@ -3074,27 +3145,24 @@ this.DOMApplicationRegistry = {
|
||||||
* something similar after updating the app, and we could refactor both cases
|
* something similar after updating the app, and we could refactor both cases
|
||||||
* to use the same code to send the "applied" event.
|
* to use the same code to send the "applied" event.
|
||||||
*
|
*
|
||||||
* @param aNewApp {Object} the new app data
|
* @param aApp {Object} app data
|
||||||
* @param aOldApp {Object} the currently stored app data
|
|
||||||
* @param aId {String} the unique id of the app
|
|
||||||
*/
|
*/
|
||||||
_sendAppliedEvent: function(aNewApp, aOldApp, aId) {
|
_sendAppliedEvent: function(aApp) {
|
||||||
aOldApp.downloading = false;
|
aApp.downloading = false;
|
||||||
aOldApp.downloadAvailable = false;
|
aApp.downloadAvailable = false;
|
||||||
aOldApp.downloadSize = 0;
|
aApp.downloadSize = 0;
|
||||||
aOldApp.installState = "installed";
|
aApp.installState = "installed";
|
||||||
aOldApp.readyToApplyDownload = false;
|
aApp.readyToApplyDownload = false;
|
||||||
if (aOldApp.staged && aOldApp.staged.manifestHash) {
|
if (aApp.staged && aApp.staged.manifestHash) {
|
||||||
// If we're here then the manifest has changed but the package
|
// If we're here then the manifest has changed but the package
|
||||||
// hasn't. Let's clear this, so we don't keep offering
|
// hasn't. Let's clear this, so we don't keep offering
|
||||||
// a bogus update to the user
|
// a bogus update to the user
|
||||||
aOldApp.manifestHash = aOldApp.staged.manifestHash;
|
aApp.manifestHash = aApp.staged.manifestHash;
|
||||||
aOldApp.etag = aOldApp.staged.etag || aOldApp.etag;
|
aApp.etag = aApp.staged.etag || aApp.etag;
|
||||||
aOldApp.staged = {};
|
aApp.staged = {};
|
||||||
|
// Move the staged update manifest to a non staged one.
|
||||||
// Move the staged update manifest to a non staged one.
|
|
||||||
try {
|
try {
|
||||||
let staged = this._getAppDir(aId);
|
let staged = this._getAppDir(aApp.id);
|
||||||
staged.append("staged-update.webapp");
|
staged.append("staged-update.webapp");
|
||||||
staged.moveTo(staged.parent, "update.webapp");
|
staged.moveTo(staged.parent, "update.webapp");
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
@ -3105,15 +3173,15 @@ this.DOMApplicationRegistry = {
|
||||||
// Save the updated registry, and cleanup the tmp directory.
|
// Save the updated registry, and cleanup the tmp directory.
|
||||||
this._saveApps().then(() => {
|
this._saveApps().then(() => {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: aOldApp,
|
app: aApp,
|
||||||
manifestURL: aNewApp.manifestURL
|
id: aApp.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
manifestURL: aNewApp.manifestURL,
|
manifestURL: aApp.manifestURL,
|
||||||
eventType: ["downloadsuccess", "downloadapplied"]
|
eventType: ["downloadsuccess", "downloadapplied"]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
let file = FileUtils.getFile("TmpD", ["webapps", aId], false);
|
let file = FileUtils.getFile("TmpD", ["webapps", aApp.id], false);
|
||||||
if (file && file.exists()) {
|
if (file && file.exists()) {
|
||||||
file.remove(true);
|
file.remove(true);
|
||||||
}
|
}
|
||||||
|
@ -3432,9 +3500,10 @@ this.DOMApplicationRegistry = {
|
||||||
dir.moveTo(parent, newId);
|
dir.moveTo(parent, newId);
|
||||||
});
|
});
|
||||||
// Signals that we need to swap the old id with the new app.
|
// Signals that we need to swap the old id with the new app.
|
||||||
this.broadcastMessage("Webapps:RemoveApp", { id: oldId });
|
this.broadcastMessage("Webapps:UpdateApp", { oldId: oldId,
|
||||||
this.broadcastMessage("Webapps:AddApp", { id: newId,
|
newId: newId,
|
||||||
app: aOldApp });
|
app: aOldApp });
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3537,7 +3606,7 @@ this.DOMApplicationRegistry = {
|
||||||
this.broadcastMessage("Webapps:UpdateState", {
|
this.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: aOldApp,
|
app: aOldApp,
|
||||||
error: aError,
|
error: aError,
|
||||||
manifestURL: aNewApp.manifestURL
|
id: aNewApp.id
|
||||||
});
|
});
|
||||||
this.broadcastMessage("Webapps:FireEvent", {
|
this.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloaderror",
|
eventType: "downloaderror",
|
||||||
|
@ -3717,9 +3786,13 @@ this.DOMApplicationRegistry = {
|
||||||
},
|
},
|
||||||
|
|
||||||
doGetAll: function(aData, aMm) {
|
doGetAll: function(aData, aMm) {
|
||||||
this.getAll(function (apps) {
|
// We can't do this until the registry is ready.
|
||||||
aData.apps = apps;
|
debug("doGetAll");
|
||||||
aMm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
|
this.registryReady.then(() => {
|
||||||
|
this.getAll(function (apps) {
|
||||||
|
aData.apps = apps;
|
||||||
|
aMm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -4087,7 +4160,7 @@ AppcacheObserver.prototype = {
|
||||||
let app = this.app;
|
let app = this.app;
|
||||||
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "progress",
|
eventType: "progress",
|
||||||
|
@ -4119,7 +4192,7 @@ AppcacheObserver.prototype = {
|
||||||
app.downloadAvailable = false;
|
app.downloadAvailable = false;
|
||||||
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: ["downloadsuccess", "downloadapplied"],
|
eventType: ["downloadsuccess", "downloadapplied"],
|
||||||
|
@ -4142,7 +4215,7 @@ AppcacheObserver.prototype = {
|
||||||
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: app,
|
app: app,
|
||||||
error: aError,
|
error: aError,
|
||||||
manifestURL: app.manifestURL
|
id: app.id
|
||||||
});
|
});
|
||||||
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: "downloaderror",
|
eventType: "downloaderror",
|
||||||
|
|
|
@ -102,6 +102,7 @@ var PackagedTestHelper = (function PackagedTestHelper() {
|
||||||
var aApp = evt.application;
|
var aApp = evt.application;
|
||||||
aApp.ondownloaderror = function(evt) {
|
aApp.ondownloaderror = function(evt) {
|
||||||
var error = aApp.downloadError.name;
|
var error = aApp.downloadError.name;
|
||||||
|
ok(true, "Got downloaderror " + error);
|
||||||
if (error == aExpectedError) {
|
if (error == aExpectedError) {
|
||||||
ok(true, "Got expected " + aExpectedError);
|
ok(true, "Got expected " + aExpectedError);
|
||||||
var expected = {
|
var expected = {
|
||||||
|
|
|
@ -79,15 +79,15 @@ function updateApp(aExpectedReady, aPreviousVersion, aNextVersion) {
|
||||||
checkLastAppState.bind(PackagedTestHelper, miniManifestURL, false, false,
|
checkLastAppState.bind(PackagedTestHelper, miniManifestURL, false, false,
|
||||||
aNextVersion, PackagedTestHelper.next);
|
aNextVersion, PackagedTestHelper.next);
|
||||||
|
|
||||||
var ondownloadsuccesshandler =
|
var ondownloadsuccesshandler =
|
||||||
checkLastAppState.bind(undefined, miniManifestURL,
|
checkLastAppState.bind(undefined, miniManifestURL,
|
||||||
aExpectedReady, false, aPreviousVersion,
|
aExpectedReady, false, aPreviousVersion,
|
||||||
function() {
|
function() {
|
||||||
navigator.mozApps.mgmt.applyDownload(lApp);
|
navigator.mozApps.mgmt.applyDownload(lApp);
|
||||||
});
|
});
|
||||||
|
|
||||||
checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler, null,
|
checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler,
|
||||||
true);
|
null, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ var steps = [
|
||||||
"&appName=arandomname" +
|
"&appName=arandomname" +
|
||||||
"&appToFail1";
|
"&appToFail1";
|
||||||
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
|
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
|
||||||
"MANIFEST_MISMATCH", 2, false, true,
|
"MANIFEST_MISMATCH", 1, false, true,
|
||||||
"arandomname",
|
"arandomname",
|
||||||
function () {
|
function () {
|
||||||
checkForUpdate(false, null, null, null, false,
|
checkForUpdate(false, null, null, null, false,
|
||||||
|
|
|
@ -243,4 +243,4 @@ addLoadEvent(go);
|
||||||
</script>
|
</script>
|
||||||
</pre>
|
</pre>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -586,14 +586,18 @@ AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID)
|
||||||
kMozAudioChannelAttributeTable[index].value > higher &&
|
kMozAudioChannelAttributeTable[index].value > higher &&
|
||||||
kMozAudioChannelAttributeTable[index].value > (int16_t)AudioChannel::Normal;
|
kMozAudioChannelAttributeTable[index].value > (int16_t)AudioChannel::Normal;
|
||||||
--index) {
|
--index) {
|
||||||
if (kMozAudioChannelAttributeTable[index].value == (int16_t)AudioChannel::Content &&
|
|
||||||
mPlayableHiddenContentChildID != CONTENT_PROCESS_ID_UNKNOWN) {
|
|
||||||
higher = kMozAudioChannelAttributeTable[index].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each channel type will be split to fg and bg for recording the state,
|
// Each channel type will be split to fg and bg for recording the state,
|
||||||
// so here need to do a translation.
|
// so here need to do a translation.
|
||||||
if (!mChannelCounters[index * 2 + 1].IsEmpty()) {
|
if (mChannelCounters[index * 2 + 1].IsEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kMozAudioChannelAttributeTable[index].value == (int16_t)AudioChannel::Content) {
|
||||||
|
if (mPlayableHiddenContentChildID != CONTENT_PROCESS_ID_UNKNOWN) {
|
||||||
|
higher = kMozAudioChannelAttributeTable[index].value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
higher = kMozAudioChannelAttributeTable[index].value;
|
higher = kMozAudioChannelAttributeTable[index].value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,20 +166,24 @@ DOMInterfaces = {
|
||||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothAdapter',
|
'nativeType': 'mozilla::dom::bluetooth::BluetoothAdapter',
|
||||||
},
|
},
|
||||||
|
|
||||||
'BluetoothDevice': {
|
'BluetoothClassOfDevice': {
|
||||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothDevice',
|
'nativeType': 'mozilla::dom::bluetooth::BluetoothClassOfDevice',
|
||||||
},
|
},
|
||||||
|
|
||||||
'BluetoothManager': {
|
'BluetoothDevice': {
|
||||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothManager',
|
'nativeType': 'mozilla::dom::bluetooth::BluetoothDevice',
|
||||||
},
|
},
|
||||||
|
|
||||||
'BluetoothDiscoveryHandle': {
|
'BluetoothDiscoveryHandle': {
|
||||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothDiscoveryHandle',
|
'nativeType': 'mozilla::dom::bluetooth::BluetoothDiscoveryHandle',
|
||||||
},
|
},
|
||||||
|
|
||||||
'BluetoothClassOfDevice': {
|
'BluetoothManager': {
|
||||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothClassOfDevice',
|
'nativeType': 'mozilla::dom::bluetooth::BluetoothManager',
|
||||||
|
},
|
||||||
|
|
||||||
|
'BluetoothPairingHandle': {
|
||||||
|
'nativeType': 'mozilla::dom::bluetooth::BluetoothPairingHandle',
|
||||||
},
|
},
|
||||||
|
|
||||||
'CameraCapabilities': {
|
'CameraCapabilities': {
|
||||||
|
|
|
@ -148,7 +148,7 @@ BluetoothHfpManager::Init()
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
BluetoothHfpManager::InitHfpInterface()
|
BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
@ -157,11 +157,15 @@ BluetoothHfpManager::InitHfpInterface()
|
||||||
* Implement InitHfpInterface() for applications that want to create SCO
|
* Implement InitHfpInterface() for applications that want to create SCO
|
||||||
* link without a HFP connection (e.g., VoIP).
|
* link without a HFP connection (e.g., VoIP).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
BluetoothHfpManager::DeinitHfpInterface()
|
BluetoothHfpManager::DeinitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
@ -170,6 +174,10 @@ BluetoothHfpManager::DeinitHfpInterface()
|
||||||
* Implement DeinitHfpInterface() for applications that want to create SCO
|
* Implement DeinitHfpInterface() for applications that want to create SCO
|
||||||
* link without a HFP connection (e.g., VoIP).
|
* link without a HFP connection (e.g., VoIP).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Deinit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -30,8 +30,8 @@ public:
|
||||||
|
|
||||||
static BluetoothHfpManager* Get();
|
static BluetoothHfpManager* Get();
|
||||||
virtual ~BluetoothHfpManager() { }
|
virtual ~BluetoothHfpManager() { }
|
||||||
static void InitHfpInterface();
|
static void InitHfpInterface(BluetoothProfileResultHandler* aRes);
|
||||||
static void DeinitHfpInterface();
|
static void DeinitHfpInterface(BluetoothProfileResultHandler* aRes);
|
||||||
|
|
||||||
bool ConnectSco();
|
bool ConnectSco();
|
||||||
bool DisconnectSco();
|
bool DisconnectSco();
|
||||||
|
|
|
@ -407,10 +407,9 @@ BluetoothAdapter::StartDiscovery(ErrorResult& aRv)
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
if (aRv.Failed()) {
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure
|
* Ensure
|
||||||
|
@ -451,10 +450,9 @@ BluetoothAdapter::StopDiscovery(ErrorResult& aRv)
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
if (aRv.Failed()) {
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure
|
* Ensure
|
||||||
|
@ -484,14 +482,13 @@ already_AddRefed<Promise>
|
||||||
BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
|
BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||||
if(!global) {
|
if (!global) {
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
if (aRv.Failed()) {
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure
|
* Ensure
|
||||||
|
@ -525,14 +522,13 @@ already_AddRefed<Promise>
|
||||||
BluetoothAdapter::SetDiscoverable(bool aDiscoverable, ErrorResult& aRv)
|
BluetoothAdapter::SetDiscoverable(bool aDiscoverable, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||||
if(!global) {
|
if (!global) {
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
if (aRv.Failed()) {
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure
|
* Ensure
|
||||||
|
@ -646,104 +642,17 @@ BluetoothAdapter::Unpair(const nsAString& aDeviceAddress, ErrorResult& aRv)
|
||||||
return PairUnpair(false, aDeviceAddress, aRv);
|
return PairUnpair(false, aDeviceAddress, aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<DOMRequest>
|
|
||||||
BluetoothAdapter::SetPinCode(const nsAString& aDeviceAddress,
|
|
||||||
const nsAString& aPinCode, ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
|
||||||
if (!win) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<DOMRequest> request = new DOMRequest(win);
|
|
||||||
nsRefPtr<BluetoothVoidReplyRunnable> results =
|
|
||||||
new BluetoothVoidReplyRunnable(request);
|
|
||||||
|
|
||||||
BluetoothService* bs = BluetoothService::Get();
|
|
||||||
if (!bs) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (!bs->SetPinCodeInternal(aDeviceAddress, aPinCode, results)) {
|
|
||||||
BT_WARNING("SetPinCode failed!");
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return request.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<DOMRequest>
|
|
||||||
BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
|
||||||
if (!win) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<DOMRequest> request = new DOMRequest(win);
|
|
||||||
nsRefPtr<BluetoothVoidReplyRunnable> results =
|
|
||||||
new BluetoothVoidReplyRunnable(request);
|
|
||||||
|
|
||||||
BluetoothService* bs = BluetoothService::Get();
|
|
||||||
if (!bs) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (bs->SetPasskeyInternal(aDeviceAddress, aPasskey, results)) {
|
|
||||||
BT_WARNING("SetPasskeyInternal failed!");
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return request.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<DOMRequest>
|
|
||||||
BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
|
|
||||||
bool aConfirmation, ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
|
||||||
if (!win) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<DOMRequest> request = new DOMRequest(win);
|
|
||||||
nsRefPtr<BluetoothVoidReplyRunnable> results =
|
|
||||||
new BluetoothVoidReplyRunnable(request);
|
|
||||||
|
|
||||||
BluetoothService* bs = BluetoothService::Get();
|
|
||||||
if (!bs) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (!bs->SetPairingConfirmationInternal(aDeviceAddress,
|
|
||||||
aConfirmation,
|
|
||||||
results)) {
|
|
||||||
BT_WARNING("SetPairingConfirmation failed!");
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return request.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<Promise>
|
already_AddRefed<Promise>
|
||||||
BluetoothAdapter::EnableDisable(bool aEnable, ErrorResult& aRv)
|
BluetoothAdapter::EnableDisable(bool aEnable, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||||
if(!global) {
|
if (!global) {
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
if (aRv.Failed()) {
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure BluetoothService is available before modifying adapter state
|
// Ensure BluetoothService is available before modifying adapter state
|
||||||
BluetoothService* bs = BluetoothService::Get();
|
BluetoothService* bs = BluetoothService::Get();
|
||||||
|
|
|
@ -99,18 +99,6 @@ public:
|
||||||
Unpair(const nsAString& aDeviceAddress, ErrorResult& aRv);
|
Unpair(const nsAString& aDeviceAddress, ErrorResult& aRv);
|
||||||
already_AddRefed<DOMRequest>
|
already_AddRefed<DOMRequest>
|
||||||
GetPairedDevices(ErrorResult& aRv);
|
GetPairedDevices(ErrorResult& aRv);
|
||||||
already_AddRefed<DOMRequest>
|
|
||||||
SetPinCode(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
already_AddRefed<DOMRequest>
|
|
||||||
SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
already_AddRefed<DOMRequest>
|
|
||||||
SetPairingConfirmation(const nsAString& aDeviceAddress, bool aConfirmation,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
already_AddRefed<DOMRequest>
|
|
||||||
SetAuthorization(const nsAString& aDeviceAddress, bool aAllow,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
already_AddRefed<Promise> EnableDisable(bool aEnable, ErrorResult& aRv);
|
already_AddRefed<Promise> EnableDisable(bool aEnable, ErrorResult& aRv);
|
||||||
already_AddRefed<Promise> Enable(ErrorResult& aRv);
|
already_AddRefed<Promise> Enable(ErrorResult& aRv);
|
||||||
|
|
|
@ -148,6 +148,15 @@ extern bool gBluetoothDebugFlag;
|
||||||
#define HFP_STATUS_CHANGED_ID "hfpstatuschanged"
|
#define HFP_STATUS_CHANGED_ID "hfpstatuschanged"
|
||||||
#define SCO_STATUS_CHANGED_ID "scostatuschanged"
|
#define SCO_STATUS_CHANGED_ID "scostatuschanged"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of pairing requests for constructing BluetoothPairingEvent and
|
||||||
|
* BluetoothPairingHandle.
|
||||||
|
*/
|
||||||
|
#define PAIRING_REQ_TYPE_DISPLAYPASSKEY "displaypasskeyreq"
|
||||||
|
#define PAIRING_REQ_TYPE_ENTERPINCODE "enterpincodereq"
|
||||||
|
#define PAIRING_REQ_TYPE_CONFIRMATION "pairingconfirmationreq"
|
||||||
|
#define PAIRING_REQ_TYPE_CONSENT "pairingconsentreq"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the pair status of a Bluetooth device is changed, we'll dispatch an
|
* When the pair status of a Bluetooth device is changed, we'll dispatch an
|
||||||
* event.
|
* event.
|
||||||
|
|
|
@ -144,9 +144,7 @@ BluetoothDevice::FetchUuids(ErrorResult& aRv)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
if (aRv.Failed()) {
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
BluetoothService* bs = BluetoothService::Get();
|
BluetoothService* bs = BluetoothService::Get();
|
||||||
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
|
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "BluetoothCommon.h"
|
||||||
|
#include "BluetoothDevice.h"
|
||||||
|
#include "BluetoothPairingHandle.h"
|
||||||
|
#include "BluetoothReplyRunnable.h"
|
||||||
|
#include "BluetoothService.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/BluetoothPairingHandleBinding.h"
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace dom;
|
||||||
|
|
||||||
|
USING_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BluetoothPairingHandle, mOwner)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothPairingHandle)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothPairingHandle)
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothPairingHandle)
|
||||||
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
BluetoothPairingHandle::BluetoothPairingHandle(nsPIDOMWindow* aOwner,
|
||||||
|
const nsAString& aDeviceAddress,
|
||||||
|
const nsAString& aType,
|
||||||
|
const nsAString& aPasskey)
|
||||||
|
: mOwner(aOwner)
|
||||||
|
, mDeviceAddress(aDeviceAddress)
|
||||||
|
, mType(aType)
|
||||||
|
, mPasskey(aPasskey)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aOwner && !aDeviceAddress.IsEmpty() && !aType.IsEmpty());
|
||||||
|
|
||||||
|
if (aType.EqualsLiteral(PAIRING_REQ_TYPE_DISPLAYPASSKEY) ||
|
||||||
|
aType.EqualsLiteral(PAIRING_REQ_TYPE_CONFIRMATION)) {
|
||||||
|
MOZ_ASSERT(!aPasskey.IsEmpty());
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(aPasskey.IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIsDOMBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
BluetoothPairingHandle::~BluetoothPairingHandle()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<BluetoothPairingHandle>
|
||||||
|
BluetoothPairingHandle::Create(nsPIDOMWindow* aOwner,
|
||||||
|
const nsAString& aDeviceAddress,
|
||||||
|
const nsAString& aType,
|
||||||
|
const nsAString& aPasskey)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aOwner && !aDeviceAddress.IsEmpty() && !aType.IsEmpty());
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothPairingHandle> handle =
|
||||||
|
new BluetoothPairingHandle(aOwner, aDeviceAddress, aType, aPasskey);
|
||||||
|
|
||||||
|
return handle.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
BluetoothPairingHandle::SetPinCode(const nsAString& aPinCode, ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||||
|
if (!global) {
|
||||||
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
|
|
||||||
|
BT_ENSURE_TRUE_REJECT(mType.EqualsLiteral("enterpincodereq"),
|
||||||
|
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
|
||||||
|
BluetoothService* bs = BluetoothService::Get();
|
||||||
|
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothReplyRunnable> result =
|
||||||
|
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
|
||||||
|
promise,
|
||||||
|
NS_LITERAL_STRING("SetPinCode"));
|
||||||
|
bs->SetPinCodeInternal(mDeviceAddress, aPinCode, result);
|
||||||
|
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
BluetoothPairingHandle::SetPairingConfirmation(bool aConfirm, ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||||
|
if (!global) {
|
||||||
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
|
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||||
|
|
||||||
|
BT_ENSURE_TRUE_REJECT(mType.EqualsLiteral("pairingconfirmationreq"),
|
||||||
|
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
|
||||||
|
BluetoothService* bs = BluetoothService::Get();
|
||||||
|
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothReplyRunnable> result =
|
||||||
|
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
|
||||||
|
promise,
|
||||||
|
NS_LITERAL_STRING(
|
||||||
|
"SetPairingConfirmation"));
|
||||||
|
|
||||||
|
bs->SetPairingConfirmationInternal(mDeviceAddress,
|
||||||
|
aConfirm,
|
||||||
|
result);
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
BluetoothPairingHandle::WrapObject(JSContext* aCx)
|
||||||
|
{
|
||||||
|
return BluetoothPairingHandleBinding::Wrap(aCx, this);
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_bluetooth_bluetoothpairinghandle_h
|
||||||
|
#define mozilla_dom_bluetooth_bluetoothpairinghandle_h
|
||||||
|
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
class ErrorResult;
|
||||||
|
namespace dom {
|
||||||
|
class Promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
class BluetoothDevice;
|
||||||
|
|
||||||
|
class BluetoothPairingHandle MOZ_FINAL : public nsISupports,
|
||||||
|
public nsWrapperCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothPairingHandle)
|
||||||
|
|
||||||
|
static already_AddRefed<BluetoothPairingHandle>
|
||||||
|
Create(nsPIDOMWindow* aOwner,
|
||||||
|
const nsAString& aDeviceAddress,
|
||||||
|
const nsAString& aType,
|
||||||
|
const nsAString& aPasskey);
|
||||||
|
|
||||||
|
nsPIDOMWindow* GetParentObject() const
|
||||||
|
{
|
||||||
|
return mOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
void GetPasskey(nsString& aPasskey) const
|
||||||
|
{
|
||||||
|
aPasskey = mPasskey;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
SetPinCode(const nsAString& aPinCode, ErrorResult& aRv);
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
SetPairingConfirmation(bool aConfirm, ErrorResult& aRv);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BluetoothPairingHandle(nsPIDOMWindow* aOwner,
|
||||||
|
const nsAString& aDeviceAddress,
|
||||||
|
const nsAString& aType,
|
||||||
|
const nsAString& aPasskey);
|
||||||
|
~BluetoothPairingHandle();
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMWindow> mOwner;
|
||||||
|
nsString mDeviceAddress;
|
||||||
|
nsString mType;
|
||||||
|
nsString mPasskey;
|
||||||
|
};
|
||||||
|
|
||||||
|
END_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
#endif // mozilla_dom_bluetooth_bluetoothpairinghandle_h
|
|
@ -219,15 +219,15 @@ public:
|
||||||
UpdateSdpRecords(const nsAString& aDeviceAddress,
|
UpdateSdpRecords(const nsAString& aDeviceAddress,
|
||||||
BluetoothProfileManagerBase* aManager) = 0;
|
BluetoothProfileManagerBase* aManager) = 0;
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
||||||
BluetoothReplyRunnable* aRunnable) = 0;
|
BluetoothReplyRunnable* aRunnable) = 0;
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
||||||
BluetoothReplyRunnable* aRunnable) = 0;
|
BluetoothReplyRunnable* aRunnable) = 0;
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
|
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
|
||||||
BluetoothReplyRunnable* aRunnable) = 0;
|
BluetoothReplyRunnable* aRunnable) = 0;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,15 @@
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
#define ENSURE_BLUETOOTH_IS_READY_VOID(runnable) \
|
||||||
|
do { \
|
||||||
|
if (!sBtInterface || !IsEnabled()) { \
|
||||||
|
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth is not ready"); \
|
||||||
|
DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::ipc;
|
using namespace mozilla::ipc;
|
||||||
USING_BLUETOOTH_NAMESPACE
|
USING_BLUETOOTH_NAMESPACE
|
||||||
|
@ -1492,14 +1501,14 @@ private:
|
||||||
BluetoothReplyRunnable* mRunnable;
|
BluetoothReplyRunnable* mRunnable;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothServiceBluedroid::SetPinCodeInternal(
|
BluetoothServiceBluedroid::SetPinCodeInternal(
|
||||||
const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
|
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
|
||||||
|
|
||||||
bt_bdaddr_t remoteAddress;
|
bt_bdaddr_t remoteAddress;
|
||||||
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
||||||
|
@ -1508,16 +1517,14 @@ BluetoothServiceBluedroid::SetPinCodeInternal(
|
||||||
&remoteAddress, true, aPinCode.Length(),
|
&remoteAddress, true, aPinCode.Length(),
|
||||||
(bt_pin_code_t*)NS_ConvertUTF16toUTF8(aPinCode).get(),
|
(bt_pin_code_t*)NS_ConvertUTF16toUTF8(aPinCode).get(),
|
||||||
new PinReplyResultHandler(aRunnable));
|
new PinReplyResultHandler(aRunnable));
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothServiceBluedroid::SetPasskeyInternal(
|
BluetoothServiceBluedroid::SetPasskeyInternal(
|
||||||
const nsAString& aDeviceAddress, uint32_t aPasskey,
|
const nsAString& aDeviceAddress, uint32_t aPasskey,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
{
|
{
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SspReplyResultHandler MOZ_FINAL : public BluetoothResultHandler
|
class SspReplyResultHandler MOZ_FINAL : public BluetoothResultHandler
|
||||||
|
@ -1542,21 +1549,23 @@ private:
|
||||||
BluetoothReplyRunnable* mRunnable;
|
BluetoothReplyRunnable* mRunnable;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothServiceBluedroid::SetPairingConfirmationInternal(
|
BluetoothServiceBluedroid::SetPairingConfirmationInternal(
|
||||||
const nsAString& aDeviceAddress, bool aConfirm,
|
const nsAString& aDeviceAddress, bool aConfirm,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
|
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
|
||||||
|
|
||||||
bt_bdaddr_t remoteAddress;
|
bt_bdaddr_t remoteAddress;
|
||||||
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
||||||
|
|
||||||
sBtInterface->SspReply(&remoteAddress, (bt_ssp_variant_t)0, aConfirm, 0,
|
sBtInterface->SspReply(&remoteAddress,
|
||||||
|
BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
|
||||||
|
aConfirm,
|
||||||
|
0, /* aPasskey */
|
||||||
new SspReplyResultHandler(aRunnable));
|
new SspReplyResultHandler(aRunnable));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -66,15 +66,15 @@ public:
|
||||||
RemoveDeviceInternal(const nsAString& aDeviceObjectPath,
|
RemoveDeviceInternal(const nsAString& aDeviceObjectPath,
|
||||||
BluetoothReplyRunnable* aRunnable);
|
BluetoothReplyRunnable* aRunnable);
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
||||||
BluetoothReplyRunnable* aRunnable);
|
BluetoothReplyRunnable* aRunnable);
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
||||||
BluetoothReplyRunnable* aRunnable);
|
BluetoothReplyRunnable* aRunnable);
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
|
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
|
||||||
BluetoothReplyRunnable* aRunnable);
|
BluetoothReplyRunnable* aRunnable);
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ BluetoothHfpManager::Init()
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
BluetoothHfpManager::InitHfpInterface()
|
BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
@ -157,11 +157,15 @@ BluetoothHfpManager::InitHfpInterface()
|
||||||
* Implement InitHfpInterface() for applications that want to create SCO
|
* Implement InitHfpInterface() for applications that want to create SCO
|
||||||
* link without a HFP connection (e.g., VoIP).
|
* link without a HFP connection (e.g., VoIP).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
BluetoothHfpManager::DeinitHfpInterface()
|
BluetoothHfpManager::DeinitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
@ -170,6 +174,10 @@ BluetoothHfpManager::DeinitHfpInterface()
|
||||||
* Implement DeinitHfpInterface() for applications that want to create SCO
|
* Implement DeinitHfpInterface() for applications that want to create SCO
|
||||||
* link without a HFP connection (e.g., VoIP).
|
* link without a HFP connection (e.g., VoIP).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Deinit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -30,8 +30,8 @@ public:
|
||||||
|
|
||||||
static BluetoothHfpManager* Get();
|
static BluetoothHfpManager* Get();
|
||||||
virtual ~BluetoothHfpManager() { }
|
virtual ~BluetoothHfpManager() { }
|
||||||
static void InitHfpInterface();
|
static void InitHfpInterface(BluetoothProfileResultHandler* aRes);
|
||||||
static void DeinitHfpInterface();
|
static void DeinitHfpInterface(BluetoothProfileResultHandler* aRes);
|
||||||
|
|
||||||
bool ConnectSco();
|
bool ConnectSco();
|
||||||
bool DisconnectSco();
|
bool DisconnectSco();
|
||||||
|
|
|
@ -3195,7 +3195,7 @@ private:
|
||||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress,
|
BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress,
|
||||||
const nsAString& aPinCode,
|
const nsAString& aPinCode,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
|
@ -3204,8 +3204,6 @@ BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress,
|
||||||
NS_ConvertUTF16toUTF8(aPinCode),
|
NS_ConvertUTF16toUTF8(aPinCode),
|
||||||
aRunnable);
|
aRunnable);
|
||||||
DispatchToDBusThread(task);
|
DispatchToDBusThread(task);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetPasskeyTask : public Task
|
class SetPasskeyTask : public Task
|
||||||
|
@ -3271,7 +3269,7 @@ private:
|
||||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress,
|
BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress,
|
||||||
uint32_t aPasskey,
|
uint32_t aPasskey,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
|
@ -3280,12 +3278,10 @@ BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress,
|
||||||
aPasskey,
|
aPasskey,
|
||||||
aRunnable);
|
aRunnable);
|
||||||
DispatchToDBusThread(task);
|
DispatchToDBusThread(task);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothDBusService::SetPairingConfirmationInternal(
|
BluetoothDBusService::SetPairingConfirmationInternal(
|
||||||
const nsAString& aDeviceAddress,
|
const nsAString& aDeviceAddress,
|
||||||
bool aConfirm,
|
bool aConfirm,
|
||||||
|
@ -3297,8 +3293,6 @@ BluetoothDBusService::SetPairingConfirmationInternal(
|
||||||
aConfirm,
|
aConfirm,
|
||||||
aRunnable);
|
aRunnable);
|
||||||
DispatchToDBusThread(task);
|
DispatchToDBusThread(task);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -93,15 +93,15 @@ public:
|
||||||
RemoveDeviceInternal(const nsAString& aDeviceObjectPath,
|
RemoveDeviceInternal(const nsAString& aDeviceObjectPath,
|
||||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual nsresult
|
||||||
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
||||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual nsresult
|
||||||
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
||||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual nsresult
|
||||||
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
|
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
|
||||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
|
|
@ -466,12 +466,9 @@ BluetoothRequestParent::DoRequest(const SetPinCodeRequest& aRequest)
|
||||||
MOZ_ASSERT(mService);
|
MOZ_ASSERT(mService);
|
||||||
MOZ_ASSERT(mRequestType == Request::TSetPinCodeRequest);
|
MOZ_ASSERT(mRequestType == Request::TSetPinCodeRequest);
|
||||||
|
|
||||||
bool result =
|
mService->SetPinCodeInternal(aRequest.path(),
|
||||||
mService->SetPinCodeInternal(aRequest.path(),
|
aRequest.pincode(),
|
||||||
aRequest.pincode(),
|
mReplyRunnable.get());
|
||||||
mReplyRunnable.get());
|
|
||||||
|
|
||||||
NS_ENSURE_TRUE(result, false);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -482,12 +479,9 @@ BluetoothRequestParent::DoRequest(const SetPasskeyRequest& aRequest)
|
||||||
MOZ_ASSERT(mService);
|
MOZ_ASSERT(mService);
|
||||||
MOZ_ASSERT(mRequestType == Request::TSetPasskeyRequest);
|
MOZ_ASSERT(mRequestType == Request::TSetPasskeyRequest);
|
||||||
|
|
||||||
bool result =
|
mService->SetPasskeyInternal(aRequest.path(),
|
||||||
mService->SetPasskeyInternal(aRequest.path(),
|
aRequest.passkey(),
|
||||||
aRequest.passkey(),
|
mReplyRunnable.get());
|
||||||
mReplyRunnable.get());
|
|
||||||
|
|
||||||
NS_ENSURE_TRUE(result, false);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -499,12 +493,9 @@ BluetoothRequestParent::DoRequest(const ConfirmPairingConfirmationRequest&
|
||||||
MOZ_ASSERT(mService);
|
MOZ_ASSERT(mService);
|
||||||
MOZ_ASSERT(mRequestType == Request::TConfirmPairingConfirmationRequest);
|
MOZ_ASSERT(mRequestType == Request::TConfirmPairingConfirmationRequest);
|
||||||
|
|
||||||
bool result =
|
mService->SetPairingConfirmationInternal(aRequest.path(),
|
||||||
mService->SetPairingConfirmationInternal(aRequest.path(),
|
true,
|
||||||
true,
|
mReplyRunnable.get());
|
||||||
mReplyRunnable.get());
|
|
||||||
|
|
||||||
NS_ENSURE_TRUE(result, false);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -516,12 +507,9 @@ BluetoothRequestParent::DoRequest(const DenyPairingConfirmationRequest&
|
||||||
MOZ_ASSERT(mService);
|
MOZ_ASSERT(mService);
|
||||||
MOZ_ASSERT(mRequestType == Request::TDenyPairingConfirmationRequest);
|
MOZ_ASSERT(mRequestType == Request::TDenyPairingConfirmationRequest);
|
||||||
|
|
||||||
bool result =
|
mService->SetPairingConfirmationInternal(aRequest.path(),
|
||||||
mService->SetPairingConfirmationInternal(aRequest.path(),
|
false,
|
||||||
false,
|
mReplyRunnable.get());
|
||||||
mReplyRunnable.get());
|
|
||||||
|
|
||||||
NS_ENSURE_TRUE(result, false);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ BluetoothServiceChildProcess::UpdateSdpRecords(const nsAString& aDeviceAddress,
|
||||||
MOZ_CRASH("This should never be called!");
|
MOZ_CRASH("This should never be called!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothServiceChildProcess::SetPinCodeInternal(
|
BluetoothServiceChildProcess::SetPinCodeInternal(
|
||||||
const nsAString& aDeviceAddress,
|
const nsAString& aDeviceAddress,
|
||||||
const nsAString& aPinCode,
|
const nsAString& aPinCode,
|
||||||
|
@ -215,10 +215,9 @@ BluetoothServiceChildProcess::SetPinCodeInternal(
|
||||||
{
|
{
|
||||||
SendRequest(aRunnable,
|
SendRequest(aRunnable,
|
||||||
SetPinCodeRequest(nsString(aDeviceAddress), nsString(aPinCode)));
|
SetPinCodeRequest(nsString(aDeviceAddress), nsString(aPinCode)));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothServiceChildProcess::SetPasskeyInternal(
|
BluetoothServiceChildProcess::SetPasskeyInternal(
|
||||||
const nsAString& aDeviceAddress,
|
const nsAString& aDeviceAddress,
|
||||||
uint32_t aPasskey,
|
uint32_t aPasskey,
|
||||||
|
@ -226,10 +225,9 @@ BluetoothServiceChildProcess::SetPasskeyInternal(
|
||||||
{
|
{
|
||||||
SendRequest(aRunnable,
|
SendRequest(aRunnable,
|
||||||
SetPasskeyRequest(nsString(aDeviceAddress), aPasskey));
|
SetPasskeyRequest(nsString(aDeviceAddress), aPasskey));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
BluetoothServiceChildProcess::SetPairingConfirmationInternal(
|
BluetoothServiceChildProcess::SetPairingConfirmationInternal(
|
||||||
const nsAString& aDeviceAddress,
|
const nsAString& aDeviceAddress,
|
||||||
bool aConfirm,
|
bool aConfirm,
|
||||||
|
@ -242,7 +240,6 @@ BluetoothServiceChildProcess::SetPairingConfirmationInternal(
|
||||||
SendRequest(aRunnable,
|
SendRequest(aRunnable,
|
||||||
DenyPairingConfirmationRequest(nsString(aDeviceAddress)));
|
DenyPairingConfirmationRequest(nsString(aDeviceAddress)));
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -94,17 +94,17 @@ public:
|
||||||
UpdateSdpRecords(const nsAString& aDeviceAddress,
|
UpdateSdpRecords(const nsAString& aDeviceAddress,
|
||||||
BluetoothProfileManagerBase* aManager) MOZ_OVERRIDE;
|
BluetoothProfileManagerBase* aManager) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPinCodeInternal(const nsAString& aDeviceAddress,
|
SetPinCodeInternal(const nsAString& aDeviceAddress,
|
||||||
const nsAString& aPinCode,
|
const nsAString& aPinCode,
|
||||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPasskeyInternal(const nsAString& aDeviceAddress,
|
SetPasskeyInternal(const nsAString& aDeviceAddress,
|
||||||
uint32_t aPasskey,
|
uint32_t aPasskey,
|
||||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual void
|
||||||
SetPairingConfirmationInternal(const nsAString& aDeviceAddress,
|
SetPairingConfirmationInternal(const nsAString& aDeviceAddress,
|
||||||
bool aConfirm,
|
bool aConfirm,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
|
|
|
@ -12,6 +12,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||||
'BluetoothDiscoveryHandle.cpp',
|
'BluetoothDiscoveryHandle.cpp',
|
||||||
'BluetoothHidManager.cpp',
|
'BluetoothHidManager.cpp',
|
||||||
'BluetoothManager.cpp',
|
'BluetoothManager.cpp',
|
||||||
|
'BluetoothPairingHandle.cpp',
|
||||||
'BluetoothProfileController.cpp',
|
'BluetoothProfileController.cpp',
|
||||||
'BluetoothReplyRunnable.cpp',
|
'BluetoothReplyRunnable.cpp',
|
||||||
'BluetoothService.cpp',
|
'BluetoothService.cpp',
|
||||||
|
@ -99,6 +100,7 @@ EXPORTS.mozilla.dom.bluetooth += [
|
||||||
'BluetoothDevice.h',
|
'BluetoothDevice.h',
|
||||||
'BluetoothDiscoveryHandle.h',
|
'BluetoothDiscoveryHandle.h',
|
||||||
'BluetoothManager.h',
|
'BluetoothManager.h',
|
||||||
|
'BluetoothPairingHandle.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
IPDL_SOURCES += [
|
IPDL_SOURCES += [
|
||||||
|
|
|
@ -231,6 +231,7 @@ BrowserElementChild.prototype = {
|
||||||
"go-forward": this._recvGoForward,
|
"go-forward": this._recvGoForward,
|
||||||
"reload": this._recvReload,
|
"reload": this._recvReload,
|
||||||
"stop": this._recvStop,
|
"stop": this._recvStop,
|
||||||
|
"zoom": this._recvZoom,
|
||||||
"unblock-modal-prompt": this._recvStopWaiting,
|
"unblock-modal-prompt": this._recvStopWaiting,
|
||||||
"fire-ctx-callback": this._recvFireCtxCallback,
|
"fire-ctx-callback": this._recvFireCtxCallback,
|
||||||
"owner-visibility-change": this._recvOwnerVisibilityChange,
|
"owner-visibility-change": this._recvOwnerVisibilityChange,
|
||||||
|
@ -1031,6 +1032,10 @@ BrowserElementChild.prototype = {
|
||||||
webNav.stop(webNav.STOP_NETWORK);
|
webNav.stop(webNav.STOP_NETWORK);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_recvZoom: function(data) {
|
||||||
|
docShell.contentViewer.fullZoom = data.json.zoom;
|
||||||
|
},
|
||||||
|
|
||||||
_recvSetInputMethodActive: function(data) {
|
_recvSetInputMethodActive: function(data) {
|
||||||
let msgData = { id: data.json.id };
|
let msgData = { id: data.json.id };
|
||||||
if (!this._isContentWindowCreated) {
|
if (!this._isContentWindowCreated) {
|
||||||
|
|
|
@ -126,6 +126,7 @@ function BrowserElementParent(frameLoader, hasRemoteFrame, isPendingFrame) {
|
||||||
defineNoReturnMethod('goForward', this._goForward);
|
defineNoReturnMethod('goForward', this._goForward);
|
||||||
defineNoReturnMethod('reload', this._reload);
|
defineNoReturnMethod('reload', this._reload);
|
||||||
defineNoReturnMethod('stop', this._stop);
|
defineNoReturnMethod('stop', this._stop);
|
||||||
|
defineNoReturnMethod('zoom', this._zoom);
|
||||||
defineMethod('download', this._download);
|
defineMethod('download', this._download);
|
||||||
defineDOMRequestMethod('purgeHistory', 'purge-history');
|
defineDOMRequestMethod('purgeHistory', 'purge-history');
|
||||||
defineMethod('getScreenshot', this._getScreenshot);
|
defineMethod('getScreenshot', this._getScreenshot);
|
||||||
|
@ -591,6 +592,16 @@ BrowserElementParent.prototype = {
|
||||||
this._sendAsyncMsg('stop');
|
this._sendAsyncMsg('stop');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent".
|
||||||
|
*/
|
||||||
|
_zoom: function(zoom) {
|
||||||
|
zoom *= 100;
|
||||||
|
zoom = Math.min(getIntPref("zoom.maxPercent", 300), zoom);
|
||||||
|
zoom = Math.max(getIntPref("zoom.minPercent", 50), zoom);
|
||||||
|
this._sendAsyncMsg('zoom', {zoom: zoom / 100.0});
|
||||||
|
},
|
||||||
|
|
||||||
_download: function(_url, _options) {
|
_download: function(_url, _options) {
|
||||||
let ioService =
|
let ioService =
|
||||||
Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
|
Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
|
||||||
|
|
|
@ -60,6 +60,10 @@ const kEventConstructors = {
|
||||||
return new BluetoothDiscoveryStateChangedEvent(aName, aProps);
|
return new BluetoothDiscoveryStateChangedEvent(aName, aProps);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BluetoothPairingEvent: { create: function (aName, aProps) {
|
||||||
|
return new BluetoothPairingEvent(aName, aProps);
|
||||||
|
},
|
||||||
|
},
|
||||||
BluetoothStatusChangedEvent: { create: function (aName, aProps) {
|
BluetoothStatusChangedEvent: { create: function (aName, aProps) {
|
||||||
return new BluetoothStatusChangedEvent(aName, aProps);
|
return new BluetoothStatusChangedEvent(aName, aProps);
|
||||||
},
|
},
|
||||||
|
|
|
@ -198,6 +198,18 @@ let PaymentManager = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_B2G
|
||||||
|
let appsService = Cc["@mozilla.org/AppsService;1"]
|
||||||
|
.getService(Ci.nsIAppsService);
|
||||||
|
let systemAppId = Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let manifestURL = Services.prefs.getCharPref("b2g.system_manifest_url");
|
||||||
|
systemAppId = appsService.getAppLocalIdByManifestURL(manifestURL);
|
||||||
|
this.LOG("System app id=" + systemAppId);
|
||||||
|
} catch(e) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Now register the payment providers.
|
// Now register the payment providers.
|
||||||
for (let i in nums) {
|
for (let i in nums) {
|
||||||
let branch = prefService
|
let branch = prefService
|
||||||
|
@ -211,12 +223,28 @@ let PaymentManager = {
|
||||||
if (type in this.registeredProviders) {
|
if (type in this.registeredProviders) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.registeredProviders[type] = {
|
let provider = this.registeredProviders[type] = {
|
||||||
name: branch.getCharPref("name"),
|
name: branch.getCharPref("name"),
|
||||||
uri: branch.getCharPref("uri"),
|
uri: branch.getCharPref("uri"),
|
||||||
description: branch.getCharPref("description"),
|
description: branch.getCharPref("description"),
|
||||||
requestMethod: branch.getCharPref("requestMethod")
|
requestMethod: branch.getCharPref("requestMethod")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef MOZ_B2G
|
||||||
|
// Let this payment provider access the firefox-accounts API when
|
||||||
|
// it's loaded in the trusted UI.
|
||||||
|
if (systemAppId != Ci.nsIScriptSecurityManager.NO_APP_ID) {
|
||||||
|
this.LOG("Granting firefox-accounts permission to " + provider.uri);
|
||||||
|
let uri = Services.io.newURI(provider.uri, null, null);
|
||||||
|
let principal = Services.scriptSecurityManager
|
||||||
|
.getAppCodebasePrincipal(uri, systemAppId, true);
|
||||||
|
|
||||||
|
Services.perms.addFromPrincipal(principal, "firefox-accounts",
|
||||||
|
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||||
|
Ci.nsIPermissionManager.EXPIRE_SESSION);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (this._debug) {
|
if (this._debug) {
|
||||||
this.LOG("Registered Payment Providers: " +
|
this.LOG("Registered Payment Providers: " +
|
||||||
JSON.stringify(this.registeredProviders[type]));
|
JSON.stringify(this.registeredProviders[type]));
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
DIRS += ['interfaces']
|
DIRS += ['interfaces']
|
||||||
|
|
||||||
EXTRA_JS_MODULES += [
|
EXTRA_PP_JS_MODULES += [
|
||||||
'Payment.jsm',
|
'Payment.jsm',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -113,12 +113,6 @@ interface BluetoothAdapter : EventTarget {
|
||||||
DOMRequest getPairedDevices();
|
DOMRequest getPairedDevices();
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
DOMRequest getConnectedDevices(unsigned short serviceUuid);
|
DOMRequest getConnectedDevices(unsigned short serviceUuid);
|
||||||
[NewObject, Throws]
|
|
||||||
DOMRequest setPinCode(DOMString deviceAddress, DOMString pinCode);
|
|
||||||
[NewObject, Throws]
|
|
||||||
DOMRequest setPasskey(DOMString deviceAddress, unsigned long passkey);
|
|
||||||
[NewObject, Throws]
|
|
||||||
DOMRequest setPairingConfirmation(DOMString deviceAddress, boolean confirmation);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect/Disconnect to a specific service of a target remote device.
|
* Connect/Disconnect to a specific service of a target remote device.
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* -*- 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/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[CheckPermissions="bluetooth",
|
||||||
|
Constructor(DOMString type,
|
||||||
|
optional BluetoothPairingEventInit eventInitDict)]
|
||||||
|
interface BluetoothPairingEvent : Event
|
||||||
|
{
|
||||||
|
readonly attribute BluetoothDevice? device;
|
||||||
|
readonly attribute BluetoothPairingHandle? handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary BluetoothPairingEventInit : EventInit
|
||||||
|
{
|
||||||
|
BluetoothDevice? device = null;
|
||||||
|
BluetoothPairingHandle? handle = null;
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* -*- 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/. */
|
||||||
|
|
||||||
|
[CheckPermissions="bluetooth"]
|
||||||
|
interface BluetoothPairingHandle
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A 6-digit string ranging from decimal 000000 to 999999.
|
||||||
|
* This attribute is an empty string for enterpincodereq and
|
||||||
|
* pairingconsentreq.
|
||||||
|
*/
|
||||||
|
readonly attribute DOMString passkey;
|
||||||
|
|
||||||
|
// Promise<void>
|
||||||
|
[NewObject, Throws]
|
||||||
|
Promise setPinCode(DOMString aPinCode);
|
||||||
|
// Promise<void>
|
||||||
|
[NewObject, Throws]
|
||||||
|
Promise setPairingConfirmation(boolean aConfirm);
|
||||||
|
};
|
|
@ -571,6 +571,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||||
'BluetoothDevice2.webidl',
|
'BluetoothDevice2.webidl',
|
||||||
'BluetoothDiscoveryHandle.webidl',
|
'BluetoothDiscoveryHandle.webidl',
|
||||||
'BluetoothManager2.webidl',
|
'BluetoothManager2.webidl',
|
||||||
|
'BluetoothPairingHandle.webidl',
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
WEBIDL_FILES += [
|
WEBIDL_FILES += [
|
||||||
|
@ -695,6 +696,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||||
'BluetoothAdapterEvent.webidl',
|
'BluetoothAdapterEvent.webidl',
|
||||||
'BluetoothAttributeEvent.webidl',
|
'BluetoothAttributeEvent.webidl',
|
||||||
|
'BluetoothPairingEvent.webidl',
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||||
|
|
|
@ -3642,6 +3642,14 @@ nsTextPaintStyle::InitSelectionColorsAndShadow()
|
||||||
eCSSProperty_color;
|
eCSSProperty_color;
|
||||||
nscoord frameColor = mFrame->GetVisitedDependentColor(property);
|
nscoord frameColor = mFrame->GetVisitedDependentColor(property);
|
||||||
mSelectionTextColor = EnsureDifferentColors(frameColor, mSelectionBGColor);
|
mSelectionTextColor = EnsureDifferentColors(frameColor, mSelectionBGColor);
|
||||||
|
} else if (mSelectionTextColor == NS_CHANGE_COLOR_IF_SAME_AS_BG) {
|
||||||
|
nsCSSProperty property = mFrame->IsSVGText() ? eCSSProperty_fill :
|
||||||
|
eCSSProperty_color;
|
||||||
|
nscolor frameColor = mFrame->GetVisitedDependentColor(property);
|
||||||
|
if (frameColor == mSelectionBGColor) {
|
||||||
|
mSelectionTextColor =
|
||||||
|
LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectForegroundCustom);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor);
|
EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,15 @@ function setPermissions() {
|
||||||
perms.add(uri, "allowXULXBL", Ci.nsIPermissionManager.ALLOW_ACTION);
|
perms.add(uri, "allowXULXBL", Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cm = Cc["@mozilla.org/categorymanager;1"]
|
||||||
|
.getService(Components.interfaces.nsICategoryManager);
|
||||||
|
|
||||||
|
// Disable update timers that cause b2g failures.
|
||||||
|
if (cm) {
|
||||||
|
cm.deleteCategoryEntry("update-timer", "WebappsUpdateTimer", false);
|
||||||
|
cm.deleteCategoryEntry("update-timer", "nsUpdateService", false);
|
||||||
|
}
|
||||||
|
|
||||||
// Load into any existing windows
|
// Load into any existing windows
|
||||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
|
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||||
.getService(Ci.nsIWindowMediator);
|
.getService(Ci.nsIWindowMediator);
|
||||||
|
|
|
@ -54,10 +54,13 @@ this.MobileIdentityClient.prototype = {
|
||||||
return this._request(REGISTER, "POST", null, {});
|
return this._request(REGISTER, "POST", null, {});
|
||||||
},
|
},
|
||||||
|
|
||||||
smsMtVerify: function(aSessionToken, aMsisdn, aWantShortCode = false) {
|
smsMtVerify: function(aSessionToken, aMsisdn, aMcc, aMnc,
|
||||||
|
aWantShortCode = false) {
|
||||||
let credentials = this._deriveHawkCredentials(aSessionToken);
|
let credentials = this._deriveHawkCredentials(aSessionToken);
|
||||||
return this._request(SMS_MT_VERIFY, "POST", credentials, {
|
return this._request(SMS_MT_VERIFY, "POST", credentials, {
|
||||||
msisdn: aMsisdn,
|
msisdn: aMsisdn,
|
||||||
|
mcc: aMcc,
|
||||||
|
mnc: aMnc,
|
||||||
shortVerificationCode: aWantShortCode
|
shortVerificationCode: aWantShortCode
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -450,30 +450,31 @@ this.MobileIdentityManager = {
|
||||||
aToVerify.msisdn &&
|
aToVerify.msisdn &&
|
||||||
aToVerify.verificationDetails &&
|
aToVerify.verificationDetails &&
|
||||||
aToVerify.verificationDetails.mtSender) {
|
aToVerify.verificationDetails.mtSender) {
|
||||||
this.activeVerificationFlow = new MobileIdentitySmsMtVerificationFlow(
|
this.activeVerificationFlow = new MobileIdentitySmsMtVerificationFlow({
|
||||||
aOrigin,
|
origin: aOrigin,
|
||||||
aToVerify.msisdn,
|
msisdn: aToVerify.msisdn,
|
||||||
aToVerify.iccId,
|
mcc: aToVerify.mcc,
|
||||||
aToVerify.serviceId === undefined, // external: the phone number does
|
mnc: aToVerify.mnc,
|
||||||
// not seem to belong to any of the
|
iccId: aToVerify.iccId,
|
||||||
// device SIM cards.
|
external: aToVerify.serviceId === undefined,
|
||||||
aToVerify.verificationDetails.mtSender,
|
mtSender: aToVerify.verificationDetails.mtSender
|
||||||
|
},
|
||||||
this.ui,
|
this.ui,
|
||||||
this.client
|
this.client
|
||||||
);
|
);
|
||||||
#ifdef MOZ_B2G_RIL
|
#ifdef MOZ_B2G_RIL
|
||||||
} else if (aToVerify.verificationMethod.indexOf(SMS_MO_MT) != -1 &&
|
} else if (aToVerify.verificationMethod.indexOf(SMS_MO_MT) != -1 &&
|
||||||
aToVerify.serviceId &&
|
aToVerify.serviceId &&
|
||||||
aToVerify.verificationDetails &&
|
aToVerify.verificationDetails &&
|
||||||
aToVerify.verificationDetails.moVerifier &&
|
aToVerify.verificationDetails.moVerifier &&
|
||||||
aToVerify.verificationDetails.mtSender) {
|
aToVerify.verificationDetails.mtSender) {
|
||||||
|
this.activeVerificationFlow = new MobileIdentitySmsMoMtVerificationFlow({
|
||||||
this.activeVerificationFlow = new MobileIdentitySmsMoMtVerificationFlow(
|
origin: aOrigin,
|
||||||
aOrigin,
|
serviceId: aToVerify.serviceId,
|
||||||
aToVerify.serviceId,
|
iccId: aToVerify.iccId,
|
||||||
aToVerify.iccId,
|
mtSender: aToVerify.verificationDetails.mtSender,
|
||||||
aToVerify.verificationDetails.mtSender,
|
moVerifier: aToVerify.verificationDetails.moVerifier
|
||||||
aToVerify.verificationDetails.moVerifier,
|
},
|
||||||
this.ui,
|
this.ui,
|
||||||
this.client
|
this.client
|
||||||
);
|
);
|
||||||
|
@ -517,6 +518,8 @@ this.MobileIdentityManager = {
|
||||||
toVerify.serviceId = serviceId;
|
toVerify.serviceId = serviceId;
|
||||||
toVerify.iccId = this.iccInfo[serviceId].iccId;
|
toVerify.iccId = this.iccInfo[serviceId].iccId;
|
||||||
toVerify.msisdn = this.iccInfo[serviceId].msisdn;
|
toVerify.msisdn = this.iccInfo[serviceId].msisdn;
|
||||||
|
toVerify.mcc = this.iccInfo[serviceId].mcc;
|
||||||
|
toVerify.mnc = this.iccInfo[serviceId].mnc;
|
||||||
toVerify.verificationMethod =
|
toVerify.verificationMethod =
|
||||||
this.iccInfo[serviceId].verificationMethods[0];
|
this.iccInfo[serviceId].verificationMethods[0];
|
||||||
toVerify.verificationDetails =
|
toVerify.verificationDetails =
|
||||||
|
@ -524,6 +527,7 @@ this.MobileIdentityManager = {
|
||||||
return this._verificationFlow(toVerify, aOrigin);
|
return this._verificationFlow(toVerify, aOrigin);
|
||||||
} else {
|
} else {
|
||||||
toVerify.msisdn = aUserSelection.msisdn;
|
toVerify.msisdn = aUserSelection.msisdn;
|
||||||
|
toVerify.mcc = aUserSelection.mcc;
|
||||||
return this.client.discover(aUserSelection.msisdn,
|
return this.client.discover(aUserSelection.msisdn,
|
||||||
aUserSelection.mcc)
|
aUserSelection.mcc)
|
||||||
.then(
|
.then(
|
||||||
|
|
|
@ -39,24 +39,14 @@ SilentSmsRequest.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.MobileIdentitySmsMoMtVerificationFlow = function(aOrigin,
|
this.MobileIdentitySmsMoMtVerificationFlow = function(aVerificationOptions,
|
||||||
aServiceId,
|
|
||||||
aIccId,
|
|
||||||
aMtSender,
|
|
||||||
aMoVerifier,
|
|
||||||
aUI,
|
aUI,
|
||||||
aClient) {
|
aClient) {
|
||||||
|
|
||||||
log.debug("MobileIdentitySmsMoMtVerificationFlow");
|
log.debug("MobileIdentitySmsMoMtVerificationFlow ${}", aVerificationOptions);
|
||||||
|
|
||||||
MobileIdentitySmsVerificationFlow.call(this,
|
MobileIdentitySmsVerificationFlow.call(this,
|
||||||
aOrigin,
|
aVerificationOptions,
|
||||||
null, //msisdn
|
|
||||||
aIccId,
|
|
||||||
aServiceId,
|
|
||||||
false, // external
|
|
||||||
aMtSender,
|
|
||||||
aMoVerifier,
|
|
||||||
aUI,
|
aUI,
|
||||||
aClient,
|
aClient,
|
||||||
this.smsVerifyStrategy);
|
this.smsVerifyStrategy);
|
||||||
|
|
|
@ -13,25 +13,14 @@ Cu.import("resource://gre/modules/MobileIdentitySmsVerificationFlow.jsm");
|
||||||
Cu.import("resource://gre/modules/Promise.jsm");
|
Cu.import("resource://gre/modules/Promise.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
this.MobileIdentitySmsMtVerificationFlow = function(aOrigin,
|
this.MobileIdentitySmsMtVerificationFlow = function(aVerificationOptions,
|
||||||
aMsisdn,
|
|
||||||
aIccId,
|
|
||||||
aExternal,
|
|
||||||
aMtSender,
|
|
||||||
aUI,
|
aUI,
|
||||||
aClient) {
|
aClient) {
|
||||||
|
|
||||||
log.debug("MobileIdentitySmsVerificationFlow " + aMsisdn + ", external: " +
|
log.debug("MobileIdentitySmsVerificationFlow ${}", aVerificationOptions);
|
||||||
aExternal);
|
|
||||||
|
|
||||||
MobileIdentitySmsVerificationFlow.call(this,
|
MobileIdentitySmsVerificationFlow.call(this,
|
||||||
aOrigin,
|
aVerificationOptions,
|
||||||
aMsisdn,
|
|
||||||
aIccId,
|
|
||||||
null, // service ID
|
|
||||||
aExternal,
|
|
||||||
aMtSender,
|
|
||||||
null, // moVerifier
|
|
||||||
aUI,
|
aUI,
|
||||||
aClient,
|
aClient,
|
||||||
this.smsVerifyStrategy);
|
this.smsVerifyStrategy);
|
||||||
|
@ -44,6 +33,8 @@ this.MobileIdentitySmsMtVerificationFlow.prototype = {
|
||||||
smsVerifyStrategy: function() {
|
smsVerifyStrategy: function() {
|
||||||
return this.client.smsMtVerify(this.sessionToken,
|
return this.client.smsMtVerify(this.sessionToken,
|
||||||
this.verificationOptions.msisdn,
|
this.verificationOptions.msisdn,
|
||||||
|
this.verificationOptions.mcc,
|
||||||
|
this.verificationOptions.mnc,
|
||||||
this.verificationOptions.external);
|
this.verificationOptions.external);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,13 +19,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "smsService",
|
||||||
"nsISmsService");
|
"nsISmsService");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this.MobileIdentitySmsVerificationFlow = function(aOrigin,
|
this.MobileIdentitySmsVerificationFlow = function(aVerificationOptions,
|
||||||
aMsisdn,
|
|
||||||
aIccId,
|
|
||||||
aServiceId,
|
|
||||||
aExternal,
|
|
||||||
aMtSender,
|
|
||||||
aMoVerifier,
|
|
||||||
aUI,
|
aUI,
|
||||||
aClient,
|
aClient,
|
||||||
aVerifyStrategy) {
|
aVerifyStrategy) {
|
||||||
|
@ -33,15 +27,9 @@ this.MobileIdentitySmsVerificationFlow = function(aOrigin,
|
||||||
// SMS MT or SMS MO+MT specific verify strategy.
|
// SMS MT or SMS MO+MT specific verify strategy.
|
||||||
this.smsVerifyStrategy = aVerifyStrategy;
|
this.smsVerifyStrategy = aVerifyStrategy;
|
||||||
|
|
||||||
MobileIdentityVerificationFlow.call(this, {
|
log.debug("aVerificationOptions ${}", aVerificationOptions);
|
||||||
origin: aOrigin,
|
MobileIdentityVerificationFlow.call(this, aVerificationOptions, aUI, aClient,
|
||||||
msisdn: aMsisdn,
|
this._verifyStrategy, this._cleanupStrategy);
|
||||||
iccId: aIccId,
|
|
||||||
serviceId: aServiceId,
|
|
||||||
external: aExternal,
|
|
||||||
mtSender: aMtSender,
|
|
||||||
moVerifier: aMoVerifier
|
|
||||||
}, aUI, aClient, this._verifyStrategy, this._cleanupStrategy);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.MobileIdentitySmsVerificationFlow.prototype = {
|
this.MobileIdentitySmsVerificationFlow.prototype = {
|
||||||
|
|
|
@ -138,7 +138,8 @@ MockUi.prototype = {
|
||||||
__proto__: Mock.prototype,
|
__proto__: Mock.prototype,
|
||||||
|
|
||||||
_startFlowResult: {
|
_startFlowResult: {
|
||||||
phoneNumber: PHONE_NUMBER
|
phoneNumber: PHONE_NUMBER,
|
||||||
|
mcc: MNC
|
||||||
},
|
},
|
||||||
|
|
||||||
_verifyCodePromptResult: {
|
_verifyCodePromptResult: {
|
||||||
|
@ -434,7 +435,9 @@ add_test(function() {
|
||||||
client._("smsMtVerify").callsLength(1);
|
client._("smsMtVerify").callsLength(1);
|
||||||
client._("smsMtVerify").call(1).arg(1, SESSION_TOKEN);
|
client._("smsMtVerify").call(1).arg(1, SESSION_TOKEN);
|
||||||
client._("smsMtVerify").call(1).arg(2, PHONE_NUMBER);
|
client._("smsMtVerify").call(1).arg(2, PHONE_NUMBER);
|
||||||
client._("smsMtVerify").call(1).arg(3, true);
|
client._("smsMtVerify").call(1).arg(3, MNC);
|
||||||
|
client._("smsMtVerify").call(1).arg(4, undefined);
|
||||||
|
client._("smsMtVerify").call(1).arg(5, true);
|
||||||
client._("verifyCode").callsLength(1);
|
client._("verifyCode").callsLength(1);
|
||||||
client._("verifyCode").call(1).arg(1, SESSION_TOKEN);
|
client._("verifyCode").call(1).arg(1, SESSION_TOKEN);
|
||||||
client._("verifyCode").call(1).arg(2, {
|
client._("verifyCode").call(1).arg(2, {
|
||||||
|
@ -670,7 +673,9 @@ add_test(function() {
|
||||||
client._("smsMtVerify").callsLength(1);
|
client._("smsMtVerify").callsLength(1);
|
||||||
client._("smsMtVerify").call(1).arg(1, _sessionToken);
|
client._("smsMtVerify").call(1).arg(1, _sessionToken);
|
||||||
client._("smsMtVerify").call(1).arg(2, PHONE_NUMBER);
|
client._("smsMtVerify").call(1).arg(2, PHONE_NUMBER);
|
||||||
client._("smsMtVerify").call(1).arg(3, true);
|
client._("smsMtVerify").call(1).arg(3, MNC);
|
||||||
|
client._("smsMtVerify").call(1).arg(4, undefined);
|
||||||
|
client._("smsMtVerify").call(1).arg(5, true);
|
||||||
client._("verifyCode").callsLength(1);
|
client._("verifyCode").callsLength(1);
|
||||||
client._("verifyCode").call(1).arg(1, _sessionToken);
|
client._("verifyCode").call(1).arg(1, _sessionToken);
|
||||||
client._("verifyCode").call(1).arg(2, {
|
client._("verifyCode").call(1).arg(2, {
|
||||||
|
|
|
@ -262,7 +262,7 @@ WebappsActor.prototype = {
|
||||||
reg.broadcastMessage("Webapps:UpdateState", {
|
reg.broadcastMessage("Webapps:UpdateState", {
|
||||||
app: aApp,
|
app: aApp,
|
||||||
manifest: manifest,
|
manifest: manifest,
|
||||||
manifestURL: aApp.manifestURL
|
id: aApp.id
|
||||||
});
|
});
|
||||||
reg.broadcastMessage("Webapps:FireEvent", {
|
reg.broadcastMessage("Webapps:FireEvent", {
|
||||||
eventType: ["downloadsuccess", "downloadapplied"],
|
eventType: ["downloadsuccess", "downloadapplied"],
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
eColorID_TextForeground,
|
eColorID_TextForeground,
|
||||||
eColorID_TextSelectBackground,
|
eColorID_TextSelectBackground,
|
||||||
eColorID_TextSelectForeground,
|
eColorID_TextSelectForeground,
|
||||||
|
eColorID_TextSelectForegroundCustom,
|
||||||
eColorID_TextSelectBackgroundDisabled,
|
eColorID_TextSelectBackgroundDisabled,
|
||||||
eColorID_TextSelectBackgroundAttention,
|
eColorID_TextSelectBackgroundAttention,
|
||||||
eColorID_TextHighlightBackground,
|
eColorID_TextHighlightBackground,
|
||||||
|
@ -588,6 +589,12 @@ public:
|
||||||
// Of course if other plaforms work like the Mac, they can use it too.
|
// Of course if other plaforms work like the Mac, they can use it too.
|
||||||
#define NS_DONT_CHANGE_COLOR NS_RGB(0x01, 0x01, 0x01)
|
#define NS_DONT_CHANGE_COLOR NS_RGB(0x01, 0x01, 0x01)
|
||||||
|
|
||||||
|
// Similar with NS_DONT_CHANGE_COLOR, except NS_DONT_CHANGE_COLOR would returns
|
||||||
|
// complementary color if fg color is same as bg color.
|
||||||
|
// NS_CHANGE_COLOR_IF_SAME_AS_BG would returns eColorID_TextSelectForegroundCustom if
|
||||||
|
// fg and bg color are the same.
|
||||||
|
#define NS_CHANGE_COLOR_IF_SAME_AS_BG NS_RGB(0x02, 0x02, 0x02)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Special colors for eColorID_IME* and eColorID_SpellCheckerUnderline
|
// Special colors for eColorID_IME* and eColorID_SpellCheckerUnderline
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
|
@ -97,7 +97,12 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
|
||||||
// still used
|
// still used
|
||||||
aColor = BASE_SELECTED_COLOR;
|
aColor = BASE_SELECTED_COLOR;
|
||||||
break;
|
break;
|
||||||
|
case eColorID_TextSelectForegroundCustom:
|
||||||
|
aColor = NS_RGB(0x4d,0x4d,0x4d);
|
||||||
|
break;
|
||||||
case eColorID_TextSelectForeground:
|
case eColorID_TextSelectForeground:
|
||||||
|
aColor = NS_CHANGE_COLOR_IF_SAME_AS_BG;
|
||||||
|
break;
|
||||||
case eColorID_IMESelectedRawTextForeground:
|
case eColorID_IMESelectedRawTextForeground:
|
||||||
case eColorID_IMESelectedConvertedTextForeground:
|
case eColorID_IMESelectedConvertedTextForeground:
|
||||||
// still used
|
// still used
|
||||||
|
|
|
@ -151,6 +151,7 @@ const char nsXPLookAndFeel::sColorPrefs[][38] =
|
||||||
"ui.textForeground",
|
"ui.textForeground",
|
||||||
"ui.textSelectBackground",
|
"ui.textSelectBackground",
|
||||||
"ui.textSelectForeground",
|
"ui.textSelectForeground",
|
||||||
|
"ui.textSelectForegroundCustom",
|
||||||
"ui.textSelectBackgroundDisabled",
|
"ui.textSelectBackgroundDisabled",
|
||||||
"ui.textSelectBackgroundAttention",
|
"ui.textSelectBackgroundAttention",
|
||||||
"ui.textHighlightBackground",
|
"ui.textHighlightBackground",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче