Merge m-c to inbound. a=merge

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2015-05-06 16:27:28 -04:00
commit d9725dbb72
117 changed files with 1422 additions and 482 deletions

View File

@ -1 +0,0 @@
b2g/branding/official/content/splash.png

View File

@ -1 +0,0 @@
b2g/branding/unofficial/content/splash.png

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26"> <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<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="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>

View File

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26"> <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<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="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33"> <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<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="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26"> <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<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="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -17,7 +17,7 @@
</project> </project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

View File

@ -1,9 +1,9 @@
{ {
"git": { "git": {
"git_revision": "eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785", "git_revision": "426fe6450ab8da92bb473fef12ccb39c6c920dd0",
"remote": "https://git.mozilla.org/releases/gaia.git", "remote": "https://git.mozilla.org/releases/gaia.git",
"branch": "" "branch": ""
}, },
"revision": "78e99873114b371f245690c3b0b80834a649f2f2", "revision": "b48088c5abd6ad5a64b9b870e52d6de14b3f2bc3",
"repo_path": "integration/gaia-central" "repo_path": "integration/gaia-central"
} }

View File

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33"> <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
<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="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -1443,16 +1443,15 @@ pref("devtools.performance.ui.show-idle-blocks", true);
pref("devtools.performance.ui.enable-memory", false); pref("devtools.performance.ui.enable-memory", false);
pref("devtools.performance.ui.enable-framerate", true); pref("devtools.performance.ui.enable-framerate", true);
pref("devtools.performance.ui.show-jit-optimizations", false); pref("devtools.performance.ui.show-jit-optimizations", false);
// If in aurora (40.0, will revert for 40.1), set default // If in aurora/dev edition (40.0, will revert for 40.1), set default
// to retro mode. // to retro mode.
// TODO bug 1160313 // TODO bug 1160313
#if MOZ_UPDATE_CHANNEL == aurora #ifdef MOZ_DEV_EDITION
pref("devtools.performance.ui.retro-mode", true); pref("devtools.performance.ui.retro-mode", true);
#else #else
pref("devtools.performance.ui.retro-mode", false); pref("devtools.performance.ui.retro-mode", false);
#endif #endif
// The default cache UI setting // The default cache UI setting
pref("devtools.cache.disabled", false); pref("devtools.cache.disabled", false);

View File

@ -49,7 +49,6 @@
"no-empty": 0, // TODO: Remove (use default) "no-empty": 0, // TODO: Remove (use default)
"no-extra-bind": 0, // Leave as 0 "no-extra-bind": 0, // Leave as 0
"no-extra-boolean-cast": 0, // TODO: Remove (use default) "no-extra-boolean-cast": 0, // TODO: Remove (use default)
"no-extra-semi": 0, // TODO: Remove (use default)
"no-multi-spaces": 0, // TBD. "no-multi-spaces": 0, // TBD.
"no-new": 0, // TODO: Remove (use default) "no-new": 0, // TODO: Remove (use default)
"no-redeclare": 0, // TODO: Remove (use default) "no-redeclare": 0, // TODO: Remove (use default)
@ -64,8 +63,6 @@
"no-use-before-define": 0, // TODO: Remove (use default) "no-use-before-define": 0, // TODO: Remove (use default)
"no-wrap-func": 0, // TODO: Remove (use default) "no-wrap-func": 0, // TODO: Remove (use default)
"quotes": 0, // [2, "double", "avoid-escape"], "quotes": 0, // [2, "double", "avoid-escape"],
"semi": 0, // TODO: Remove (use default)
"semi-spacing": 0, // TODO: Remove (use default)
"space-infix-ops": 0, // TODO: Remove (use default) "space-infix-ops": 0, // TODO: Remove (use default)
"space-return-throw-case": 0, // TODO: Remove (use default) "space-return-throw-case": 0, // TODO: Remove (use default)
"strict": 0, // [2, "function"], "strict": 0, // [2, "function"],

View File

@ -18,7 +18,7 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
throw new Error("mozL10n.get not availabled from chrome!"); throw new Error("mozL10n.get not availabled from chrome!");
}}; }};
} else { } else {
mozL10n = document.mozL10n || navigator.mozL10n mozL10n = document.mozL10n || navigator.mozL10n;
} }
/** /**

View File

@ -46,7 +46,7 @@ loop.CallConnectionWebSocket = (function() {
loop.shared.utils.getBoolPreference("debug.websocket"); loop.shared.utils.getBoolPreference("debug.websocket");
_.extend(this, Backbone.Events); _.extend(this, Backbone.Events);
}; }
CallConnectionWebSocket.prototype = { CallConnectionWebSocket.prototype = {
/** /**

View File

@ -306,7 +306,7 @@ this.CardDavImporter.prototype = {
// a supported field. We're saving it off here in case we // a supported field. We're saving it off here in case we
// need to use it if the fullname is blank. // need to use it if the fullname is blank.
nickname = value; nickname = value;
}; }
if (name === "ADR") { if (name === "ADR") {
value = value.replace(/\\;/g, "\r"); value = value.replace(/\\;/g, "\r");
@ -455,7 +455,7 @@ this.CardDavImporter.prototype = {
req.onerror = function(error) { req.onerror = function(error) {
reject(error); reject(error);
} };
req.send(body); req.send(body);
}); });

View File

@ -325,7 +325,7 @@ this.GoogleImporter.prototype = {
request.onerror = function(error) { request.onerror = function(error) {
reject(error); reject(error);
} };
request.send(); request.send();
}); });
@ -514,7 +514,7 @@ this.GoogleImporter.prototype = {
for (let [,orgNode] of Iterator(orgNodes)) { for (let [,orgNode] of Iterator(orgNodes)) {
let orgElement = orgNode.getElementsByTagNameNS(kNS_GD, "orgName")[0]; let orgElement = orgNode.getElementsByTagNameNS(kNS_GD, "orgName")[0];
let titleElement = orgNode.getElementsByTagNameNS(kNS_GD, "orgTitle")[0]; let titleElement = orgNode.getElementsByTagNameNS(kNS_GD, "orgTitle")[0];
contact.org.push(orgElement ? orgElement.textContent : "") contact.org.push(orgElement ? orgElement.textContent : "");
contact.jobTitle.push(titleElement ? titleElement.textContent : ""); contact.jobTitle.push(titleElement ? titleElement.textContent : "");
} }
} }

View File

@ -53,8 +53,9 @@ CallProgressSocket.prototype = {
*/ */
connect: function(onSuccess, onError) { connect: function(onSuccess, onError) {
this._onSuccess = onSuccess; this._onSuccess = onSuccess;
this._onError = onError || this._onError = onError || (reason => {
(reason => {MozLoopService.log.warn("LoopCalls::callProgessSocket - ", reason);}); MozLoopService.log.warn("LoopCalls::callProgessSocket - ", reason);
});
if (!onSuccess) { if (!onSuccess) {
this._onError("missing onSuccess argument"); this._onError("missing onSuccess argument");
@ -237,7 +238,7 @@ let LoopCallsInternal = {
_getCalls: function(sessionType, version) { _getCalls: function(sessionType, version) {
return MozLoopService.hawkRequest(sessionType, "/calls?version=" + version, "GET").then( return MozLoopService.hawkRequest(sessionType, "/calls?version=" + version, "GET").then(
response => {this._processCalls(response, sessionType);} response => { this._processCalls(response, sessionType); }
); );
}, },
@ -309,7 +310,7 @@ let LoopCallsInternal = {
} }
openChat(); openChat();
}) });
} else { } else {
openChat(); openChat();
} }
@ -397,7 +398,7 @@ let LoopCallsInternal = {
} }
// This instance of CallProgressSocket should stay alive until the underlying // This instance of CallProgressSocket should stay alive until the underlying
// websocket is closed since it is passed to the websocket as the nsIWebSocketListener. // websocket is closed since it is passed to the websocket as the nsIWebSocketListener.
callProgress.connect(() => {callProgress.sendBusy();}); callProgress.connect(() => { callProgress.sendBusy(); });
} }
}; };
Object.freeze(LoopCallsInternal); Object.freeze(LoopCallsInternal);

View File

@ -288,7 +288,7 @@ const batch = function(operation, data, callback) {
} }
callback(null, processed); callback(null, processed);
}); });
} };
/** /**
* Extend a `target` object with the properties defined in `source`. * Extend a `target` object with the properties defined in `source`.

View File

@ -7,11 +7,13 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
const {MozLoopService, LOOP_SESSION_TYPE} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); const {MozLoopService, LOOP_SESSION_TYPE} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "Promise", XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm"); "resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task", XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
"resource://gre/modules/Task.jsm"); "resource://services-common/utils.js");
XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() { XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {}); const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
return new EventEmitter(); return new EventEmitter();
@ -19,8 +21,11 @@ XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
XPCOMUtils.defineLazyGetter(this, "gLoopBundle", function() { XPCOMUtils.defineLazyGetter(this, "gLoopBundle", function() {
return Services.strings.createBundle('chrome://browser/locale/loop/loop.properties'); return Services.strings.createBundle('chrome://browser/locale/loop/loop.properties');
}); });
XPCOMUtils.defineLazyModuleGetter(this, "LoopRoomsCache",
"resource:///modules/loop/LoopRoomsCache.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "loopUtils", XPCOMUtils.defineLazyModuleGetter(this, "loopUtils",
"resource:///modules/loop/utils.js", "utils") "resource:///modules/loop/utils.js", "utils");
XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto", XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto",
"resource:///modules/loop/crypto.js", "LoopCrypto"); "resource:///modules/loop/crypto.js", "LoopCrypto");
@ -41,6 +46,8 @@ const roomsPushNotification = function(version, channelID) {
let gDirty = true; let gDirty = true;
// Global variable that keeps track of the currently used account. // Global variable that keeps track of the currently used account.
let gCurrentUser = null; let gCurrentUser = null;
// Global variable that keeps track of the room cache.
let gRoomsCache = null;
/** /**
* Extend a `target` object with the properties defined in `source`. * Extend a `target` object with the properties defined in `source`.
@ -123,6 +130,13 @@ let LoopRoomsInternal = {
*/ */
rooms: new Map(), rooms: new Map(),
get roomsCache() {
if (!gRoomsCache) {
gRoomsCache = new LoopRoomsCache();
}
return gRoomsCache;
},
/** /**
* @var {String} sessionType The type of user session. May be 'FXA' or 'GUEST'. * @var {String} sessionType The type of user session. May be 'FXA' or 'GUEST'.
*/ */
@ -275,12 +289,40 @@ let LoopRoomsInternal = {
throw new Error("Missing wrappedKey"); throw new Error("Missing wrappedKey");
} }
// Bug 1152761 will cause us to additionally store keys locally. We'll let savedRoomKey = yield this.roomsCache.getKey(this.sessionType, roomData.roomToken);
// need to add some code for recovery in case decryption fails. let fallback = false;
let key = yield this.promiseDecryptRoomKey(roomData.context.wrappedKey); let key;
try {
key = yield this.promiseDecryptRoomKey(roomData.context.wrappedKey);
} catch (error) {
// If we don't have a key saved, then we can't do anything.
if (!savedRoomKey) {
throw error;
}
// We failed to decrypt the room key, so has our FxA key changed?
// If so, we fall-back to the saved room key.
key = savedRoomKey;
fallback = true;
}
let decryptedData = yield loopCrypto.decryptBytes(key, roomData.context.value); let decryptedData = yield loopCrypto.decryptBytes(key, roomData.context.value);
if (fallback) {
// Fallback decryption succeeded, so we need to re-encrypt the room key and
// save the data back again.
// XXX Bug 1152764 will implement this or make it a separate bug.
} else if (!savedRoomKey || key != savedRoomKey) {
// Decryption succeeded, but we don't have the right key saved.
try {
yield this.roomsCache.setKey(this.sessionType, roomData.roomToken, key);
}
catch (error) {
MozLoopService.log.error("Failed to save room key:", error);
}
}
roomData.roomKey = key; roomData.roomKey = key;
roomData.decryptedContext = JSON.parse(decryptedData); roomData.decryptedContext = JSON.parse(decryptedData);
@ -337,11 +379,11 @@ let LoopRoomsInternal = {
this.saveAndNotifyUpdate(roomData, isUpdate); this.saveAndNotifyUpdate(roomData, isUpdate);
} catch (error) { } catch (error) {
MozLoopService.log.error("Failed to decrypt room data: " + error); MozLoopService.log.error("Failed to decrypt room data: ", error);
// Do what we can to save the room data. // Do what we can to save the room data.
room.decryptedContext = {}; room.decryptedContext = {};
this.saveAndNotifyUpdate(room, isUpdate); this.saveAndNotifyUpdate(room, isUpdate);
}; }
} }
}), }),
@ -490,6 +532,9 @@ let LoopRoomsInternal = {
this.setGuestCreatedRoom(true); this.setGuestCreatedRoom(true);
} }
// Now we've got the room token, we can save the key to disk.
yield this.roomsCache.setKey(this.sessionType, room.roomToken, room.roomKey);
eventEmitter.emit("add", room); eventEmitter.emit("add", room);
callback(null, room); callback(null, room);
}.bind(this)).catch(callback); }.bind(this)).catch(callback);
@ -700,6 +745,10 @@ let LoopRoomsInternal = {
sendData = { sendData = {
roomName: newRoomName roomName: newRoomName
}; };
} else {
// This might be an upgrade to encrypted rename, so store the key
// just in case.
yield this.roomsCache.setKey(this.sessionType, all.roomToken, all.roomKey);
} }
let response = yield MozLoopService.hawkRequest(this.sessionType, let response = yield MozLoopService.hawkRequest(this.sessionType,
@ -727,8 +776,12 @@ let LoopRoomsInternal = {
return; return;
} }
let oldDirty = gDirty;
gDirty = true; gDirty = true;
this.getAll(version, () => {}); // If we were already dirty, then get the full set of rooms. For example,
// we'd already be dirty if we had started up but not got the list of rooms
// yet.
this.getAll(oldDirty ? null : version, () => {});
}, },
/** /**

View File

@ -0,0 +1,159 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
const {MozLoopService, LOOP_SESSION_TYPE} =
Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
"resource://services-common/utils.js");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
this.EXPORTED_SYMBOLS = ["LoopRoomsCache"];
const LOOP_ROOMS_CACHE_FILENAME = "loopRoomsCache.json";
/**
* RoomsCache is a cache for saving simple rooms data to the disk in case we
* need it for back-up purposes, e.g. recording room keys for FxA if the user
* changes their password.
*
* The format of the data is:
*
* {
* <sessionType>: {
* <roomToken>: {
* "key": <roomKey>
* }
* }
* }
*
* It is intended to try and keep the data forward and backwards compatible in
* a reasonable manner, hence why the structure is more complex than it needs
* to be to store tokens and keys.
*
* @param {Object} options The options for the RoomsCache, containing:
* - {String} baseDir The base directory in which to save the file.
* - {String} filename The filename for the cache file.
*/
function LoopRoomsCache(options) {
options = options || {};
this.baseDir = options.baseDir || OS.Constants.Path.profileDir;
this.path = OS.Path.join(
this.baseDir,
options.filename || LOOP_ROOMS_CACHE_FILENAME
);
this._cache = null;
}
LoopRoomsCache.prototype = {
/**
* Updates the local copy of the cache and saves it to disk.
*
* @param {Object} contents An object to be saved in json format.
* @return {Promise} A promise that is resolved once the save is complete.
*/
_setCache: function(contents) {
this._cache = contents;
return OS.File.makeDir(this.baseDir, {ignoreExisting: true}).then(() => {
return CommonUtils.writeJSON(contents, this.path);
});
},
/**
* Returns the local copy of the cache if there is one, otherwise it reads
* it from the disk.
*
* @return {Promise} A promise that is resolved once the read is complete.
*/
_getCache: Task.async(function* () {
if (this._cache) {
return this._cache;
}
try {
return (this._cache = yield CommonUtils.readJSON(this.path));
} catch(error) {
// This is really complex due to OSFile's error handling, see bug 1160109.
if ((OS.Constants.libc && error.unixErrno != OS.Constants.libc.ENOENT) ||
(OS.Constants.Win && error.winLastError != OS.Constants.Win.ERROR_FILE_NOT_FOUND)) {
MozLoopService.log.debug("Error reading the cache:", error);
}
return (this._cache = {});
}
}),
/**
* Function for testability purposes. Clears the cache.
*
* @return {Promise} A promise that is resolved once the clear is complete.
*/
clear: function() {
this._cache = null;
return OS.File.remove(this.path);
},
/**
* Gets a room key from the cache.
*
* @param {LOOP_SESSION_TYPE} sessionType The session type for the room.
* @param {String} roomToken The token for the room.
* @return {Promise} A promise that is resolved when the data has been read
* with the value of the key, or null if it isn't present.
*/
getKey: Task.async(function* (sessionType, roomToken) {
if (sessionType != LOOP_SESSION_TYPE.FXA) {
return null;
}
let sessionData = (yield this._getCache())[sessionType];
if (!sessionData || !sessionData[roomToken]) {
return null;
}
return sessionData[roomToken].key;
}),
/**
* Stores a room key into the cache. Note, if the key has not changed,
* the store will not be re-written.
*
* @param {LOOP_SESSION_TYPE} sessionType The session type for the room.
* @param {String} roomToken The token for the room.
* @param {String} roomKey The encryption key for the room.
* @return {Promise} A promise that is resolved when the data has been stored.
*/
setKey: Task.async(function* (sessionType, roomToken, roomKey) {
if (sessionType != LOOP_SESSION_TYPE.FXA) {
return;
}
let cache = yield this._getCache();
// Create these objects if they don't exist.
// We aim to do this creation and setting of the room key in a
// forwards-compatible way so that if new fields are added to rooms later
// then we don't mess them up (if there's no keys).
if (!cache[sessionType]) {
cache[sessionType] = {};
}
if (!cache[sessionType][roomToken]) {
cache[sessionType][roomToken] = {};
}
// Only save it if there's no key, or it is different.
if (!cache[sessionType][roomToken].key ||
cache[sessionType][roomToken].key != roomKey) {
cache[sessionType][roomToken].key = roomKey;
return yield this._setCache(cache);
}
})
};

View File

@ -10,7 +10,7 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Timer.jsm"); Cu.import("resource://gre/modules/Timer.jsm");
const {MozLoopService} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); const { MozLoopService } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
const consoleLog = MozLoopService.log; const consoleLog = MozLoopService.log;
this.EXPORTED_SYMBOLS = ["MozLoopPushHandler"]; this.EXPORTED_SYMBOLS = ["MozLoopPushHandler"];
@ -296,7 +296,7 @@ PingMonitor.prototype = {
restart: function () { restart: function () {
consoleLog.info("PushHandler: ping timeout restart"); consoleLog.info("PushHandler: ping timeout restart");
this.stop(); this.stop();
this._pingTimerID = setTimeout(() => {this._pingSend()}, this._pingInterval); this._pingTimerID = setTimeout(() => { this._pingSend(); }, this._pingInterval);
}, },
/** /**
@ -503,7 +503,7 @@ let MozLoopPushHandler = {
this._channelsToRegister.push(channelID); this._channelsToRegister.push(channelID);
this._registerChannels(); this._registerChannels();
}, },
/** /**
* Un-register a notification channel. * Un-register a notification channel.
* *
@ -771,14 +771,14 @@ let MozLoopPushHandler = {
(aMsg) => this._onMsg(aMsg), (aMsg) => this._onMsg(aMsg),
() => this._onStart(), () => this._onStart(),
(aCode, aReason) => this._onClose(aCode, aReason)); (aCode, aReason) => this._onClose(aCode, aReason));
} };
let pushServerURLFetchError = () => { let pushServerURLFetchError = () => {
consoleLog.warn("PushHandler: Could not retrieve push server URL from Loop server, will retry"); consoleLog.warn("PushHandler: Could not retrieve push server URL from Loop server, will retry");
this._pushSocket = undefined; this._pushSocket = undefined;
this._retryManager.retry(() => this._openSocket()); this._retryManager.retry(() => this._openSocket());
return; return;
} };
try { try {
this.pushServerUri = Services.prefs.getCharPref("loop.debug.pushserver"); this.pushServerUri = Services.prefs.getCharPref("loop.debug.pushserver");
@ -871,4 +871,4 @@ let MozLoopPushHandler = {
channelID: channelID}); channelID: channelID});
} }
}, },
} };

View File

@ -64,7 +64,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI",
XPCOMUtils.defineLazyModuleGetter(this, "convertToRTCStatsReport", XPCOMUtils.defineLazyModuleGetter(this, "convertToRTCStatsReport",
"resource://gre/modules/media/RTCStatsReport.jsm"); "resource://gre/modules/media/RTCStatsReport.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "loopUtils", XPCOMUtils.defineLazyModuleGetter(this, "loopUtils",
"resource:///modules/loop/utils.js", "utils") "resource:///modules/loop/utils.js", "utils");
XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto", XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto",
"resource:///modules/loop/crypto.js", "LoopCrypto"); "resource:///modules/loop/crypto.js", "LoopCrypto");
@ -170,12 +170,12 @@ let MozLoopServiceInternal = {
deferredRegistrations: new Map(), deferredRegistrations: new Map(),
get pushHandler() { get pushHandler() {
return this.mocks.pushHandler || MozLoopPushHandler return this.mocks.pushHandler || MozLoopPushHandler;
}, },
// The uri of the Loop server. // The uri of the Loop server.
get loopServerUri() { get loopServerUri() {
return Services.prefs.getCharPref("loop.server") return Services.prefs.getCharPref("loop.server");
}, },
/** /**
@ -365,7 +365,7 @@ let MozLoopServiceInternal = {
} else { } else {
resolve(this.registerWithLoopServer(sessionType, serviceType, pushURL)); resolve(this.registerWithLoopServer(sessionType, serviceType, pushURL));
} }
} };
this.pushHandler.register(channelID, onRegistered, onNotification); this.pushHandler.register(channelID, onRegistered, onNotification);
}); });
@ -443,7 +443,7 @@ let MozLoopServiceInternal = {
// Create a blank URL record set if none exists for this sessionType. // Create a blank URL record set if none exists for this sessionType.
if (!pushURLs) { if (!pushURLs) {
pushURLs = {calls: undefined, rooms: undefined}; pushURLs = { calls: undefined, rooms: undefined };
this.pushURLs.set(sessionType, pushURLs); this.pushURLs.set(sessionType, pushURLs);
} }
@ -456,7 +456,7 @@ let MozLoopServiceInternal = {
newURLs[serviceType] = pushURL; newURLs[serviceType] = pushURL;
return this.hawkRequestInternal(sessionType, "/registration", "POST", return this.hawkRequestInternal(sessionType, "/registration", "POST",
{simplePushURLs: newURLs}).then( { simplePushURLs: newURLs }).then(
(response) => { (response) => {
// If this failed we got an invalid token. // If this failed we got an invalid token.
if (!this.storeSessionToken(sessionType, response.headers)) { if (!this.storeSessionToken(sessionType, response.headers)) {
@ -533,7 +533,7 @@ let MozLoopServiceInternal = {
log.error("Failed to unregister with the loop server. Error: ", error); log.error("Failed to unregister with the loop server. Error: ", error);
throw error; throw error;
}); });
} };
return Promise.all([unregister(sessionType, callsPushURL), unregister(sessionType, roomsPushURL)]); return Promise.all([unregister(sessionType, callsPushURL), unregister(sessionType, roomsPushURL)]);
}, },
@ -584,7 +584,7 @@ let MozLoopServiceInternal = {
} else { } else {
newPayloadObj[property] = payloadObj[property]; newPayloadObj[property] = payloadObj[property];
} }
}; }
payloadObj = newPayloadObj; payloadObj = newPayloadObj;
} }
@ -804,7 +804,7 @@ let MozLoopServiceInternal = {
log.info(e.data.ok ? log.info(e.data.ok ?
"Successfully staged loop report for telemetry upload." : "Successfully staged loop report for telemetry upload." :
("Failed to stage loop report. Error: " + e.data.fail)); ("Failed to stage loop report. Error: " + e.data.fail));
} };
worker.postMessage(job); worker.postMessage(job);
}); });
}, pc.id); }, pc.id);
@ -942,7 +942,7 @@ let MozLoopServiceInternal = {
return JSON.parse(response.body); return JSON.parse(response.body);
}, },
error => {this._hawkRequestError(error);}); error => { this._hawkRequestError(error); });
}, },
/** /**
@ -1025,7 +1025,7 @@ let MozLoopServiceInternal = {
return this.hawkRequestInternal(LOOP_SESSION_TYPE.FXA, "/fxa-oauth/token", "POST", payload).then(response => { return this.hawkRequestInternal(LOOP_SESSION_TYPE.FXA, "/fxa-oauth/token", "POST", payload).then(response => {
return JSON.parse(response.body); return JSON.parse(response.body);
}, },
error => {this._hawkRequestError(error);}); error => { this._hawkRequestError(error); });
}, },
/** /**
@ -1689,7 +1689,7 @@ this.MozLoopService = {
*/ */
hawkRequest: function(sessionType, path, method, payloadObj) { hawkRequest: function(sessionType, path, method, payloadObj) {
return MozLoopServiceInternal.hawkRequest(sessionType, path, method, payloadObj).catch( return MozLoopServiceInternal.hawkRequest(sessionType, path, method, payloadObj).catch(
error => {MozLoopServiceInternal._hawkRequestError(error);}); error => { MozLoopServiceInternal._hawkRequestError(error); });
}, },
/** /**

View File

@ -20,6 +20,7 @@ EXTRA_JS_MODULES.loop += [
'modules/LoopCalls.jsm', 'modules/LoopCalls.jsm',
'modules/LoopContacts.jsm', 'modules/LoopContacts.jsm',
'modules/LoopRooms.jsm', 'modules/LoopRooms.jsm',
'modules/LoopRoomsCache.jsm',
'modules/LoopStorage.jsm', 'modules/LoopStorage.jsm',
'modules/MozLoopAPI.jsm', 'modules/MozLoopAPI.jsm',
'modules/MozLoopPushHandler.jsm', 'modules/MozLoopPushHandler.jsm',

View File

@ -58,7 +58,7 @@ loop.standaloneMedia = (function() {
if (typeof cb == "function") { if (typeof cb == "function") {
cb(param); cb(param);
} }
}) });
} }
function handleSuccess(localStream) { function handleSuccess(localStream) {
this.userMedia.pending = false; this.userMedia.pending = false;
@ -134,7 +134,7 @@ loop.standaloneMedia = (function() {
// This function is needed to pull in the instance // This function is needed to pull in the instance
// of the singleton for tests to overwrite the used instance. // of the singleton for tests to overwrite the used instance.
singletonMultiplexGum.getPermsAndCacheMedia.apply(singletonMultiplexGum, arguments); singletonMultiplexGum.getPermsAndCacheMedia.apply(singletonMultiplexGum, arguments);
}; }
patchSymbolIfExtant("navigator", "mozGetUserMedia", myGetUserMedia); patchSymbolIfExtant("navigator", "mozGetUserMedia", myGetUserMedia);
patchSymbolIfExtant("navigator", "webkitGetUserMedia", myGetUserMedia); patchSymbolIfExtant("navigator", "webkitGetUserMedia", myGetUserMedia);
patchSymbolIfExtant("navigator", "getUserMedia", myGetUserMedia); patchSymbolIfExtant("navigator", "getUserMedia", myGetUserMedia);

View File

@ -36,7 +36,7 @@ loop.store.StandaloneMetricsStore = (function() {
pageLoad: "page load messages", pageLoad: "page load messages",
success: "success", success: "success",
support: "support link click" support: "support link click"
} };
var StandaloneMetricsStore = loop.store.createStore({ var StandaloneMetricsStore = loop.store.createStore({
actions: [ actions: [
@ -132,7 +132,7 @@ loop.store.StandaloneMetricsStore = (function() {
*/ */
mediaConnected: function() { mediaConnected: function() {
this._storeEvent(METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.success, this._storeEvent(METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.success,
"Media connected") "Media connected");
}, },
/** /**

View File

@ -215,7 +215,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
if (event.target && event.target.href) { if (event.target && event.target.href) {
this.props.dispatcher.dispatch(new sharedActions.RecordClick({ this.props.dispatcher.dispatch(new sharedActions.RecordClick({
linkInfo: event.target.href linkInfo: event.target.href
})) }));
} }
}, },
@ -288,7 +288,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
getInitialState: function() { getInitialState: function() {
return { return {
failureLogged: false failureLogged: false
} };
}, },
_logFailure: function(message) { _logFailure: function(message) {

View File

@ -215,7 +215,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
if (event.target && event.target.href) { if (event.target && event.target.href) {
this.props.dispatcher.dispatch(new sharedActions.RecordClick({ this.props.dispatcher.dispatch(new sharedActions.RecordClick({
linkInfo: event.target.href linkInfo: event.target.href
})) }));
} }
}, },
@ -288,7 +288,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
getInitialState: function() { getInitialState: function() {
return { return {
failureLogged: false failureLogged: false
} };
}, },
_logFailure: function(message) { _logFailure: function(message) {

View File

@ -680,6 +680,6 @@ describe("loop.roomViews", function () {
React.addons.TestUtils.Simulate.click(closeBtn); React.addons.TestUtils.Simulate.click(closeBtn);
expect(view.getDOMNode()).to.eql(null); expect(view.getDOMNode()).to.eql(null);
}); });
}) });
}); });
}); });

View File

@ -9,7 +9,7 @@ const kAuth = {
"method": "basic", "method": "basic",
"user": "username", "user": "username",
"password": "p455w0rd" "password": "p455w0rd"
} };
// "pid" for "provider ID" // "pid" for "provider ID"
@ -166,7 +166,7 @@ const monkeyPatchImporter = function(importer) {
}); });
}.bind(importer); }.bind(importer);
return importer; return importer;
} };
add_task(function* test_CardDavImport() { add_task(function* test_CardDavImport() {
let importer = monkeyPatchImporter(new CardDavImporter()); let importer = monkeyPatchImporter(new CardDavImporter());
@ -323,4 +323,4 @@ add_task(function* test_CardDavImport() {
}, (err, result) => { err ? resolve(err) : reject(new Error("Should have failed")); }, mockDb); }, (err, result) => { err ? resolve(err) : reject(new Error("Should have failed")); }, mockDb);
}); });
Assert.equal(error.message, "No authentication specified", "Missing parameters should generate error"); Assert.equal(error.message, "No authentication specified", "Missing parameters should generate error");
}) });

View File

@ -106,7 +106,7 @@ const normalizeContact = function(contact) {
// Get a copy of contact without private properties. // Get a copy of contact without private properties.
for (let prop of Object.getOwnPropertyNames(contact)) { for (let prop of Object.getOwnPropertyNames(contact)) {
if (!prop.startsWith("_")) { if (!prop.startsWith("_")) {
result[prop] = contact[prop] result[prop] = contact[prop];
} }
} }
return result; return result;
@ -189,7 +189,7 @@ add_task(function* () {
Assert.ok(!err, "There shouldn't be an error"); Assert.ok(!err, "There shouldn't be an error");
Assert.equal(found.length, 0, "There shouldn't be any contacts left"); Assert.equal(found.length, 0, "There shouldn't be any contacts left");
resolve(); resolve();
}) });
}); });
}); });
}); });

View File

@ -33,7 +33,7 @@ function promiseWindowIdReceivedOnAdd(handler) {
handler.resolve = resolve; handler.resolve = resolve;
gMozLoopAPI.addBrowserSharingListener(handler.listener); gMozLoopAPI.addBrowserSharingListener(handler.listener);
}); });
}; }
let createdTabs = []; let createdTabs = [];
@ -52,7 +52,7 @@ function promiseWindowIdReceivedNewTab(handlers = []) {
promiseHandlers.push(promiseTabLoadEvent(createdTab, "about:mozilla")); promiseHandlers.push(promiseTabLoadEvent(createdTab, "about:mozilla"));
return Promise.all(promiseHandlers); return Promise.all(promiseHandlers);
}; }
function promiseRemoveTab(tab) { function promiseRemoveTab(tab) {
return new Promise(resolve => { return new Promise(resolve => {
@ -170,7 +170,7 @@ add_task(function* test_infoBar() {
"The popup should be opening anchored to the dropmarker"); "The popup should be opening anchored to the dropmarker");
Assert.strictEqual(button.getElementsByTagNameNS(kNSXUL, "menupopup").length, 1, Assert.strictEqual(button.getElementsByTagNameNS(kNSXUL, "menupopup").length, 1,
"There should be a popup attached to the button"); "There should be a popup attached to the button");
} };
testBarProps(); testBarProps();

View File

@ -19,9 +19,9 @@ describe("loop.OTSdkDriver", function () {
beforeEach(function() { beforeEach(function() {
sandbox = sinon.sandbox.create(); sandbox = sinon.sandbox.create();
fakeLocalElement = {fake: 1}; fakeLocalElement = { fake: 1 };
fakeRemoteElement = {fake: 2}; fakeRemoteElement = { fake: 2 };
fakeScreenElement = {fake: 3}; fakeScreenElement = { fake: 3 };
fakeEvent = { fakeEvent = {
preventDefault: sinon.stub() preventDefault: sinon.stub()
}; };
@ -98,7 +98,7 @@ describe("loop.OTSdkDriver", function () {
describe("Constructor", function() { describe("Constructor", function() {
it("should throw an error if the dispatcher is missing", function() { it("should throw an error if the dispatcher is missing", function() {
expect(function() { expect(function() {
new loop.OTSdkDriver({sdk: sdk}); new loop.OTSdkDriver({ sdk: sdk });
}).to.Throw(/dispatcher/); }).to.Throw(/dispatcher/);
}); });
@ -112,8 +112,8 @@ describe("loop.OTSdkDriver", function () {
describe("#setupStreamElements", function() { describe("#setupStreamElements", function() {
it("should call initPublisher", function() { it("should call initPublisher", function() {
driver.setupStreamElements(new sharedActions.SetupStreamElements({ driver.setupStreamElements(new sharedActions.SetupStreamElements({
getLocalElementFunc: function() {return fakeLocalElement;}, getLocalElementFunc: function() { return fakeLocalElement; },
getRemoteElementFunc: function() {return fakeRemoteElement;}, getRemoteElementFunc: function() { return fakeRemoteElement; },
publisherConfig: publisherConfig publisherConfig: publisherConfig
})); }));
@ -127,8 +127,8 @@ describe("loop.OTSdkDriver", function () {
sdk.initPublisher.returns(publisher); sdk.initPublisher.returns(publisher);
driver.setupStreamElements(new sharedActions.SetupStreamElements({ driver.setupStreamElements(new sharedActions.SetupStreamElements({
getLocalElementFunc: function() {return fakeLocalElement;}, getLocalElementFunc: function() { return fakeLocalElement; },
getRemoteElementFunc: function() {return fakeRemoteElement;}, getRemoteElementFunc: function() { return fakeRemoteElement; },
publisherConfig: publisherConfig publisherConfig: publisherConfig
})); }));
}); });
@ -158,8 +158,8 @@ describe("loop.OTSdkDriver", function () {
sdk.initPublisher.returns(publisher); sdk.initPublisher.returns(publisher);
driver.setupStreamElements(new sharedActions.SetupStreamElements({ driver.setupStreamElements(new sharedActions.SetupStreamElements({
getLocalElementFunc: function() {return fakeLocalElement;}, getLocalElementFunc: function() { return fakeLocalElement; },
getRemoteElementFunc: function() {return fakeRemoteElement;}, getRemoteElementFunc: function() { return fakeRemoteElement; },
publisherConfig: publisherConfig publisherConfig: publisherConfig
})); }));
}); });
@ -604,9 +604,9 @@ describe("loop.OTSdkDriver", function () {
driver.connectSession(sessionData); driver.connectSession(sessionData);
driver.setupStreamElements(new sharedActions.SetupStreamElements({ driver.setupStreamElements(new sharedActions.SetupStreamElements({
getLocalElementFunc: function() {return fakeLocalElement;}, getLocalElementFunc: function() {return fakeLocalElement; },
getScreenShareElementFunc: function() {return fakeScreenElement;}, getScreenShareElementFunc: function() {return fakeScreenElement; },
getRemoteElementFunc: function() {return fakeRemoteElement;}, getRemoteElementFunc: function() {return fakeRemoteElement; },
publisherConfig: publisherConfig publisherConfig: publisherConfig
})); }));
}); });
@ -732,7 +732,7 @@ describe("loop.OTSdkDriver", function () {
}); });
it("should dispatch a VideoDimensionsChanged action", function() { it("should dispatch a VideoDimensionsChanged action", function() {
publisher.trigger("streamCreated", {stream: fakeStream}); publisher.trigger("streamCreated", { stream: fakeStream });
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch, sinon.assert.calledWithExactly(dispatcher.dispatch,
@ -773,21 +773,21 @@ describe("loop.OTSdkDriver", function () {
}); });
it("should dispatch a VideoDimensionsChanged action", function() { it("should dispatch a VideoDimensionsChanged action", function() {
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch, sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.VideoDimensionsChanged({ new sharedActions.VideoDimensionsChanged({
isLocal: false, isLocal: false,
videoType: "camera", videoType: "camera",
dimensions: {width: 1, height: 2} dimensions: { width: 1, height: 2 }
})); }));
}); });
it("should dispatch a ConnectionStatus action", function() { it("should dispatch a ConnectionStatus action", function() {
driver._metrics.connections = 1; driver._metrics.connections = 1;
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch, sinon.assert.calledWithExactly(dispatcher.dispatch,
@ -801,7 +801,7 @@ describe("loop.OTSdkDriver", function () {
}); });
it("should subscribe to a camera stream", function() { it("should subscribe to a camera stream", function() {
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
sinon.assert.calledOnce(session.subscribe); sinon.assert.calledOnce(session.subscribe);
sinon.assert.calledWithExactly(session.subscribe, sinon.assert.calledWithExactly(session.subscribe,
@ -811,7 +811,7 @@ describe("loop.OTSdkDriver", function () {
it("should subscribe to a screen sharing stream", function() { it("should subscribe to a screen sharing stream", function() {
fakeStream.videoType = "screen"; fakeStream.videoType = "screen";
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
sinon.assert.calledOnce(session.subscribe); sinon.assert.calledOnce(session.subscribe);
sinon.assert.calledWithExactly(session.subscribe, sinon.assert.calledWithExactly(session.subscribe,
@ -821,7 +821,7 @@ describe("loop.OTSdkDriver", function () {
it("should dispatch a mediaConnected action if both streams are up", function() { it("should dispatch a mediaConnected action if both streams are up", function() {
driver._publishedLocalStream = true; driver._publishedLocalStream = true;
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
// Called twice due to the VideoDimensionsChanged above. // Called twice due to the VideoDimensionsChanged above.
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
@ -836,19 +836,19 @@ describe("loop.OTSdkDriver", function () {
var startTime = 1; var startTime = 1;
sandbox.stub(performance, "now").returns(startTime); sandbox.stub(performance, "now").returns(startTime);
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
expect(driver._getTwoWayMediaStartTime()).to.eql(startTime); expect(driver._getTwoWayMediaStartTime()).to.eql(startTime);
}); });
it("should not store the start time when both streams are up and" + it("should not store the start time when both streams are up and" +
" driver._isDesktop is false", function() { " driver._isDesktop is false", function() {
driver._isDesktop = false ; driver._isDesktop = false;
driver._publishedLocalStream = true; driver._publishedLocalStream = true;
var startTime = 73; var startTime = 73;
sandbox.stub(performance, "now").returns(startTime); sandbox.stub(performance, "now").returns(startTime);
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
expect(driver._getTwoWayMediaStartTime()).to.not.eql(startTime); expect(driver._getTwoWayMediaStartTime()).to.not.eql(startTime);
}); });
@ -859,7 +859,7 @@ describe("loop.OTSdkDriver", function () {
driver._publishedLocalStream = true; driver._publishedLocalStream = true;
fakeStream.videoType = "screen"; fakeStream.videoType = "screen";
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
sinon.assert.neverCalledWithMatch(dispatcher.dispatch, sinon.assert.neverCalledWithMatch(dispatcher.dispatch,
sinon.match.hasOwn("name", "mediaConnected")); sinon.match.hasOwn("name", "mediaConnected"));
@ -877,12 +877,12 @@ describe("loop.OTSdkDriver", function () {
function() { function() {
fakeStream.videoType = "screen"; fakeStream.videoType = "screen";
session.trigger("streamCreated", {stream: fakeStream}); session.trigger("streamCreated", { stream: fakeStream });
// Called twice due to the VideoDimensionsChanged above. // Called twice due to the VideoDimensionsChanged above.
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch, sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ReceivingScreenShare({receiving: true})); new sharedActions.ReceivingScreenShare({ receiving: true }));
}); });
}); });
@ -916,7 +916,7 @@ describe("loop.OTSdkDriver", function () {
}); });
it("should dispatch a ReceivingScreenShare action", function() { it("should dispatch a ReceivingScreenShare action", function() {
session.trigger("streamDestroyed", {stream: fakeStream}); session.trigger("streamDestroyed", { stream: fakeStream });
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch, sinon.assert.calledWithExactly(dispatcher.dispatch,
@ -946,7 +946,7 @@ describe("loop.OTSdkDriver", function () {
it("should not dispatch an action if the videoType is camera", function() { it("should not dispatch an action if the videoType is camera", function() {
fakeStream.videoType = "camera"; fakeStream.videoType = "camera";
session.trigger("streamDestroyed", {stream: fakeStream}); session.trigger("streamDestroyed", { stream: fakeStream });
sinon.assert.neverCalledWithMatch(dispatcher.dispatch, sinon.assert.neverCalledWithMatch(dispatcher.dispatch,
sinon.match.hasOwn("name", "receivingScreenShare")); sinon.match.hasOwn("name", "receivingScreenShare"));
@ -1001,7 +1001,7 @@ describe("loop.OTSdkDriver", function () {
it("should dispatch a RemotePeerConnected action if this is for a remote user", it("should dispatch a RemotePeerConnected action if this is for a remote user",
function() { function() {
session.trigger("connectionCreated", { session.trigger("connectionCreated", {
connection: {id: "remoteUser"} connection: { id: "remoteUser" }
}); });
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
@ -1011,7 +1011,7 @@ describe("loop.OTSdkDriver", function () {
it("should store the connection details for a remote user", function() { it("should store the connection details for a remote user", function() {
session.trigger("connectionCreated", { session.trigger("connectionCreated", {
connection: {id: "remoteUser"} connection: { id: "remoteUser" }
}); });
expect(driver.connections).to.include.keys("remoteUser"); expect(driver.connections).to.include.keys("remoteUser");
@ -1022,7 +1022,7 @@ describe("loop.OTSdkDriver", function () {
driver._metrics.sendStreams = 1; driver._metrics.sendStreams = 1;
session.trigger("connectionCreated", { session.trigger("connectionCreated", {
connection: {id: "remoteUser"} connection: { id: "remoteUser" }
}); });
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);
@ -1039,7 +1039,7 @@ describe("loop.OTSdkDriver", function () {
it("should not dispatch an RemotePeerConnected action if this is for a local user", it("should not dispatch an RemotePeerConnected action if this is for a local user",
function() { function() {
session.trigger("connectionCreated", { session.trigger("connectionCreated", {
connection: {id: "localUser"} connection: { id: "localUser" }
}); });
sinon.assert.neverCalledWithMatch(dispatcher.dispatch, sinon.assert.neverCalledWithMatch(dispatcher.dispatch,
@ -1048,7 +1048,7 @@ describe("loop.OTSdkDriver", function () {
it("should not store the connection details for a local user", function() { it("should not store the connection details for a local user", function() {
session.trigger("connectionCreated", { session.trigger("connectionCreated", {
connection: {id: "localUser"} connection: { id: "localUser" }
}); });
expect(driver.connections).to.not.include.keys("localUser"); expect(driver.connections).to.not.include.keys("localUser");
@ -1059,7 +1059,7 @@ describe("loop.OTSdkDriver", function () {
driver._metrics.sendStreams = 0; driver._metrics.sendStreams = 0;
session.trigger("connectionCreated", { session.trigger("connectionCreated", {
connection: {id: "localUser"} connection: { id: "localUser" }
}); });
sinon.assert.called(dispatcher.dispatch); sinon.assert.called(dispatcher.dispatch);

View File

@ -92,7 +92,7 @@ describe("loop.store.StandaloneMetricsStore", function() {
sinon.assert.calledWithExactly(window.ga, sinon.assert.calledWithExactly(window.ga,
"send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.linkClick, "send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.linkClick,
"fake"); "fake");
}) });
}); });
describe("Store Change Handlers", function() { describe("Store Change Handlers", function() {

View File

@ -249,7 +249,7 @@ describe("loop.standaloneRoomViews", function() {
local: {}, local: {},
remote: {} remote: {}
}); });
}) });
}); });
describe("#publishStream", function() { describe("#publishStream", function() {

View File

@ -94,7 +94,7 @@ describe("loop.StandaloneClient", function() {
sinon.assert.calledWithExactly(console.error, "Server error", sinon.assert.calledWithExactly(console.error, "Server error",
"HTTP 404 Not Found", serverResponse); "HTTP 404 Not Found", serverResponse);
}); });
}) });
}); });

View File

@ -5,6 +5,9 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
// Initialize this before the imports, as some of them need it.
do_get_profile();
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Http.jsm"); Cu.import("resource://gre/modules/Http.jsm");
@ -13,7 +16,9 @@ Cu.import("resource:///modules/loop/MozLoopService.jsm");
Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource:///modules/loop/LoopCalls.jsm"); Cu.import("resource:///modules/loop/LoopCalls.jsm");
Cu.import("resource:///modules/loop/LoopRooms.jsm"); Cu.import("resource:///modules/loop/LoopRooms.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
const { LoopRoomsInternal } = Cu.import("resource:///modules/loop/LoopRooms.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler",
"resource:///modules/loop/MozLoopPushHandler.jsm"); "resource:///modules/loop/MozLoopPushHandler.jsm");
@ -135,7 +140,7 @@ let mockPushHandler = {
* enables us to check parameters and return messages similar to the push * enables us to check parameters and return messages similar to the push
* server. * server.
*/ */
function MockWebSocketChannel() {}; function MockWebSocketChannel() {}
MockWebSocketChannel.prototype = { MockWebSocketChannel.prototype = {
QueryInterface: XPCOMUtils.generateQI(Ci.nsIWebSocketChannel), QueryInterface: XPCOMUtils.generateQI(Ci.nsIWebSocketChannel),
@ -211,3 +216,10 @@ MockWebSocketChannel.prototype = {
this.listener.onServerClose(this.context, err || -1); this.listener.onServerClose(this.context, err || -1);
}, },
}; };
const extend = function(target, source) {
for (let key of Object.getOwnPropertyNames(source)) {
target[key] = source[key];
}
return target;
};

View File

@ -33,7 +33,7 @@ function generateSessionTypeVerificationStub(desiredSessionType) {
resolve(); resolve();
}); });
}; }
return hawkRequestStub; return hawkRequestStub;
} }

View File

@ -130,10 +130,10 @@ add_test(function test_ping_websocket() {
mockWebSocket.defaultMsgHandler = (msg) => { mockWebSocket.defaultMsgHandler = (msg) => {
pingReceived = true; pingReceived = true;
// Do not send a ping response. // Do not send a ping response.
} };
mockWebSocket.close = () => { mockWebSocket.close = () => {
socketClosed = true; socketClosed = true;
} };
MozLoopPushHandler.shutdown(); MozLoopPushHandler.shutdown();
MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket}); MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket});
@ -220,4 +220,4 @@ function run_test() {
}); });
run_next_test(); run_next_test();
}; }

View File

@ -182,13 +182,6 @@ const kCreateRoomData = {
const kChannelGuest = MozLoopService.channelIDs.roomsGuest; const kChannelGuest = MozLoopService.channelIDs.roomsGuest;
const kChannelFxA = MozLoopService.channelIDs.roomsFxA; const kChannelFxA = MozLoopService.channelIDs.roomsFxA;
const extend = function(target, source) {
for (let key of Object.getOwnPropertyNames(source)) {
target[key] = source[key];
}
return target;
};
const normalizeRoom = function(room) { const normalizeRoom = function(room) {
let newRoom = extend({}, room); let newRoom = extend({}, room);
let name = newRoom.decryptedContext.roomName; let name = newRoom.decryptedContext.roomName;
@ -470,33 +463,38 @@ add_task(function* test_roomUpdates() {
"781f012b-f1ea-4ce1-9105-7cfc36fb4ec7" "781f012b-f1ea-4ce1-9105-7cfc36fb4ec7"
]; ];
roomsPushNotification("1", kChannelGuest); roomsPushNotification("1", kChannelGuest);
yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedLeaves).length === 0); yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedLeaves).length === 0 &&
gExpectedUpdates.length === 0);
gExpectedUpdates.push("_nxD4V4FflQ"); gExpectedUpdates.push("_nxD4V4FflQ");
gExpectedJoins["_nxD4V4FflQ"] = ["2a1787a6-4a73-43b5-ae3e-906ec1e763cb"]; gExpectedJoins["_nxD4V4FflQ"] = ["2a1787a6-4a73-43b5-ae3e-906ec1e763cb"];
roomsPushNotification("2", kChannelGuest); roomsPushNotification("2", kChannelGuest);
yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedJoins).length === 0); yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedJoins).length === 0 &&
gExpectedUpdates.length === 0);
gExpectedUpdates.push("_nxD4V4FflQ"); gExpectedUpdates.push("_nxD4V4FflQ");
gExpectedJoins["_nxD4V4FflQ"] = ["781f012b-f1ea-4ce1-9105-7cfc36fb4ec7"]; gExpectedJoins["_nxD4V4FflQ"] = ["781f012b-f1ea-4ce1-9105-7cfc36fb4ec7"];
gExpectedLeaves["_nxD4V4FflQ"] = ["2a1787a6-4a73-43b5-ae3e-906ec1e763cb"]; gExpectedLeaves["_nxD4V4FflQ"] = ["2a1787a6-4a73-43b5-ae3e-906ec1e763cb"];
roomsPushNotification("3", kChannelGuest); roomsPushNotification("3", kChannelGuest);
yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedLeaves).length === 0); yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedLeaves).length === 0 &&
Object.getOwnPropertyNames(gExpectedJoins).length === 0 &&
gExpectedUpdates.length === 0);
gExpectedUpdates.push("_nxD4V4FflQ"); gExpectedUpdates.push("_nxD4V4FflQ");
gExpectedJoins["_nxD4V4FflQ"] = [ gExpectedJoins["_nxD4V4FflQ"] = [
"2a1787a6-4a73-43b5-ae3e-906ec1e763cb", "2a1787a6-4a73-43b5-ae3e-906ec1e763cb",
"5de6281c-6568-455f-af08-c0b0a973100e"]; "5de6281c-6568-455f-af08-c0b0a973100e"];
roomsPushNotification("4", kChannelGuest); roomsPushNotification("4", kChannelGuest);
yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedJoins).length === 0); yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedJoins).length === 0 &&
gExpectedUpdates.length === 0);
}); });
// Test if push updates' channelIDs are respected. // Test if push updates' channelIDs are respected.
add_task(function* () { add_task(function* test_channelIdsRespected() {
function badRoomJoin() { function badRoomJoin() {
Assert.ok(false, "Unexpected 'joined' event emitted!"); Assert.ok(false, "Unexpected 'joined' event emitted!");
} }
LoopRooms.on("join", onRoomLeft); LoopRooms.on("join", badRoomJoin);
roomsPushNotification("4", kChannelFxA); roomsPushNotification("4", kChannelFxA);
LoopRooms.off("join", badRoomJoin); LoopRooms.off("join", badRoomJoin);
@ -510,7 +508,8 @@ add_task(function* () {
"5de6281c-6568-455f-af08-c0b0a973100e" "5de6281c-6568-455f-af08-c0b0a973100e"
]; ];
roomsPushNotification("3", kChannelFxA); roomsPushNotification("3", kChannelFxA);
yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedLeaves).length === 0); yield waitForCondition(() => Object.getOwnPropertyNames(gExpectedLeaves).length === 0 &&
gExpectedUpdates.length === 0);
}); });
// Test if joining a room as Guest works as expected. // Test if joining a room as Guest works as expected.

View File

@ -0,0 +1,269 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
Cu.import("resource://services-common/utils.js");
const { LOOP_ROOMS_CACHE_FILENAME } = Cu.import("resource:///modules/loop/LoopRoomsCache.jsm", {});
const kContextEnabledPref = "loop.contextInConverations.enabled";
const kFxAKey = "uGIs-kGbYt1hBBwjyW7MLQ";
// Rooms details as responded by the server.
const kRoomsResponses = new Map([
["_nxD4V4FflQ", {
// Encrypted with roomKey "FliIGLUolW-xkKZVWstqKw".
// roomKey is wrapped with kFxAKey.
context: {
wrappedKey: "F3V27oPB+FgjFbVPML2PupONYqoIZ53XRU4BqG46Lr3eyIGumgCEqgjSe/MXAXiQ//8=",
value: "df7B4SNxhOI44eJjQavCevADyCCxz6/DEZbkOkRUMVUxzS42FbzN6C2PqmCKDYUGyCJTwJ0jln8TLw==",
alg: "AES-GCM"
},
roomToken: "_nxD4V4FflQ",
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ"
}],
["QzBbvGmIZWU", {
context: {
wrappedKey: "AFu7WwFNjhWR5J6L8ks7S6H/1ktYVEw3yt1eIIWVaMabZaB3vh5612/FNzua4oS2oCM=",
value: "sqj+xRNEty8K3Q1gSMd5bIUYKu34JfiO2+LIMlJrOetFIbJdBoQ+U8JZNaTFl6Qp3RULZ41x0zeSBSk=",
alg: "AES-GCM"
},
roomToken: "QzBbvGmIZWU",
roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU"
}]
]);
const kExpectedRooms = new Map([
["_nxD4V4FflQ", {
context: {
wrappedKey: "F3V27oPB+FgjFbVPML2PupONYqoIZ53XRU4BqG46Lr3eyIGumgCEqgjSe/MXAXiQ//8=",
value: "df7B4SNxhOI44eJjQavCevADyCCxz6/DEZbkOkRUMVUxzS42FbzN6C2PqmCKDYUGyCJTwJ0jln8TLw==",
alg: "AES-GCM"
},
decryptedContext: {
roomName: "First Room Name"
},
roomKey: "FliIGLUolW-xkKZVWstqKw",
roomToken: "_nxD4V4FflQ",
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ#FliIGLUolW-xkKZVWstqKw"
}],
["QzBbvGmIZWU", {
context: {
wrappedKey: "AFu7WwFNjhWR5J6L8ks7S6H/1ktYVEw3yt1eIIWVaMabZaB3vh5612/FNzua4oS2oCM=",
value: "sqj+xRNEty8K3Q1gSMd5bIUYKu34JfiO2+LIMlJrOetFIbJdBoQ+U8JZNaTFl6Qp3RULZ41x0zeSBSk=",
alg: "AES-GCM"
},
decryptedContext: {
roomName: "Loopy Discussion",
},
roomKey: "h2H8Sa9QxLCTTiXNmJVtRA",
roomToken: "QzBbvGmIZWU",
roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU"
}]
]);
const kCreateRoomProps = {
decryptedContext: {
roomName: "Say Hello",
},
roomOwner: "Gavin",
maxSize: 2
};
const kCreateRoomData = {
roomToken: "Vo2BFQqIaAM",
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ",
expiresAt: 1405534180
};
function getCachePath() {
return OS.Path.join(OS.Constants.Path.profileDir, LOOP_ROOMS_CACHE_FILENAME);
}
function readRoomsCache() {
return CommonUtils.readJSON(getCachePath());
}
function saveRoomsCache(contents) {
delete LoopRoomsInternal.roomsCache._cache;
return CommonUtils.writeJSON(contents, getCachePath());
}
function clearRoomsCache() {
return LoopRoomsInternal.roomsCache.clear();
}
// This is a cut-down version of the one in test_looprooms.js.
add_task(function* setup_server() {
loopServer.registerPathHandler("/registration", (req, res) => {
res.setStatusLine(null, 200, "OK");
res.processAsync();
res.finish();
});
loopServer.registerPathHandler("/rooms", (req, res) => {
res.setStatusLine(null, 200, "OK");
if (req.method == "POST") {
Assert.ok(req.bodyInputStream, "POST request should have a payload");
let body = CommonUtils.readBytesFromInputStream(req.bodyInputStream);
let data = JSON.parse(body);
Assert.ok(!("decryptedContext" in data), "should not have any decrypted data");
Assert.ok("context" in data, "should have context");
res.write(JSON.stringify(kCreateRoomData));
} else {
res.write(JSON.stringify([...kRoomsResponses.values()]));
}
res.processAsync();
res.finish();
});
function returnRoomDetails(res, roomName) {
roomDetail.roomName = roomName;
res.setStatusLine(null, 200, "OK");
res.write(JSON.stringify(roomDetail));
res.processAsync();
res.finish();
}
function getJSONData(body) {
return JSON.parse(CommonUtils.readBytesFromInputStream(body));
}
// Add a request handler for each room in the list.
[...kRoomsResponses.values()].forEach(function(room) {
loopServer.registerPathHandler("/rooms/" + encodeURIComponent(room.roomToken), (req, res) => {
if (req.method == "POST") {
let data = getJSONData(req.bodyInputStream);
res.setStatusLine(null, 200, "OK");
res.write(JSON.stringify(data));
res.processAsync();
res.finish();
} else if (req.method == "PATCH") {
let data = getJSONData(req.bodyInputStream);
Assert.ok("context" in data, "should have encrypted context");
// We return a fake encrypted name here as the context is
// encrypted.
returnRoomDetails(res, "fakeEncrypted");
} else {
res.setStatusLine(null, 200, "OK");
res.write(JSON.stringify(room));
res.processAsync();
res.finish();
}
});
});
loopServer.registerPathHandler("/rooms/error401", (req, res) => {
res.setStatusLine(null, 401, "Not Found");
res.processAsync();
res.finish();
});
loopServer.registerPathHandler("/rooms/errorMalformed", (req, res) => {
res.setStatusLine(null, 200, "OK");
res.write("{\"some\": \"Syntax Error!\"}}}}}}");
res.processAsync();
res.finish();
});
mockPushHandler.registrationPushURL = kEndPointUrl;
yield MozLoopService.promiseRegisteredWithServers();
});
// Test if getting rooms saves unknown keys correctly.
add_task(function* test_get_rooms_saves_unknown_keys() {
let rooms = yield LoopRooms.promise("getAll");
// Check that we've saved the encryption keys correctly.
let roomsCache = yield readRoomsCache();
for (let room of [...kExpectedRooms.values()]) {
if (room.context.wrappedKey) {
Assert.equal(roomsCache[LOOP_SESSION_TYPE.FXA][room.roomToken].key, room.roomKey);
}
}
yield clearRoomsCache();
});
// Test that when we get a room it updates the saved key if it is different.
add_task(function* test_get_rooms_saves_different_keys() {
let roomsCache = {};
roomsCache[LOOP_SESSION_TYPE.FXA] = {
QzBbvGmIZWU: {key: "fakeKey"}
};
yield saveRoomsCache(roomsCache);
const kRoomToken = "QzBbvGmIZWU";
let room = yield LoopRooms.promise("get", kRoomToken);
// Check that we've saved the encryption keys correctly.
roomsCache = yield readRoomsCache();
Assert.notEqual(roomsCache[LOOP_SESSION_TYPE.FXA][kRoomToken].key, "fakeKey");
Assert.equal(roomsCache[LOOP_SESSION_TYPE.FXA][kRoomToken].key, room.roomKey);
yield clearRoomsCache();
});
// Test that if roomKey decryption fails, the saved key is used for decryption.
add_task(function* test_get_rooms_uses_saved_key() {
const kRoomToken = "_nxD4V4FflQ";
const kExpected = kExpectedRooms.get(kRoomToken);
let roomsCache = {};
roomsCache[LOOP_SESSION_TYPE.FXA] = {
"_nxD4V4FflQ": {key: kExpected.roomKey}
};
yield saveRoomsCache(roomsCache);
// Change the encryption key for FxA, so that decoding the room key will break.
Services.prefs.setCharPref("loop.key.fxa", "invalidKey");
let room = yield LoopRooms.promise("get", kRoomToken);
Assert.deepEqual(room, kExpected);
Services.prefs.setCharPref("loop.key.fxa", kFxAKey);
yield clearRoomsCache();
});
// Test that when a room is created the new key is saved.
add_task(function* test_create_room_saves_key() {
let room = yield LoopRooms.promise("create", kCreateRoomProps);
let roomsCache = yield readRoomsCache();
Assert.equal(roomsCache[LOOP_SESSION_TYPE.FXA][room.roomToken].key, room.roomKey);
yield clearRoomsCache();
});
function run_test() {
setupFakeLoopServer();
Services.prefs.setCharPref("loop.key.fxa", kFxAKey);
Services.prefs.setBoolPref(kContextEnabledPref, true);
// Pretend we're signed into FxA.
MozLoopServiceInternal.fxAOAuthTokenData = { token_type: "bearer" };
MozLoopServiceInternal.fxAOAuthProfile = { email: "fake@invalid.com" };
do_register_cleanup(function () {
Services.prefs.clearUserPref(kContextEnabledPref);
Services.prefs.clearUserPref("loop.key.fxa");
MozLoopServiceInternal.fxAOAuthTokenData = null;
MozLoopServiceInternal.fxAOAuthProfile = null;
});
run_next_test();
}

View File

@ -0,0 +1,119 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource://services-common/utils.js");
Cu.import("resource:///modules/loop/LoopRooms.jsm");
Cu.import("resource:///modules/Chat.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
const kGuestKey = "uGIs-kGbYt1hBBwjyW7MLQ";
const kChannelGuest = MozLoopService.channelIDs.roomsGuest;
const kRoomsResponses = new Map([
["_nxD4V4FflQ", {
roomToken: "_nxD4V4FflQ",
// Encrypted with roomKey "FliIGLUolW-xkKZVWstqKw".
// roomKey is wrapped with kGuestKey.
context: {
wrappedKey: "F3V27oPB+FgjFbVPML2PupONYqoIZ53XRU4BqG46Lr3eyIGumgCEqgjSe/MXAXiQ//8=",
value: "df7B4SNxhOI44eJjQavCevADyCCxz6/DEZbkOkRUMVUxzS42FbzN6C2PqmCKDYUGyCJTwJ0jln8TLw==",
alg: "AES-GCM"
},
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ",
maxSize: 2,
ctime: 1405517546,
participants: [{
displayName: "Alexis",
account: "alexis@example.com",
roomConnectionId: "2a1787a6-4a73-43b5-ae3e-906ec1e763cb"
}, {
displayName: "Adam",
roomConnectionId: "781f012b-f1ea-4ce1-9105-7cfc36fb4ec7"
}]
}],
["QzBbvGmIZWU", {
roomToken: "QzBbvGmIZWU",
roomName: "Second Room Name",
roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU",
maxSize: 2,
ctime: 140551741
}],
]);
let gRoomsAdded = [];
let gRoomsUpdated = [];
const onRoomAdded = function(e, room) {
gRoomsAdded.push(room);
};
const onRoomUpdated = function(e, room) {
gRoomsUpdated.push(room);
};
let gQueryString = null;
add_task(function* setup_server() {
loopServer.registerPathHandler("/registration", (req, res) => {
res.setStatusLine(null, 200, "OK");
res.processAsync();
res.finish();
});
loopServer.registerPathHandler("/rooms", (req, res) => {
gQueryString = req.queryString;
res.setStatusLine(null, 200, "OK");
// For this simple test, always send all rooms, even though this wouldn't
// happen normally.
res.write(JSON.stringify([...kRoomsResponses.values()]));
res.processAsync();
res.finish();
});
mockPushHandler.registrationPushURL = kEndPointUrl;
yield MozLoopService.promiseRegisteredWithServers();
});
// Test if notifying from push correctly gets all rooms the first time.
add_task(function* test_notification_firstTime() {
roomsPushNotification("1", kChannelGuest);
// Wait for the notification to complete before we getAll, otherwise
// the getAll may cover up what we're testing.
yield waitForCondition(() => gRoomsAdded.length === 2);
let rooms = yield LoopRooms.promise("getAll");
Assert.equal(rooms.length, 2);
Assert.equal(gQueryString, "", "Query string should not be set.");
});
// Test if notifying from push correctly only gets the specific room the second time.
add_task(function* test_notification_firstTime() {
roomsPushNotification("2", kChannelGuest);
yield waitForCondition(() => gRoomsUpdated.length === 2);
let rooms = yield LoopRooms.promise("getAll");
Assert.equal(rooms.length, 2);
Assert.equal(gQueryString, "version=2", "Query string should be set.");
});
function run_test() {
setupFakeLoopServer();
Services.prefs.setCharPref("loop.key", kGuestKey);
LoopRooms.on("add", onRoomAdded);
LoopRooms.on("update", onRoomUpdated);
do_register_cleanup(function () {
Services.prefs.clearUserPref("loop.key");
LoopRooms.off("add", onRoomAdded);
LoopRooms.off("update", onRoomUpdated);
});
run_next_test();
}

View File

@ -120,4 +120,4 @@ function run_test() {
}); });
run_next_test(); run_next_test();
}; }

View File

@ -7,6 +7,8 @@ skip-if = toolkit == 'gonk'
[test_loopapi_hawk_request.js] [test_loopapi_hawk_request.js]
[test_looppush_initialize.js] [test_looppush_initialize.js]
[test_looprooms.js] [test_looprooms.js]
[test_looprooms_encryption_in_fxa.js]
[test_looprooms_first_notification.js]
[test_loopservice_directcall.js] [test_loopservice_directcall.js]
[test_loopservice_dnd.js] [test_loopservice_dnd.js]
[test_loopservice_encryptionkey.js] [test_loopservice_encryptionkey.js]

View File

@ -632,7 +632,6 @@ BrowserGlue.prototype = {
let buttons = [ let buttons = [
{ {
label: win.gNavigatorBundle.getFormattedString("addonwatch.disable.label", [addon.name]), label: win.gNavigatorBundle.getFormattedString("addonwatch.disable.label", [addon.name]),
accessKey: win.gNavigatorBundle.getString("addonwatch.disable.accesskey"),
callback: function() { callback: function() {
addon.userDisabled = true; addon.userDisabled = true;
if (addon.pendingOperations != addon.PENDING_NONE) { if (addon.pendingOperations != addon.PENDING_NONE) {

View File

@ -19,14 +19,17 @@ loader.lazyRequireGetter(this, "TimelineFront",
"devtools/server/actors/timeline", true); "devtools/server/actors/timeline", true);
loader.lazyRequireGetter(this, "MemoryFront", loader.lazyRequireGetter(this, "MemoryFront",
"devtools/server/actors/memory", true); "devtools/server/actors/memory", true);
loader.lazyRequireGetter(this, "timers", loader.lazyRequireGetter(this, "Poller",
"resource://gre/modules/Timer.jsm"); "devtools/shared/poller", true);
// how often do we pull allocation sites from the memory actor // how often do we pull allocation sites from the memory actor
const ALLOCATION_SITE_POLL_TIMER = 200; // ms const ALLOCATION_SITE_POLL_TIMER = 200; // ms
// how often do we check the status of the profiler's circular buffer
const BUFFER_CHECK_TIMER = 5000; // ms
const MEMORY_ACTOR_METHODS = [ const MEMORY_ACTOR_METHODS = [
"destroy", "attach", "detach", "getState", "getAllocationsSettings", "attach", "detach", "getState", "getAllocationsSettings",
"getAllocations", "startRecordingAllocations", "stopRecordingAllocations" "getAllocations", "startRecordingAllocations", "stopRecordingAllocations"
]; ];
@ -45,6 +48,9 @@ const PROFILER_ACTOR_METHODS = [
function ProfilerFrontFacade (target) { function ProfilerFrontFacade (target) {
this._target = target; this._target = target;
this._onProfilerEvent = this._onProfilerEvent.bind(this); this._onProfilerEvent = this._onProfilerEvent.bind(this);
this._checkBufferStatus = this._checkBufferStatus.bind(this);
this._BUFFER_CHECK_TIMER = this._target.TEST_MOCK_BUFFER_CHECK_TIMER || BUFFER_CHECK_TIMER;
EventEmitter.decorate(this); EventEmitter.decorate(this);
} }
@ -72,6 +78,9 @@ ProfilerFrontFacade.prototype = {
* Unregisters events for the underlying profiler actor. * Unregisters events for the underlying profiler actor.
*/ */
destroy: Task.async(function *() { destroy: Task.async(function *() {
if (this._poller) {
yield this._poller.destroy();
}
yield this.unregisterEventNotifications({ events: this.EVENTS }); yield this.unregisterEventNotifications({ events: this.EVENTS });
// TODO bug 1159389, listen directly to actor if supporting new front // TODO bug 1159389, listen directly to actor if supporting new front
this._target.client.removeListener("eventNotification", this._onProfilerEvent); this._target.client.removeListener("eventNotification", this._onProfilerEvent);
@ -79,16 +88,29 @@ ProfilerFrontFacade.prototype = {
/** /**
* Starts the profiler actor, if necessary. * Starts the profiler actor, if necessary.
*
* @option {number?} bufferSize
* @option {number?} sampleFrequency
*/ */
start: Task.async(function *(options={}) { start: Task.async(function *(options={}) {
// Check for poller status even if the profiler is already active --
// profiler can be activated via `console.profile` or another source, like
// the Gecko Profiler.
if (!this._poller) {
this._poller = new Poller(this._checkBufferStatus, this._BUFFER_CHECK_TIMER, false);
}
if (!this._poller.isPolling()) {
this._poller.on();
}
// Start the profiler only if it wasn't already active. The built-in // Start the profiler only if it wasn't already active. The built-in
// nsIPerformance module will be kept recording, because it's the same instance // nsIPerformance module will be kept recording, because it's the same instance
// for all targets and interacts with the whole platform, so we don't want // for all targets and interacts with the whole platform, so we don't want
// to affect other clients by stopping (or restarting) it. // to affect other clients by stopping (or restarting) it.
let profilerStatus = yield this.isActive(); let { isActive, currentTime, position, generation, totalSize } = yield this.isActive();
if (profilerStatus.isActive) { if (isActive) {
this.emit("profiler-already-active"); this.emit("profiler-already-active");
return profilerStatus.currentTime; return { startTime: currentTime, position, generation, totalSize };
} }
// Translate options from the recording model into profiler-specific // Translate options from the recording model into profiler-specific
@ -101,7 +123,16 @@ ProfilerFrontFacade.prototype = {
yield this.startProfiler(profilerOptions); yield this.startProfiler(profilerOptions);
this.emit("profiler-activated"); this.emit("profiler-activated");
return 0; return { startTime: 0, position, generation, totalSize };
}),
/**
* Indicates the end of a recording -- does not actually stop the profiler
* (stopProfiler does that), but notes that we no longer need to poll
* for buffer status.
*/
stop: Task.async(function *() {
yield this._poller.off();
}), }),
/** /**
@ -136,6 +167,10 @@ ProfilerFrontFacade.prototype = {
} }
}, },
_checkBufferStatus: Task.async(function *() {
this.emit("buffer-status", (yield this.isActive()));
}),
toString: () => "[object ProfilerFrontFacade]" toString: () => "[object ProfilerFrontFacade]"
}; };
@ -200,6 +235,7 @@ exports.TimelineFront = TimelineFrontFacade;
function MemoryFrontFacade (target) { function MemoryFrontFacade (target) {
this._target = target; this._target = target;
this._pullAllocationSites = this._pullAllocationSites.bind(this); this._pullAllocationSites = this._pullAllocationSites.bind(this);
EventEmitter.decorate(this); EventEmitter.decorate(this);
} }
@ -213,6 +249,16 @@ MemoryFrontFacade.prototype = {
this.IS_MOCK = !supported; this.IS_MOCK = !supported;
}), }),
/**
* Disables polling and destroys actor.
*/
destroy: Task.async(function *() {
if (this._poller) {
yield this._poller.destroy();
}
yield this._actor.destroy();
}),
/** /**
* Starts polling for allocation information. * Starts polling for allocation information.
*/ */
@ -235,7 +281,12 @@ MemoryFrontFacade.prototype = {
let startTime = yield this.startRecordingAllocations(allocationOptions); let startTime = yield this.startRecordingAllocations(allocationOptions);
yield this._pullAllocationSites(); if (!this._poller) {
this._poller = new Poller(this._pullAllocationSites, ALLOCATION_SITE_POLL_TIMER, false);
}
if (!this._poller.isPolling()) {
this._poller.on();
}
return startTime; return startTime;
}), }),
@ -253,8 +304,8 @@ MemoryFrontFacade.prototype = {
// be stopped before that method finishes executing. Therefore, we need to // be stopped before that method finishes executing. Therefore, we need to
// wait for the last request to `getAllocations` to finish before actually // wait for the last request to `getAllocations` to finish before actually
// stopping recording allocations. // stopping recording allocations.
yield this._poller.off();
yield this._lastPullAllocationSitesFinished; yield this._lastPullAllocationSitesFinished;
timers.clearTimeout(this._sitesPullTimeout);
let endTime = yield this.stopRecordingAllocations(); let endTime = yield this.stopRecordingAllocations();
yield this.detach(); yield this.detach();
@ -287,8 +338,6 @@ MemoryFrontFacade.prototype = {
counts: memoryData.counts counts: memoryData.counts
}); });
this._sitesPullTimeout = timers.setTimeout(this._pullAllocationSites, ALLOCATION_SITE_POLL_TIMER);
resolve(); resolve();
}), }),

View File

@ -153,6 +153,13 @@ function legacyRequest (target, actor, method, args) {
*/ */
function actorCompatibilityBridge (method) { function actorCompatibilityBridge (method) {
return function () { return function () {
// If there's no target or client on this actor facade,
// abort silently -- this occurs in tests when polling occurs
// after the test ends, when tests do not wait for toolbox destruction
// (which will destroy the actor facade, turning off the polling).
if (!this._target || !this._target.client) {
return;
}
// Check to see if this is a modern ActorFront, which has its // Check to see if this is a modern ActorFront, which has its
// own `request` method. Also, check if its a mock actor, as it mimicks // own `request` method. Also, check if its a mock actor, as it mimicks
// the ActorFront interface. // the ActorFront interface.

View File

@ -21,14 +21,11 @@ loader.lazyImporter(this, "gDevTools",
loader.lazyImporter(this, "Promise", loader.lazyImporter(this, "Promise",
"resource://gre/modules/Promise.jsm"); "resource://gre/modules/Promise.jsm");
// How often do we pull allocation sites from the memory actor.
const DEFAULT_ALLOCATION_SITES_PULL_TIMEOUT = 200; // ms
// Events to pipe from PerformanceActorsConnection to the PerformanceFront // Events to pipe from PerformanceActorsConnection to the PerformanceFront
const CONNECTION_PIPE_EVENTS = [ const CONNECTION_PIPE_EVENTS = [
"timeline-data", "profiler-already-active", "profiler-activated", "timeline-data", "profiler-already-active", "profiler-activated",
"recording-starting", "recording-started", "recording-stopping", "recording-stopped" "recording-starting", "recording-started", "recording-stopping", "recording-stopped",
"buffer-status"
]; ];
/** /**
@ -79,6 +76,7 @@ function PerformanceActorsConnection(target) {
this._onTimelineData = this._onTimelineData.bind(this); this._onTimelineData = this._onTimelineData.bind(this);
this._onConsoleProfileStart = this._onConsoleProfileStart.bind(this); this._onConsoleProfileStart = this._onConsoleProfileStart.bind(this);
this._onConsoleProfileEnd = this._onConsoleProfileEnd.bind(this); this._onConsoleProfileEnd = this._onConsoleProfileEnd.bind(this);
this._onBufferStatus = this._onBufferStatus.bind(this);
this._onProfilerUnexpectedlyStopped = this._onProfilerUnexpectedlyStopped.bind(this); this._onProfilerUnexpectedlyStopped = this._onProfilerUnexpectedlyStopped.bind(this);
Services.obs.notifyObservers(null, "performance-actors-connection-created", null); Services.obs.notifyObservers(null, "performance-actors-connection-created", null);
@ -173,6 +171,7 @@ PerformanceActorsConnection.prototype = {
this._profiler.on("profiler-stopped", this._onProfilerUnexpectedlyStopped); this._profiler.on("profiler-stopped", this._onProfilerUnexpectedlyStopped);
this._profiler.on("profiler-already-active", this._pipeToConnection); this._profiler.on("profiler-already-active", this._pipeToConnection);
this._profiler.on("profiler-activated", this._pipeToConnection); this._profiler.on("profiler-activated", this._pipeToConnection);
this._profiler.on("buffer-status", this._onBufferStatus);
}, },
/** /**
@ -186,6 +185,7 @@ PerformanceActorsConnection.prototype = {
this._profiler.off("profiler-stopped", this._onProfilerUnexpectedlyStopped); this._profiler.off("profiler-stopped", this._onProfilerUnexpectedlyStopped);
this._profiler.off("profiler-already-active", this._pipeToConnection); this._profiler.off("profiler-already-active", this._pipeToConnection);
this._profiler.off("profiler-activated", this._pipeToConnection); this._profiler.off("profiler-activated", this._pipeToConnection);
this._profiler.off("buffer-status", this._onBufferStatus);
}, },
/** /**
@ -289,10 +289,25 @@ PerformanceActorsConnection.prototype = {
* Populate our internal store of recordings for all currently recording sessions. * Populate our internal store of recordings for all currently recording sessions.
*/ */
_onTimelineData: function (_, ...data) { _onTimelineData: function (_, ...data) {
this._recordings.forEach(e => e.addTimelineData.apply(e, data)); this._recordings.forEach(e => e._addTimelineData.apply(e, data));
this.emit("timeline-data", ...data); this.emit("timeline-data", ...data);
}, },
/**
* Called whenever the underlying profiler polls its buffer status.
*/
_onBufferStatus: function (_, data) {
// If no buffer data emitted (whether from an older actor being destroyed
// from a previous test, or the server does not support it), just ignore.
// Also check for a value of buffer status (`position`) to see if it's
// because of an unsupported server.
if (!data || data.position === void 0) {
return;
}
this._recordings.forEach(e => e._addBufferStatusData.call(e, data));
this.emit("buffer-status", data);
},
/** /**
* Begins a recording session * Begins a recording session
* *
@ -310,15 +325,18 @@ PerformanceActorsConnection.prototype = {
// Get the corresponding start times from each one of them. // Get the corresponding start times from each one of them.
// The timeline and memory actors are target-dependent, so start those as well, // The timeline and memory actors are target-dependent, so start those as well,
// even though these are mocked in older Geckos (FF < 35) // even though these are mocked in older Geckos (FF < 35)
let profilerStartTime = yield this._profiler.start(options); let { startTime, position, generation, totalSize } = yield this._profiler.start(options);
let timelineStartTime = yield this._timeline.start(options); let timelineStartTime = yield this._timeline.start(options);
let memoryStartTime = yield this._memory.start(options); let memoryStartTime = yield this._memory.start(options);
let data = { profilerStartTime, timelineStartTime, memoryStartTime }; let data = {
profilerStartTime: startTime, timelineStartTime, memoryStartTime,
generation, position, totalSize
};
// Signify to the model that the recording has started, // Signify to the model that the recording has started,
// populate with data and store the recording model here. // populate with data and store the recording model here.
model.populate(data); model._populate(data);
this._recordings.push(model); this._recordings.push(model);
this.emit("recording-started", model); this.emit("recording-started", model);
@ -368,6 +386,9 @@ PerformanceActorsConnection.prototype = {
// juse use Date.now() for the memory and timeline end times, as those // juse use Date.now() for the memory and timeline end times, as those
// are only used in tests. // are only used in tests.
if (!this.isRecording()) { if (!this.isRecording()) {
// This doesn't stop the profiler, just turns off polling for
// events, and also turns off events on memory/timeline actors.
yield this._profiler.stop();
memoryEndTime = yield this._memory.stop(config); memoryEndTime = yield this._memory.stop(config);
timelineEndTime = yield this._timeline.stop(config); timelineEndTime = yield this._timeline.stop(config);
} }

View File

@ -345,7 +345,11 @@ GraphsController.prototype = {
}, },
getMappedSelection: function ({ mapStart, mapEnd }) { getMappedSelection: function ({ mapStart, mapEnd }) {
return this._getPrimaryLink().getMappedSelection({ mapStart, mapEnd }); if (this._getPrimaryLink()) {
return this._getPrimaryLink().getMappedSelection({ mapStart, mapEnd });
} else {
return null;
}
}, },
/** /**

View File

@ -43,6 +43,8 @@ RecordingModel.prototype = {
_timelineStartTime: 0, _timelineStartTime: 0,
_memoryStartTime: 0, _memoryStartTime: 0,
_configuration: {}, _configuration: {},
_originalBufferStatus: null,
_bufferPercent: null,
// Serializable fields, necessary and sufficient for import and export. // Serializable fields, necessary and sufficient for import and export.
_label: "", _label: "",
@ -90,7 +92,7 @@ RecordingModel.prototype = {
* Sets up the instance with data from the SharedPerformanceConnection when * Sets up the instance with data from the SharedPerformanceConnection when
* starting a recording. Should only be called by SharedPerformanceConnection. * starting a recording. Should only be called by SharedPerformanceConnection.
*/ */
populate: function (info) { _populate: function (info) {
// Times must come from the actor in order to be self-consistent. // Times must come from the actor in order to be self-consistent.
// However, we also want to update the view with the elapsed time // However, we also want to update the view with the elapsed time
// even when the actor is not generating data. To do this we get // even when the actor is not generating data. To do this we get
@ -100,6 +102,12 @@ RecordingModel.prototype = {
this._profilerStartTime = info.profilerStartTime; this._profilerStartTime = info.profilerStartTime;
this._timelineStartTime = info.timelineStartTime; this._timelineStartTime = info.timelineStartTime;
this._memoryStartTime = info.memoryStartTime; this._memoryStartTime = info.memoryStartTime;
this._originalBufferStatus = {
position: info.position,
totalSize: info.totalSize,
generation: info.generation
};
this._recording = true; this._recording = true;
this._markers = []; this._markers = [];
@ -280,10 +288,36 @@ RecordingModel.prototype = {
return this._recording; return this._recording;
}, },
/**
* Returns the percent (value between 0 and 1) of buffer used in this
* recording. Returns `null` for recordings that are no longer recording.
*/
getBufferUsage: function () {
return this.isRecording() ? this._bufferPercent : null;
},
/**
* Fired whenever the PerformanceFront has new buffer data.
*/
_addBufferStatusData: function (bufferStatus) {
// If this model isn't currently recording, or if the server does not
// support buffer status (or if this fires after actors are being destroyed),
// ignore this information.
if (!bufferStatus || !this.isRecording()) {
return;
}
let { position: currentPosition, totalSize, generation: currentGeneration } = bufferStatus;
let { position: origPosition, generation: origGeneration } = this._originalBufferStatus;
let normalizedCurrent = (totalSize * (currentGeneration - origGeneration)) + currentPosition;
let percent = (normalizedCurrent - origPosition) / totalSize;
this._bufferPercent = percent > 1 ? 1 : percent;
},
/** /**
* Fired whenever the PerformanceFront emits markers, memory or ticks. * Fired whenever the PerformanceFront emits markers, memory or ticks.
*/ */
addTimelineData: function (eventName, ...data) { _addTimelineData: function (eventName, ...data) {
// If this model isn't currently recording, // If this model isn't currently recording,
// ignore the timeline data. // ignore the timeline data.
if (!this.isRecording()) { if (!this.isRecording()) {
@ -343,7 +377,9 @@ RecordingModel.prototype = {
break; break;
} }
} }
} },
toString: () => "[object RecordingModel]"
}; };
exports.RecordingModel = RecordingModel; exports.RecordingModel = RecordingModel;

View File

@ -19,6 +19,7 @@ support-files =
[browser_perf-compatibility-03.js] [browser_perf-compatibility-03.js]
[browser_perf-compatibility-04.js] [browser_perf-compatibility-04.js]
[browser_perf-compatibility-05.js] [browser_perf-compatibility-05.js]
[browser_perf-compatibility-06.js]
[browser_perf-clear-01.js] [browser_perf-clear-01.js]
[browser_perf-clear-02.js] [browser_perf-clear-02.js]
[browser_perf-columns-js-calltree.js] [browser_perf-columns-js-calltree.js]
@ -90,6 +91,7 @@ support-files =
[browser_perf-refresh.js] [browser_perf-refresh.js]
[browser_perf-ui-recording.js] [browser_perf-ui-recording.js]
[browser_perf-recording-model-01.js] [browser_perf-recording-model-01.js]
[browser_perf-recording-model-02.js]
[browser_perf-recording-notices-01.js] [browser_perf-recording-notices-01.js]
[browser_perf-recording-notices-02.js] [browser_perf-recording-notices-02.js]
[browser_perf_recordings-io-01.js] [browser_perf_recordings-io-01.js]

View File

@ -0,0 +1,46 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that when using an older server (< Fx40) where the profiler actor does not
* have the `getBufferInfo` method that nothing breaks and RecordingModels have null
* `getBufferUsage()` values.
*/
function spawnTest () {
let { target, front } = yield initBackend(SIMPLE_URL, { TEST_MOCK_BUFFER_CHECK_TIMER: 10 });
let frontBufferStatusCalled = false;
// Explicitly override the profiler's `isActive` method, where
// all the buffer info is retrieved, and delete the buffer properties.
let isActive = front._connection._profiler.isActive;
front._connection._profiler.isActive = function () {
return isActive.apply(front._connection._profiler, arguments).then(res => {
return { isActive: res.isActive, currentTime: res.currentTime };
});
};
front.on("buffer-status", () => frontBufferStatusCalled = true);
let model = yield front.startRecording();
let [_, stats] = yield onceSpread(front._connection._profiler, "buffer-status");
is(stats.generation, void 0, "buffer-status has void `generation`");
is(stats.totalSize, void 0, "buffer-status has void `totalSize`");
is(stats.position, void 0, "buffer-status has void `position`");
let count = 0;
while (count < 5) {
let [_, stats] = yield onceSpread(front._connection._profiler, "buffer-status");
is(stats.generation, void 0, "buffer-status has void `generation`");
is(stats.totalSize, void 0, "buffer-status has void `totalSize`");
is(stats.position, void 0, "buffer-status has void `position`");
count++;
}
is(model.getBufferUsage(), null, "model should have `null` for its buffer usage");
yield front.stopRecording(model);
is(model.getBufferUsage(), null, "after recording, model should still have `null` for its buffer usage");
ok(!frontBufferStatusCalled, "the front should never emit a buffer-status event when not supported.");
yield removeTab(target.tab);
finish();
}

View File

@ -0,0 +1,41 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that buffer status is correctly updated in recording models.
*/
let BUFFER_SIZE = 20000;
function spawnTest () {
let { target, front } = yield initBackend(SIMPLE_URL, { TEST_MOCK_BUFFER_CHECK_TIMER: 10 });
let config = { bufferSize: BUFFER_SIZE };
let model = yield front.startRecording(config);
let [_, stats] = yield onceSpread(front, "buffer-status");
is(stats.totalSize, BUFFER_SIZE, `buffer-status event has correct totalSize: ${stats.totalSize}`);
ok(stats.position < BUFFER_SIZE, `buffer-status event has correct position: ${stats.position}`);
is(stats.generation, 0, `buffer-status event has correct generation: ${stats.generation}`);
// Halt once more for a buffer status to ensure we're beyond 0
yield once(front, "buffer-status");
let lastBufferStatus = 0;
let checkCount = 0;
while (lastBufferStatus < 1) {
let currentBufferStatus = model.getBufferUsage();
ok(currentBufferStatus > lastBufferStatus, `buffer is more filled than before: ${currentBufferStatus}`);
lastBufferStatus = currentBufferStatus;
checkCount++;
yield once(front, "buffer-status");
}
ok(checkCount >= 1, "atleast 1 event were fired until the buffer was filled");
is(lastBufferStatus, 1, "buffer usage cannot surpass 100%");
yield front.stopRecording(model);
is(model.getBufferUsage(), null, "getBufferUsage() should be null when no longer recording.");
yield removeTab(target.tab);
finish();
}

View File

@ -195,6 +195,7 @@ function initBackend(aUrl, targetOps={}) {
// may not exist. Possible options that will actually work: // may not exist. Possible options that will actually work:
// TEST_MOCK_MEMORY_ACTOR = true // TEST_MOCK_MEMORY_ACTOR = true
// TEST_MOCK_TIMELINE_ACTOR = true // TEST_MOCK_TIMELINE_ACTOR = true
// TEST_MOCK_BUFFER_CHECK_TIMER = number
merge(target, targetOps); merge(target, targetOps);
let connection = getPerformanceActorsConnection(target); let connection = getPerformanceActorsConnection(target);

View File

@ -155,6 +155,11 @@ let OverviewView = {
let mapStart = () => 0; let mapStart = () => 0;
let mapEnd = () => recording.getDuration(); let mapEnd = () => recording.getDuration();
let selection = this.graphs.getMappedSelection({ mapStart, mapEnd }); let selection = this.graphs.getMappedSelection({ mapStart, mapEnd });
// If no selection returned, this means the overview graphs have not been rendered
// yet, so act as if we have no selection (the full recording).
if (!selection) {
return { startTime: 0, endTime: recording.getDuration() };
}
return { startTime: selection.min, endTime: selection.max }; return { startTime: selection.min, endTime: selection.max };
}, },

View File

@ -1062,7 +1062,7 @@ Messages.Extended.prototype = Heritage.extend(Messages.Simple.prototype,
* DOM node or a function to invoke. * DOM node or a function to invoke.
* @return Element * @return Element
*/ */
_renderBodyPiece: function(piece) _renderBodyPiece: function(piece, options = {})
{ {
if (piece instanceof Ci.nsIDOMNode) { if (piece instanceof Ci.nsIDOMNode) {
return piece; return piece;
@ -1071,7 +1071,7 @@ Messages.Extended.prototype = Heritage.extend(Messages.Simple.prototype,
return piece(this); return piece(this);
} }
return this._renderValueGrip(piece); return this._renderValueGrip(piece, options);
}, },
/** /**
@ -1410,20 +1410,21 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
_renderBodyPieces: function(container) _renderBodyPieces: function(container)
{ {
let lastStyle = null; let lastStyle = null;
let stylePieces = this._styles.length > 0 ? this._styles.length : 1;
for (let i = 0; i < this._messagePieces.length; i++) { for (let i = 0; i < this._messagePieces.length; i++) {
let separator = i > 0 ? this._renderBodyPieceSeparator() : null; // Pieces with an associated style definition come from "%c" formatting.
if (separator) { // For body pieces beyond that, add a separator before each one.
container.appendChild(separator); if (i >= stylePieces) {
container.appendChild(this._renderBodyPieceSeparator());
} }
let piece = this._messagePieces[i]; let piece = this._messagePieces[i];
let style = this._styles[i]; let style = this._styles[i];
// No long string support. // No long string support.
if (style && typeof style == "string" ) { lastStyle = (style && typeof style == "string") ?
lastStyle = this.cleanupStyle(style); this.cleanupStyle(style) : null;
}
container.appendChild(this._renderBodyPiece(piece, lastStyle)); container.appendChild(this._renderBodyPiece(piece, lastStyle));
} }
@ -1434,7 +1435,9 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
_renderBodyPiece: function(piece, style) _renderBodyPiece: function(piece, style)
{ {
let elem = Messages.Extended.prototype._renderBodyPiece.call(this, piece); // Skip quotes for top-level strings.
let options = { noStringQuotes: true };
let elem = Messages.Extended.prototype._renderBodyPiece.call(this, piece, options);
let result = elem; let result = elem;
if (style) { if (style) {
@ -3298,11 +3301,16 @@ Widgets.ObjectRenderers.add({
* The owning message. * The owning message.
* @param object longStringActor * @param object longStringActor
* The LongStringActor to display. * The LongStringActor to display.
* @param object options
* Options, such as noStringQuotes
*/ */
Widgets.LongString = function(message, longStringActor) Widgets.LongString = function(message, longStringActor, options)
{ {
Widgets.BaseWidget.call(this, message); Widgets.BaseWidget.call(this, message);
this.longStringActor = longStringActor; this.longStringActor = longStringActor;
this.noStringQuotes = (options && "noStringQuotes" in options) ?
options.noStringQuotes : !this.message._quoteStrings;
this._onClick = this._onClick.bind(this); this._onClick = this._onClick.bind(this);
this._onSubstring = this._onSubstring.bind(this); this._onSubstring = this._onSubstring.bind(this);
}; };
@ -3338,7 +3346,7 @@ Widgets.LongString.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
_renderString: function(str) _renderString: function(str)
{ {
this.element.textContent = VariablesView.getString(str, { this.element.textContent = VariablesView.getString(str, {
noStringQuotes: !this.message._quoteStrings, noStringQuotes: this.noStringQuotes,
noEllipsis: true, noEllipsis: true,
}); });
}, },

View File

@ -89,7 +89,7 @@ function* testMethod(aMethod, aHud, aOutputNode) {
yield waitForMessages({ yield waitForMessages({
webconsole: aHud, webconsole: aHud,
messages: [{ messages: [{
text: '"foo" "bar"', text: 'foo bar',
category: CATEGORY_WEBDEV, category: CATEGORY_WEBDEV,
}], }],
}) })

View File

@ -29,6 +29,7 @@ let inputTests = [
{ {
input: "'hello \\nfrom \\rthe \\\"string world!'", input: "'hello \\nfrom \\rthe \\\"string world!'",
output: "\"hello \nfrom \rthe \"string world!\"", output: "\"hello \nfrom \rthe \"string world!\"",
consoleOutput: "hello \nfrom \rthe \"string world!",
}, },
// 1 // 1
@ -36,12 +37,14 @@ let inputTests = [
// unicode test // unicode test
input: "'\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165'", input: "'\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165'",
output: "\"\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165\"", output: "\"\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165\"",
consoleOutput: "\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165",
}, },
// 2 // 2
{ {
input: "'" + longString + "'", input: "'" + longString + "'",
output: '"' + initialString + "\"[\u2026]", output: '"' + initialString + "\"[\u2026]",
consoleOutput: initialString + "[\u2026]",
printOutput: initialString, printOutput: initialString,
}, },
@ -49,6 +52,7 @@ let inputTests = [
{ {
input: "''", input: "''",
output: '""', output: '""',
consoleOutput: "",
printOutput: '""', printOutput: '""',
}, },
@ -62,6 +66,7 @@ let inputTests = [
{ {
input: "'0'", input: "'0'",
output: '"0"', output: '"0"',
consoleOutput: "0",
}, },
// 6 // 6
@ -74,6 +79,7 @@ let inputTests = [
{ {
input: "'42'", input: "'42'",
output: '"42"', output: '"42"',
consoleOutput: "42",
}, },
// 8 // 8

View File

@ -35,7 +35,7 @@ let test = asyncTest(function* () {
webconsole: hud, webconsole: hud,
messages: [{ messages: [{
name: "console.log() output for mousemove", name: "console.log() output for mousemove",
text: /"eventLogger" mousemove { target: .+, buttons: 0, clientX: \d+, clientY: \d+, layerX: \d+, layerY: \d+ }/, text: /eventLogger mousemove { target: .+, buttons: 0, clientX: \d+, clientY: \d+, layerX: \d+, layerY: \d+ }/,
category: CATEGORY_WEBDEV, category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG, severity: SEVERITY_LOG,
}], }],
@ -45,7 +45,7 @@ let test = asyncTest(function* () {
webconsole: hud, webconsole: hud,
messages: [{ messages: [{
name: "console.log() output for keypress", name: "console.log() output for keypress",
text: /"eventLogger" keypress Shift { target: .+, key: .+, charCode: \d+, keyCode: \d+ }/, text: /eventLogger keypress Shift { target: .+, key: .+, charCode: \d+, keyCode: \d+ }/,
category: CATEGORY_WEBDEV, category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG, severity: SEVERITY_LOG,
}], }],

View File

@ -31,7 +31,7 @@ let test = asyncTest(function*() {
category: CATEGORY_OUTPUT, category: CATEGORY_OUTPUT,
}, },
{ {
text: '"foo" "bar"', text: 'foo bar',
category: CATEGORY_WEBDEV, category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG, severity: SEVERITY_LOG,
}], }],

View File

@ -1421,6 +1421,9 @@ function whenDelayedStartupFinished(aWindow, aCallback)
* opening vview for them is very slow (they can cause timeouts in debug * opening vview for them is very slow (they can cause timeouts in debug
* builds). * builds).
* *
* - consoleOutput: string|RegExp, optional, expected consoleOutput
* If not provided consoleOuput = output;
*
* - printOutput: string|RegExp, optional, expected output for * - printOutput: string|RegExp, optional, expected output for
* |print(input)|. If this is not provided, printOutput = output. * |print(input)|. If this is not provided, printOutput = output.
* *
@ -1462,11 +1465,14 @@ function checkOutputForInputs(hud, inputTests)
hud.jsterm.clearOutput(); hud.jsterm.clearOutput();
hud.jsterm.execute("console.log(" + entry.input + ")"); hud.jsterm.execute("console.log(" + entry.input + ")");
let consoleOutput = "consoleOutput" in entry ?
entry.consoleOutput : entry.output;
let [result] = yield waitForMessages({ let [result] = yield waitForMessages({
webconsole: hud, webconsole: hud,
messages: [{ messages: [{
name: "console.log() output: " + entry.output, name: "console.log() output: " + consoleOutput,
text: entry.output, text: consoleOutput,
category: CATEGORY_WEBDEV, category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG, severity: SEVERITY_LOG,
}], }],

View File

@ -52,8 +52,6 @@ const HELP_URL = "https://developer.mozilla.org/docs/Tools/Web_Console/Helpers";
const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul"; const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul";
const CONSOLE_DIR_VIEW_HEIGHT = 0.6;
const IGNORED_SOURCE_URLS = ["debugger eval code"]; const IGNORED_SOURCE_URLS = ["debugger eval code"];
// The amount of time in milliseconds that we wait before performing a live // The amount of time in milliseconds that we wait before performing a live
@ -2664,9 +2662,6 @@ WebConsoleFrame.prototype = {
// Display the variables view after the message node. // Display the variables view after the message node.
if (aLevel == "dir") { if (aLevel == "dir") {
bodyNode.style.height = (this.window.innerHeight *
CONSOLE_DIR_VIEW_HEIGHT) + "px";
let options = { let options = {
objectActor: body.arguments[0], objectActor: body.arguments[0],
targetElement: bodyNode, targetElement: bodyNode,

View File

@ -51,7 +51,6 @@ addonConfirmInstall.message=This site would like to install an add-on in #1:;Thi
addonwatch.slow=%1$S might be making %2$S run slowly addonwatch.slow=%1$S might be making %2$S run slowly
addonwatch.disable.label=Disable %S addonwatch.disable.label=Disable %S
addonwatch.disable.accesskey=D
addonwatch.ignoreSession.label=Ignore for now addonwatch.ignoreSession.label=Ignore for now
addonwatch.ignoreSession.accesskey=I addonwatch.ignoreSession.accesskey=I
addonwatch.ignorePerm.label=Ignore permanently addonwatch.ignorePerm.label=Ignore permanently

View File

@ -8485,6 +8485,9 @@ AC_SUBST(MOZ_ANDROID_SHARE_OVERLAY)
AC_SUBST(MOZ_ANDROID_TAB_QUEUE) AC_SUBST(MOZ_ANDROID_TAB_QUEUE)
AC_SUBST(MOZ_ANDROID_MLS_STUMBLER) AC_SUBST(MOZ_ANDROID_MLS_STUMBLER)
AC_SUBST(MOZ_ANDROID_DOWNLOADS_INTEGRATION) AC_SUBST(MOZ_ANDROID_DOWNLOADS_INTEGRATION)
AC_SUBST(MOZ_ANDROID_APPLICATION_CLASS)
AC_SUBST(MOZ_ANDROID_BROWSER_INTENT_CLASS)
AC_SUBST(MOZ_ANDROID_SEARCH_INTENT_CLASS)
AC_SUBST(MOZ_INSTALL_TRACKING) AC_SUBST(MOZ_INSTALL_TRACKING)
AC_SUBST(ENABLE_STRIP) AC_SUBST(ENABLE_STRIP)
AC_SUBST(PKG_SKIP_STRIP) AC_SUBST(PKG_SKIP_STRIP)

View File

@ -1361,6 +1361,27 @@ Console::ProcessCallData(ConsoleCallData* aData)
} }
} }
namespace {
// Helper method for ProcessArguments. Flushes output, if non-empty, to aSequence.
void
FlushOutput(JSContext* aCx, Sequence<JS::Value>& aSequence, nsString &output)
{
if (!output.IsEmpty()) {
JS::Rooted<JSString*> str(aCx, JS_NewUCStringCopyN(aCx,
output.get(),
output.Length()));
if (!str) {
return;
}
aSequence.AppendElement(JS::StringValue(str));
output.Truncate();
}
}
} // anonymous namespace
void void
Console::ProcessArguments(JSContext* aCx, Console::ProcessArguments(JSContext* aCx,
const nsTArray<JS::Heap<JS::Value>>& aData, const nsTArray<JS::Heap<JS::Value>>& aData,
@ -1472,17 +1493,7 @@ Console::ProcessArguments(JSContext* aCx,
case 'o': case 'o':
case 'O': case 'O':
{ {
if (!output.IsEmpty()) { FlushOutput(aCx, aSequence, output);
JS::Rooted<JSString*> str(aCx, JS_NewUCStringCopyN(aCx,
output.get(),
output.Length()));
if (!str) {
return;
}
aSequence.AppendElement(JS::StringValue(str));
output.Truncate();
}
JS::Rooted<JS::Value> v(aCx); JS::Rooted<JS::Value> v(aCx);
if (index < aData.Length()) { if (index < aData.Length()) {
@ -1495,17 +1506,7 @@ Console::ProcessArguments(JSContext* aCx,
case 'c': case 'c':
{ {
if (!output.IsEmpty()) { FlushOutput(aCx, aSequence, output);
JS::Rooted<JSString*> str(aCx, JS_NewUCStringCopyN(aCx,
output.get(),
output.Length()));
if (!str) {
return;
}
aSequence.AppendElement(JS::StringValue(str));
output.Truncate();
}
if (index < aData.Length()) { if (index < aData.Length()) {
JS::Rooted<JS::Value> v(aCx, aData[index++]); JS::Rooted<JS::Value> v(aCx, aData[index++]);
@ -1579,14 +1580,11 @@ Console::ProcessArguments(JSContext* aCx,
} }
} }
if (!output.IsEmpty()) { FlushOutput(aCx, aSequence, output);
JS::Rooted<JSString*> str(aCx, JS_NewUCStringCopyN(aCx, output.get(),
output.Length()));
if (!str) {
return;
}
aSequence.AppendElement(JS::StringValue(str)); // Discard trailing style element if there is no output to apply it to.
if (aStyles.Length() > aSequence.Length()) {
aStyles.TruncateLength(aSequence.Length());
} }
// The rest of the array, if unused by the format string. // The rest of the array, if unused by the format string.

View File

@ -298,11 +298,7 @@ BluetoothA2dpManager::ResetAvrcp()
mMediaNumber = 0; mMediaNumber = 0;
mTotalMediaCount = 0; mTotalMediaCount = 0;
mPosition = 0; mPosition = 0;
#ifdef MOZ_B2G_BT_API_V2
mPlayStatus = ControlPlayStatus::PLAYSTATUS_UNKNOWN;
#else
mPlayStatus = ControlPlayStatus::PLAYSTATUS_STOPPED; mPlayStatus = ControlPlayStatus::PLAYSTATUS_STOPPED;
#endif
} }
/* /*
@ -933,9 +929,6 @@ BluetoothA2dpManager::UpdateRegisterNotification(BluetoothAvrcpEvent aEvent,
} }
mPlaybackInterval = aParam; mPlaybackInterval = aParam;
break; break;
#ifdef MOZ_B2G_BT_API_V2
// Missing in bluetooth2
#else
case AVRCP_EVENT_APP_SETTINGS_CHANGED: case AVRCP_EVENT_APP_SETTINGS_CHANGED:
mAppSettingsChangedNotifyType = AVRCP_NTF_INTERIM; mAppSettingsChangedNotifyType = AVRCP_NTF_INTERIM;
param.mNumAttr = 2; param.mNumAttr = 2;
@ -944,7 +937,6 @@ BluetoothA2dpManager::UpdateRegisterNotification(BluetoothAvrcpEvent aEvent,
param.mIds[1] = AVRCP_PLAYER_ATTRIBUTE_SHUFFLE; param.mIds[1] = AVRCP_PLAYER_ATTRIBUTE_SHUFFLE;
param.mValues[1] = AVRCP_PLAYER_VAL_OFF_SHUFFLE; param.mValues[1] = AVRCP_PLAYER_VAL_OFF_SHUFFLE;
break; break;
#endif
default: default:
break; break;
} }

View File

@ -1512,6 +1512,12 @@ BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData)
aPDU->SetConsumer(this); aPDU->SetConsumer(this);
aPDU->SetUserData(aUserData); aPDU->SetUserData(aUserData);
aPDU->UpdateHeader(); aPDU->UpdateHeader();
if (mConnection->GetConnectionStatus() == SOCKET_DISCONNECTED) {
BT_LOGR("Connection to Bluetooth daemon is closed.");
return NS_ERROR_FAILURE;
}
mConnection->SendSocketData(aPDU); // Forward PDU to command channel mConnection->SendSocketData(aPDU); // Forward PDU to command channel
return NS_OK; return NS_OK;

View File

@ -89,15 +89,11 @@ BluetoothOppManager::Observe(nsISupports* aSubject,
{ {
MOZ_ASSERT(sBluetoothOppManager); MOZ_ASSERT(sBluetoothOppManager);
#ifdef MOZ_B2G_BT_API_V2
// Removed in bluetooth2
#else
// if state of any volume was changed // if state of any volume was changed
if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) { if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
HandleVolumeStateChanged(aSubject); HandleVolumeStateChanged(aSubject);
return NS_OK; return NS_OK;
} }
#endif
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
HandleShutdown(); HandleShutdown();
@ -226,13 +222,9 @@ BluetoothOppManager::~BluetoothOppManager()
BT_WARNING("Failed to remove shutdown observer!"); BT_WARNING("Failed to remove shutdown observer!");
} }
#ifdef MOZ_B2G_BT_API_V2
// Removed in bluetooth2
#else
if (NS_FAILED(obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED))) { if (NS_FAILED(obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED))) {
BT_WARNING("Failed to remove volume observer!"); BT_WARNING("Failed to remove volume observer!");
} }
#endif
} }
bool bool
@ -245,14 +237,10 @@ BluetoothOppManager::Init()
return false; return false;
} }
#ifdef MOZ_B2G_BT_API_V2
// Removed in bluetooth2
#else
if (NS_FAILED(obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false))) { if (NS_FAILED(obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false))) {
BT_WARNING("Failed to add ns volume observer!"); BT_WARNING("Failed to add ns volume observer!");
return false; return false;
} }
#endif
/** /**
* We don't start listening here as BluetoothServiceBluedroid calls Listen() * We don't start listening here as BluetoothServiceBluedroid calls Listen()
@ -321,9 +309,6 @@ BluetoothOppManager::HandleShutdown()
sBluetoothOppManager = nullptr; sBluetoothOppManager = nullptr;
} }
#ifdef MOZ_B2G_BT_API_V2
// Removed in bluetooth2
#else
void void
BluetoothOppManager::HandleVolumeStateChanged(nsISupports* aSubject) BluetoothOppManager::HandleVolumeStateChanged(nsISupports* aSubject)
{ {
@ -357,7 +342,6 @@ BluetoothOppManager::HandleVolumeStateChanged(nsISupports* aSubject)
Disconnect(nullptr); Disconnect(nullptr);
} }
} }
#endif
bool bool
BluetoothOppManager::Listen() BluetoothOppManager::Listen()

View File

@ -77,11 +77,7 @@ private:
bool Init(); bool Init();
void HandleShutdown(); void HandleShutdown();
#ifdef MOZ_B2G_BT_API_V2
// Removed in bluetooth2
#else
void HandleVolumeStateChanged(nsISupports* aSubject); void HandleVolumeStateChanged(nsISupports* aSubject);
#endif
void StartFileTransfer(); void StartFileTransfer();
void StartSendingNextFile(); void StartSendingNextFile();

View File

@ -208,27 +208,6 @@ BluetoothHfpManager::ResetCallArray()
} }
} }
#ifdef MOZ_B2G_BT_API_V2
void
BluetoothHfpManager::Reset()
{
mReceiveVgsFlag = false;
mDialingRequestProcessed = true;
mConnectionState = HFP_CONNECTION_STATE_DISCONNECTED;
mPrevConnectionState = HFP_CONNECTION_STATE_DISCONNECTED;
mAudioState = HFP_AUDIO_STATE_DISCONNECTED;
// Phone & Device CIND
ResetCallArray();
mBattChg = 5;
mService = HFP_NETWORK_STATE_NOT_AVAILABLE;
mRoam = HFP_SERVICE_TYPE_HOME;
mSignal = 0;
mController = nullptr;
}
#else
void void
BluetoothHfpManager::Cleanup() BluetoothHfpManager::Cleanup()
{ {
@ -255,17 +234,12 @@ BluetoothHfpManager::Reset()
mAudioState = HFP_AUDIO_STATE_DISCONNECTED; mAudioState = HFP_AUDIO_STATE_DISCONNECTED;
Cleanup(); Cleanup();
} }
#endif
bool bool
BluetoothHfpManager::Init() BluetoothHfpManager::Init()
{ {
#ifdef MOZ_B2G_BT_API_V2
// The function must run at b2g process since it would access SettingsService. // The function must run at b2g process since it would access SettingsService.
MOZ_ASSERT(IsMainProcess()); MOZ_ASSERT(IsMainProcess());
#else
// Missing on bluetooth1
#endif
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
@ -624,11 +598,7 @@ BluetoothHfpManager::NotifyConnectionStateChanged(const nsAString& aType)
} else { } else {
OnDisconnect(EmptyString()); OnDisconnect(EmptyString());
} }
#ifdef MOZ_B2G_BT_API_V2
Reset();
#else
Cleanup(); Cleanup();
#endif
} }
} }
} }
@ -719,7 +689,6 @@ BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId)
nsString regState; nsString regState;
voiceInfo->GetState(regState); voiceInfo->GetState(regState);
#ifdef MOZ_B2G_BT_API_V2
BluetoothHandsfreeNetworkState service = BluetoothHandsfreeNetworkState service =
(regState.EqualsLiteral("registered")) ? HFP_NETWORK_STATE_AVAILABLE : (regState.EqualsLiteral("registered")) ? HFP_NETWORK_STATE_AVAILABLE :
HFP_NETWORK_STATE_NOT_AVAILABLE; HFP_NETWORK_STATE_NOT_AVAILABLE;
@ -728,15 +697,6 @@ BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId)
mListener->ServiceChanged(aClientId, service); mListener->ServiceChanged(aClientId, service);
} }
mService = service; mService = service;
#else
int service = (regState.EqualsLiteral("registered")) ? 1 : 0;
if (service != mService) {
// Notify BluetoothRilListener of service change
mListener->ServiceChanged(aClientId, service);
}
mService = service ? HFP_NETWORK_STATE_AVAILABLE :
HFP_NETWORK_STATE_NOT_AVAILABLE;
#endif
// Signal // Signal
JS::Rooted<JS::Value> value(nsContentUtils::RootingCxForThread()); JS::Rooted<JS::Value> value(nsContentUtils::RootingCxForThread());

View File

@ -172,11 +172,7 @@ private:
BluetoothHfpManager(); BluetoothHfpManager();
bool Init(); bool Init();
#ifdef MOZ_B2G_BT_API_V2
// Removed in bluetooth2
#else
void Cleanup(); void Cleanup();
#endif
void HandleShutdown(); void HandleShutdown();
void HandleVolumeChanged(nsISupports* aSubject); void HandleVolumeChanged(nsISupports* aSubject);

View File

@ -300,8 +300,8 @@ BluetoothGattCharacteristic::WriteValue(const ArrayBuffer& aValue,
NS_ENSURE_TRUE(!aRv.Failed(), nullptr); NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BT_ENSURE_TRUE_REJECT(mProperties & BT_ENSURE_TRUE_REJECT(mProperties &
(GATT_CHAR_PROP_BIT_WRITE_NO_RESPONSE || (GATT_CHAR_PROP_BIT_WRITE_NO_RESPONSE |
GATT_CHAR_PROP_BIT_WRITE || GATT_CHAR_PROP_BIT_WRITE |
GATT_CHAR_PROP_BIT_SIGNED_WRITE), GATT_CHAR_PROP_BIT_SIGNED_WRITE),
promise, promise,
NS_ERROR_NOT_AVAILABLE); NS_ERROR_NOT_AVAILABLE);

View File

@ -442,12 +442,8 @@ BluetoothHfpManager::Reset()
bool bool
BluetoothHfpManager::Init() BluetoothHfpManager::Init()
{ {
#ifdef MOZ_B2G_BT_API_V2
// The function must run at b2g process since it would access SettingsService. // The function must run at b2g process since it would access SettingsService.
MOZ_ASSERT(IsMainProcess()); MOZ_ASSERT(IsMainProcess());
#else
// Missing in bluetooth1
#endif
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@ -597,11 +593,8 @@ BluetoothHfpManager::HandleVolumeChanged(nsISupports* aSubject)
// {"key":"volumeup", "value":10} // {"key":"volumeup", "value":10}
// {"key":"volumedown", "value":2} // {"key":"volumedown", "value":2}
#ifdef MOZ_B2G_BT_API_V2
RootedDictionary<dom::SettingChangeNotification> setting(nsContentUtils::RootingCx()); RootedDictionary<dom::SettingChangeNotification> setting(nsContentUtils::RootingCx());
#else
RootedDictionary<SettingChangeNotification> setting(nsContentUtils::RootingCx());
#endif
if (!WrappedJSToDictionary(aSubject, setting)) { if (!WrappedJSToDictionary(aSubject, setting)) {
return; return;
} }
@ -1115,20 +1108,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
} }
#endif // MOZ_B2G_RIL #endif // MOZ_B2G_RIL
} else { } else {
#ifdef MOZ_B2G_BT_API_V2 BT_WARNING("Unsupported AT command: %s, reply with ERROR", msg.get());
nsCString warningMsg;
warningMsg.Append(NS_LITERAL_CSTRING("Unsupported AT command: "));
warningMsg.Append(msg);
warningMsg.Append(NS_LITERAL_CSTRING(", reply with ERROR"));
BT_WARNING(warningMsg.get());
#else
nsCString warningMsg;
warningMsg.AppendLiteral("Unsupported AT command: ");
warningMsg.Append(msg);
warningMsg.AppendLiteral(", reply with ERROR");
BT_WARNING(warningMsg.get());
#endif
SendLine("ERROR"); SendLine("ERROR");
return; return;
} }
@ -1700,11 +1680,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) { GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) {
// In order to let user hear busy tone via connected Bluetooth headset, // In order to let user hear busy tone via connected Bluetooth headset,
// we postpone the timing of dropping SCO. // we postpone the timing of dropping SCO.
#ifdef MOZ_B2G_BT_API_V2
if (!(aError.Equals(NS_LITERAL_STRING("BusyError")))) { if (!(aError.Equals(NS_LITERAL_STRING("BusyError")))) {
#else
if (!(aError.EqualsLiteral("BusyError"))) {
#endif
DisconnectSco(); DisconnectSco();
} else { } else {
// Close Sco later since Dialer is still playing busy tone via HF. // Close Sco later since Dialer is still playing busy tone via HF.

View File

@ -845,6 +845,16 @@ AutoMounter::UpdateState()
break; break;
case STATE_UMS_CONFIGURING: case STATE_UMS_CONFIGURING:
if (mtpEnabled) {
// MTP was enabled. Start reconfiguring.
SetState(STATE_MTP_CONFIGURING);
SetUsbFunction(USB_FUNC_MTP);
break;
}
if (rndisConfigured) {
SetState(STATE_RNDIS_CONFIGURED);
break;
}
// While configuring, the USB configuration state will change from // While configuring, the USB configuration state will change from
// CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
// so we don't check for cable unplugged here. However, having said // so we don't check for cable unplugged here. However, having said
@ -853,18 +863,8 @@ AutoMounter::UpdateState()
// in. This is why we need to check for mtpEnabled once we get the // in. This is why we need to check for mtpEnabled once we get the
// configured event. // configured event.
if (umsConfigured) { if (umsConfigured) {
if (mtpEnabled) {
// MTP was enabled. Start reconfiguring.
SetState(STATE_MTP_CONFIGURING);
SetUsbFunction(USB_FUNC_MTP);
break;
}
SetState(STATE_UMS_CONFIGURED); SetState(STATE_UMS_CONFIGURED);
} }
if (rndisConfigured) {
SetState(STATE_RNDIS_CONFIGURED);
break;
}
break; break;
case STATE_UMS_CONFIGURED: case STATE_UMS_CONFIGURED:
@ -1119,6 +1119,7 @@ void AutoMounter::GetStatus(bool& umsAvail, bool& umsConfigured, bool& umsEnable
bool& mtpAvail, bool& mtpConfigured, bool& mtpEnabled, bool& mtpAvail, bool& mtpConfigured, bool& mtpEnabled,
bool& rndisConfigured) bool& rndisConfigured)
{ {
umsAvail = false;
umsConfigured = false; umsConfigured = false;
umsEnabled = false; umsEnabled = false;
mtpAvail = false; mtpAvail = false;

View File

@ -39,8 +39,6 @@ XPCOMUtils.defineLazyGetter(this, "gRil", function() {
return null; return null;
}); });
const TOPIC_INTERFACE_REGISTERED = "network-interface-registered";
const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed"; const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed"; const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
const TOPIC_PREF_CHANGED = "nsPref:changed"; const TOPIC_PREF_CHANGED = "nsPref:changed";
@ -126,8 +124,6 @@ function TetheringService() {
Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false); Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false); Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false); Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false);
Services.obs.addObserver(this, TOPIC_INTERFACE_REGISTERED, false);
Services.obs.addObserver(this, TOPIC_INTERFACE_UNREGISTERED, false);
Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false); Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
this._dataDefaultServiceId = 0; this._dataDefaultServiceId = 0;
@ -257,28 +253,10 @@ TetheringService.prototype = {
" changed state to " + network.state); " changed state to " + network.state);
this.onConnectionChanged(network); this.onConnectionChanged(network);
break; break;
case TOPIC_INTERFACE_REGISTERED:
network = aSubject.QueryInterface(Ci.nsINetworkInterface);
if (network &&
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
debug("Force setting " + SETTINGS_DUN_REQUIRED + " to true.");
this.tetheringSettings[SETTINGS_DUN_REQUIRED] = true;
}
break;
case TOPIC_INTERFACE_UNREGISTERED:
network = aSubject.QueryInterface(Ci.nsINetworkInterface);
if (network &&
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
libcutils.property_get("ro.tethering.dun_required") === "1";
}
break;
case TOPIC_XPCOM_SHUTDOWN: case TOPIC_XPCOM_SHUTDOWN:
Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN); Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED); Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED); Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
Services.obs.removeObserver(this, TOPIC_INTERFACE_REGISTERED);
Services.obs.removeObserver(this, TOPIC_INTERFACE_UNREGISTERED);
Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this); Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
this.dunConnectTimer.cancel(); this.dunConnectTimer.cancel();
@ -643,6 +621,10 @@ TetheringService.prototype = {
return; return;
} }
// Re-check again, test cases set this property later.
this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
libcutils.property_get("ro.tethering.dun_required") === "1";
if (!aEnable) { if (!aEnable) {
this.enableWifiTethering(false, aConfig, aCallback); this.enableWifiTethering(false, aConfig, aCallback);
return; return;

View File

@ -218,6 +218,14 @@ let gTestSuite = (function() {
return setSettings1(SETTINGS_KEY_DATA_APN_SETTINGS, aApnSettings, aAllowError); return setSettings1(SETTINGS_KEY_DATA_APN_SETTINGS, aApnSettings, aAllowError);
} }
/**
* Set 'ro.tethering.dun_required' system property to 1. Note that this is a
* 'ro' property, it can only be set once.
*/
function setTetheringDunRequired() {
return runEmulatorShellSafe(['setprop', 'ro.tethering.dun_required', '1']);
}
/** /**
* Wrap DOMRequest onsuccess/onerror events to Promise resolve/reject. * Wrap DOMRequest onsuccess/onerror events to Promise resolve/reject.
* *
@ -704,6 +712,7 @@ let gTestSuite = (function() {
suite.setWifiTetheringEnabled = setWifiTetheringEnabled; suite.setWifiTetheringEnabled = setWifiTetheringEnabled;
suite.getDataApnSettings = getDataApnSettings; suite.getDataApnSettings = getDataApnSettings;
suite.setDataApnSettings = setDataApnSettings; suite.setDataApnSettings = setDataApnSettings;
suite.setTetheringDunRequired = setTetheringDunRequired;
/** /**

View File

@ -4,4 +4,6 @@ browser = false
qemu = true qemu = true
[test_wifi_tethering_enabled.js] [test_wifi_tethering_enabled.js]
; The following test must be the last tethering test ran, as it sets the
; 'ro.tethering.dun_required' property.
[test_wifi_tethering_dun.js] [test_wifi_tethering_dun.js]

View File

@ -22,6 +22,7 @@ gTestSuite.startTest(function() {
"types": ["dun"] } ]]; "types": ["dun"] } ]];
return gTestSuite.setDataApnSettings(apnSettings); return gTestSuite.setDataApnSettings(apnSettings);
}) })
.then(() => gTestSuite.setTetheringDunRequired())
.then(() => gTestSuite.startTetheringTest(function() { .then(() => gTestSuite.startTetheringTest(function() {
return gTestSuite.ensureWifiEnabled(false) return gTestSuite.ensureWifiEnabled(false)
.then(() => gTestSuite.setWifiTetheringEnabled(true, true)) .then(() => gTestSuite.setWifiTetheringEnabled(true, true))

View File

@ -87,7 +87,7 @@
<application android:label="@string/moz_app_displayname" <application android:label="@string/moz_app_displayname"
android:icon="@drawable/icon" android:icon="@drawable/icon"
android:logo="@drawable/logo" android:logo="@drawable/logo"
android:name="org.mozilla.gecko.GeckoApplication" android:name="@MOZ_ANDROID_APPLICATION_CLASS@"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
# The preprocessor does not yet support arbitrary parentheses, so this cannot # The preprocessor does not yet support arbitrary parentheses, so this cannot
# be parenthesized thus to clarify that the logical AND operator has precedence: # be parenthesized thus to clarify that the logical AND operator has precedence:
@ -107,7 +107,7 @@
<!-- If the windowSoftInputMode adjust* flag changes below, the <!-- If the windowSoftInputMode adjust* flag changes below, the
setSoftInputMode call in BrowserSearch#onStop must also be updated. --> setSoftInputMode call in BrowserSearch#onStop must also be updated. -->
<activity android:name="org.mozilla.gecko.BrowserApp" <activity android:name="@MOZ_ANDROID_BROWSER_INTENT_CLASS@"
android:label="@string/moz_app_displayname" android:label="@string/moz_app_displayname"
android:taskAffinity="@ANDROID_PACKAGE_NAME@.BROWSER" android:taskAffinity="@ANDROID_PACKAGE_NAME@.BROWSER"
android:alwaysRetainTaskState="true" android:alwaysRetainTaskState="true"
@ -134,7 +134,7 @@
for backwards compatibility. --> for backwards compatibility. -->
<activity-alias android:name=".App" <activity-alias android:name=".App"
android:label="@MOZ_APP_DISPLAYNAME@" android:label="@MOZ_APP_DISPLAYNAME@"
android:targetActivity="org.mozilla.gecko.BrowserApp"> android:targetActivity="@MOZ_ANDROID_BROWSER_INTENT_CLASS@">
<!-- android:priority ranges between -1000 and 1000. We never want <!-- android:priority ranges between -1000 and 1000. We never want
another activity to usurp the MAIN action, so we ratchet our another activity to usurp the MAIN action, so we ratchet our
priority up. --> priority up. -->
@ -356,7 +356,7 @@
<!-- Masquerade as the Resolver so that we can be opened from the Marketplace. --> <!-- Masquerade as the Resolver so that we can be opened from the Marketplace. -->
<activity-alias <activity-alias
android:name="com.android.internal.app.ResolverActivity" android:name="com.android.internal.app.ResolverActivity"
android:targetActivity="org.mozilla.gecko.BrowserApp" android:targetActivity="@MOZ_ANDROID_BROWSER_INTENT_CLASS@"
android:exported="true" /> android:exported="true" />
<receiver android:name="org.mozilla.gecko.GeckoUpdateReceiver"> <receiver android:name="org.mozilla.gecko.GeckoUpdateReceiver">

View File

@ -81,10 +81,17 @@ public class AppConstants {
} }
/** /**
* The name of the Java class that launches the browser. * The name of the Java class that represents the android application.
*/ */
public static final String BROWSER_INTENT_CLASS_NAME = "org.mozilla.gecko.BrowserApp"; public static final String MOZ_ANDROID_APPLICATION_CLASS = "@MOZ_ANDROID_APPLICATION_CLASS@";
public static final String SEARCH_INTENT_CLASS_NAME = "org.mozilla.search.SearchActivity"; /**
* The name of the Java class that launches the browser activity.
*/
public static final String MOZ_ANDROID_BROWSER_INTENT_CLASS = "@MOZ_ANDROID_BROWSER_INTENT_CLASS@";
/**
* The name of the Java class that launches the search activity.
*/
public static final String MOZ_ANDROID_SEARCH_INTENT_CLASS = "@MOZ_ANDROID_SEARCH_INTENT_CLASS@";
public static final String GRE_MILESTONE = "@GRE_MILESTONE@"; public static final String GRE_MILESTONE = "@GRE_MILESTONE@";

View File

@ -1869,7 +1869,7 @@ public class BrowserApp extends GeckoApp
} else if (event.equals("Prompt:ShowTop")) { } else if (event.equals("Prompt:ShowTop")) {
// Bring this activity to front so the prompt is visible.. // Bring this activity to front so the prompt is visible..
Intent bringToFrontIntent = new Intent(); Intent bringToFrontIntent = new Intent();
bringToFrontIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.BROWSER_INTENT_CLASS_NAME); bringToFrontIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(bringToFrontIntent); startActivity(bringToFrontIntent);
} else if (event.equals("Accounts:Exist")) { } else if (event.equals("Accounts:Exist")) {

View File

@ -449,7 +449,7 @@ public class CrashReporter extends Activity
String action = "android.intent.action.MAIN"; String action = "android.intent.action.MAIN";
Intent intent = new Intent(action); Intent intent = new Intent(action);
intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
AppConstants.BROWSER_INTENT_CLASS_NAME); AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
intent.putExtra("didRestart", true); intent.putExtra("didRestart", true);
Log.i(LOGTAG, intent.toString()); Log.i(LOGTAG, intent.toString());
startActivity(intent); startActivity(intent);

View File

@ -76,7 +76,7 @@ public class DataReportingNotification {
try { try {
// Launch main App to launch Data choices when notification is clicked. // Launch main App to launch Data choices when notification is clicked.
Intent prefIntent = new Intent(GeckoApp.ACTION_LAUNCH_SETTINGS); Intent prefIntent = new Intent(GeckoApp.ACTION_LAUNCH_SETTINGS);
prefIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.BROWSER_INTENT_CLASS_NAME); prefIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
GeckoPreferences.setResourceToOpen(prefIntent, "preferences_vendor"); GeckoPreferences.setResourceToOpen(prefIntent, "preferences_vendor");
prefIntent.putExtra(ALERT_NAME_DATAREPORTING_NOTIFICATION, true); prefIntent.putExtra(ALERT_NAME_DATAREPORTING_NOTIFICATION, true);

View File

@ -847,7 +847,7 @@ public class GeckoAppShell
shortcutIntent.setAction(GeckoApp.ACTION_HOMESCREEN_SHORTCUT); shortcutIntent.setAction(GeckoApp.ACTION_HOMESCREEN_SHORTCUT);
shortcutIntent.setData(Uri.parse(aURI)); shortcutIntent.setData(Uri.parse(aURI));
shortcutIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, shortcutIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
AppConstants.BROWSER_INTENT_CLASS_NAME); AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
@ -1205,7 +1205,7 @@ public class GeckoAppShell
// Return an intent with a URI that will open the YouTube page in the // Return an intent with a URI that will open the YouTube page in the
// current Fennec instance. // current Fennec instance.
final Class<?> c; final Class<?> c;
final String browserClassName = AppConstants.BROWSER_INTENT_CLASS_NAME; final String browserClassName = AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS;
try { try {
c = Class.forName(browserClassName); c = Class.forName(browserClassName);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {

View File

@ -41,7 +41,7 @@ public class GuestSession {
private static PendingIntent getNotificationIntent(Context context) { private static PendingIntent getNotificationIntent(Context context) {
Intent intent = new Intent(NOTIFICATION_INTENT); Intent intent = new Intent(NOTIFICATION_INTENT);
intent.setClassName(context, AppConstants.BROWSER_INTENT_CLASS_NAME); intent.setClassName(context, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
} }

View File

@ -31,7 +31,7 @@ public class Restarter extends Service {
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("didRestart", true) .putExtra("didRestart", true)
.setClassName(getApplicationContext(), .setClassName(getApplicationContext(),
AppConstants.BROWSER_INTENT_CLASS_NAME); AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
startActivity(restartIntent); startActivity(restartIntent);
Log.d(LOGTAG, "Launched " + restartIntent); Log.d(LOGTAG, "Launched " + restartIntent);
} }

View File

@ -12,7 +12,7 @@ import org.mozilla.gecko.AppConstants;
*/ */
public class GlobalConstants { public class GlobalConstants {
public static final String BROWSER_INTENT_PACKAGE = AppConstants.ANDROID_PACKAGE_NAME; public static final String BROWSER_INTENT_PACKAGE = AppConstants.ANDROID_PACKAGE_NAME;
public static final String BROWSER_INTENT_CLASS = AppConstants.BROWSER_INTENT_CLASS_NAME; public static final String BROWSER_INTENT_CLASS = AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS;
/** /**
* Bug 800244: this signing-level permission protects broadcast intents that * Bug 800244: this signing-level permission protects broadcast intents that

View File

@ -753,6 +753,7 @@ for var in ('ANDROID_PACKAGE_NAME', 'ANDROID_CPU_ARCH',
'GRE_MILESTONE', 'MOZ_APP_BASENAME', 'MOZ_MOZILLA_API_KEY', 'GRE_MILESTONE', 'MOZ_APP_BASENAME', 'MOZ_MOZILLA_API_KEY',
'MOZ_APP_DISPLAYNAME', 'MOZ_APP_ID', 'MOZ_APP_NAME', 'MOZ_APP_DISPLAYNAME', 'MOZ_APP_ID', 'MOZ_APP_NAME',
'MOZ_APP_VENDOR', 'MOZ_APP_VERSION', 'MOZ_CHILD_PROCESS_NAME', 'MOZ_APP_VENDOR', 'MOZ_APP_VERSION', 'MOZ_CHILD_PROCESS_NAME',
'MOZ_ANDROID_APPLICATION_CLASS', 'MOZ_ANDROID_BROWSER_INTENT_CLASS', 'MOZ_ANDROID_SEARCH_INTENT_CLASS',
'MOZ_CRASHREPORTER', 'MOZ_UPDATE_CHANNEL', 'OMNIJAR_NAME', 'MOZ_CRASHREPORTER', 'MOZ_UPDATE_CHANNEL', 'OMNIJAR_NAME',
'OS_TARGET', 'TARGET_XPCOM_ABI'): 'OS_TARGET', 'TARGET_XPCOM_ABI'):
DEFINES[var] = CONFIG[var] DEFINES[var] = CONFIG[var]

View File

@ -408,7 +408,7 @@ public class ShareDialog extends Locales.LocaleAwareActivity implements SendTabT
try { try {
// This can launch in the guest profile. Sorry. // This can launch in the guest profile. Sorry.
final Intent i = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); final Intent i = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
i.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.BROWSER_INTENT_CLASS_NAME); i.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
startActivity(i); startActivity(i);
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
// Nothing much we can do. // Nothing much we can do.

View File

@ -68,7 +68,7 @@ public class TabQueueDispatcher extends Locales.LocaleAwareActivity {
* Start fennec with the supplied intent. * Start fennec with the supplied intent.
*/ */
private void loadNormally(Intent intent) { private void loadNormally(Intent intent) {
intent.setClassName(getApplicationContext(), AppConstants.BROWSER_INTENT_CLASS_NAME); intent.setClassName(getApplicationContext(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
startActivity(intent); startActivity(intent);
finish(); finish();
} }

View File

@ -155,7 +155,7 @@ public class TabQueueHelper {
ThreadUtils.assertNotOnUiThread(); ThreadUtils.assertNotOnUiThread();
Intent resultIntent = new Intent(); Intent resultIntent = new Intent();
resultIntent.setClassName(context, AppConstants.BROWSER_INTENT_CLASS_NAME); resultIntent.setClassName(context, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
resultIntent.setAction(TabQueueHelper.LOAD_URLS_ACTION); resultIntent.setAction(TabQueueHelper.LOAD_URLS_ACTION);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_CANCEL_CURRENT);

View File

@ -190,7 +190,7 @@ public class TabQueueService extends Service {
private void openNow(Intent intent) { private void openNow(Intent intent) {
Intent forwardIntent = new Intent(intent); Intent forwardIntent = new Intent(intent);
forwardIntent.setClassName(getApplicationContext(), AppConstants.BROWSER_INTENT_CLASS_NAME); forwardIntent.setClassName(getApplicationContext(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
forwardIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); forwardIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(forwardIntent); startActivity(forwardIntent);

View File

@ -16,6 +16,12 @@ MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/android/branding/official
# See the --enable-android-min-sdk and --enable-android-max-sdk arguments in configure.in. # See the --enable-android-min-sdk and --enable-android-max-sdk arguments in configure.in.
MOZ_ANDROID_MIN_SDK_VERSION=9 MOZ_ANDROID_MIN_SDK_VERSION=9
# There are several entry points into the Firefox application. These are the names of some of the classes that are
# listed in the Android manifest. They are specified in here to avoid hard-coding them in source code files.
MOZ_ANDROID_APPLICATION_CLASS=org.mozilla.gecko.GeckoApplication
MOZ_ANDROID_BROWSER_INTENT_CLASS=org.mozilla.gecko.BrowserApp
MOZ_ANDROID_SEARCH_INTENT_CLASS=org.mozilla.search.SearchActivity
MOZ_SAFE_BROWSING=1 MOZ_SAFE_BROWSING=1
MOZ_NO_SMART_CARDS=1 MOZ_NO_SMART_CARDS=1

View File

@ -130,7 +130,7 @@ public class PostSearchFragment extends Fragment {
// If the intent URI didn't specify a package, open this in Fennec. // If the intent URI didn't specify a package, open this in Fennec.
if (i.getPackage() == null) { if (i.getPackage() == null) {
i.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.BROWSER_INTENT_CLASS_NAME); i.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL,
TelemetryContract.Method.CONTENT, "search-result"); TelemetryContract.Method.CONTENT, "search-result");
} else { } else {

View File

@ -68,7 +68,7 @@ public class SearchWidget extends AppWidgetProvider {
case ACTION_LAUNCH_BROWSER: case ACTION_LAUNCH_BROWSER:
redirect = buildRedirectIntent(Intent.ACTION_MAIN, redirect = buildRedirectIntent(Intent.ACTION_MAIN,
AppConstants.ANDROID_PACKAGE_NAME, AppConstants.ANDROID_PACKAGE_NAME,
AppConstants.BROWSER_INTENT_CLASS_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS,
intent); intent);
Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH, Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
TelemetryContract.Method.WIDGET, "browser"); TelemetryContract.Method.WIDGET, "browser");
@ -76,7 +76,7 @@ public class SearchWidget extends AppWidgetProvider {
case ACTION_LAUNCH_NEW_TAB: case ACTION_LAUNCH_NEW_TAB:
redirect = buildRedirectIntent(Intent.ACTION_VIEW, redirect = buildRedirectIntent(Intent.ACTION_VIEW,
AppConstants.ANDROID_PACKAGE_NAME, AppConstants.ANDROID_PACKAGE_NAME,
AppConstants.BROWSER_INTENT_CLASS_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS,
intent); intent);
Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH, Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
TelemetryContract.Method.WIDGET, "new-tab"); TelemetryContract.Method.WIDGET, "new-tab");
@ -84,7 +84,7 @@ public class SearchWidget extends AppWidgetProvider {
case ACTION_LAUNCH_SEARCH: case ACTION_LAUNCH_SEARCH:
redirect = buildRedirectIntent(Intent.ACTION_VIEW, redirect = buildRedirectIntent(Intent.ACTION_VIEW,
AppConstants.ANDROID_PACKAGE_NAME, AppConstants.ANDROID_PACKAGE_NAME,
AppConstants.SEARCH_INTENT_CLASS_NAME, AppConstants.MOZ_ANDROID_SEARCH_INTENT_CLASS,
intent); intent);
Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH, Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
TelemetryContract.Method.WIDGET, "search"); TelemetryContract.Method.WIDGET, "search");

View File

@ -1,5 +1,5 @@
<activity <activity
android:name="org.mozilla.search.SearchActivity" android:name="@MOZ_ANDROID_SEARCH_INTENT_CLASS@"
android:launchMode="singleTop" android:launchMode="singleTop"
android:icon="@drawable/search_launcher" android:icon="@drawable/search_launcher"
android:label="@string/search_app_name" android:label="@string/search_app_name"
@ -40,9 +40,9 @@
android:name="org.mozilla.search.SearchPreferenceActivity" android:name="org.mozilla.search.SearchPreferenceActivity"
android:logo="@drawable/search_launcher" android:logo="@drawable/search_launcher"
android:label="@string/search_pref_title" android:label="@string/search_pref_title"
android:parentActivityName="org.mozilla.search.SearchActivity" android:parentActivityName="@MOZ_ANDROID_SEARCH_INTENT_CLASS@"
android:theme="@style/SettingsTheme" > android:theme="@style/SettingsTheme" >
<meta-data <meta-data
android:name="android.support.PARENT_ACTIVITY" android:name="android.support.PARENT_ACTIVITY"
android:value="org.mozilla.search.SearchActivity"/> android:value="@MOZ_ANDROID_SEARCH_INTENT_CLASS@"/>
</activity> </activity>

View File

@ -20,7 +20,7 @@ public class BrowserTestCase extends ActivityInstrumentationTestCase2<Activity>
/** /**
* The Java Class instance that launches the browser. * The Java Class instance that launches the browser.
* <p> * <p>
* This should always agree with {@link AppConstants#BROWSER_INTENT_CLASS_NAME}. * This should always agree with {@link AppConstants#MOZ_ANDROID_BROWSER_INTENT_CLASS}.
*/ */
public static final Class<? extends Activity> BROWSER_INTENT_CLASS; public static final Class<? extends Activity> BROWSER_INTENT_CLASS;
@ -30,7 +30,7 @@ public class BrowserTestCase extends ActivityInstrumentationTestCase2<Activity>
static { static {
Class<? extends Activity> cl; Class<? extends Activity> cl;
try { try {
cl = (Class<? extends Activity>) Class.forName(AppConstants.BROWSER_INTENT_CLASS_NAME); cl = (Class<? extends Activity>) Class.forName(AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
// Oh well. // Oh well.
cl = Activity.class; cl = Activity.class;

View File

@ -43,7 +43,7 @@ public abstract class BaseRobocopTest extends ActivityInstrumentationTestCase2<A
/** /**
* The Java Class instance that launches the browser. * The Java Class instance that launches the browser.
* <p> * <p>
* This should always agree with {@link AppConstants#BROWSER_INTENT_CLASS_NAME}. * This should always agree with {@link AppConstants#MOZ_ANDROID_BROWSER_INTENT_CLASS}.
*/ */
public static final Class<? extends Activity> BROWSER_INTENT_CLASS; public static final Class<? extends Activity> BROWSER_INTENT_CLASS;
@ -51,7 +51,7 @@ public abstract class BaseRobocopTest extends ActivityInstrumentationTestCase2<A
static { static {
Class<? extends Activity> cl; Class<? extends Activity> cl;
try { try {
cl = (Class<? extends Activity>) Class.forName(AppConstants.BROWSER_INTENT_CLASS_NAME); cl = (Class<? extends Activity>) Class.forName(AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
// Oh well. // Oh well.
cl = Activity.class; cl = Activity.class;

Some files were not shown because too many files have changed in this diff Show More