Merge b2g-inbound to m-c a=merge

This commit is contained in:
Wes Kocher 2014-07-29 16:42:15 -07:00
Родитель 93ba218ccc 9029cc988a
Коммит c3fdde7659
59 изменённых файлов: 1161 добавлений и 630 удалений

Просмотреть файл

@ -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",