Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-01-21 14:32:34 +01:00
commit 1e0f6191a6
86 changed files with 1757 additions and 1184 deletions

View File

@ -117,7 +117,7 @@ function checkDebuggerPort() {
function initResponsiveDesign() {
Cu.import('resource:///modules/devtools/responsivedesign.jsm');
ResponsiveUIManager.on('on', function(event, {tab:tab}) {
let responsive = tab.__responsiveUI;
let responsive = ResponsiveUIManager.getResponsiveUIForTab(tab);
let document = tab.ownerDocument;
// Only tweak reponsive mode for shell.html tabs.
@ -137,7 +137,7 @@ function initResponsiveDesign() {
}, true);
// Enable touch events
browserWindow.gBrowser.selectedTab.__responsiveUI.enableTouch();
responsive.enableTouch();
});
// Automatically toggle responsive design mode

View File

@ -148,7 +148,8 @@ window.addEventListener('ContentStart', function() {
let chromewidth = window.outerWidth - window.innerWidth;
let chromeheight = window.outerHeight - window.innerHeight + controlsHeight;
if (isMulet) {
let responsive = browserWindow.gBrowser.selectedTab.__responsiveUI;
let tab = browserWindow.gBrowser.selectedTab;
let responsive = ResponsiveUIManager.getResponsiveUIForTab(tab);
responsive.setSize((Math.round(width * scale) + 16*2),
(Math.round(height * scale) + controlsHeight + 61));
} else {

View File

@ -35,9 +35,9 @@ var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptS
let permissionSpecificChecker = {};
XPCOMUtils.defineLazyServiceGetter(this,
"AudioManager",
"@mozilla.org/telephony/audiomanager;1",
"nsIAudioManager");
"TelephonyService",
"@mozilla.org/telephony/telephonyservice;1",
"nsITelephonyService");
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
"resource://gre/modules/SystemAppProxy.jsm");
@ -455,12 +455,29 @@ ContentPermissionPrompt.prototype = {
(function() {
// Do not allow GetUserMedia while in call.
permissionSpecificChecker["audio-capture"] = function(request) {
if (AudioManager.phoneState === Ci.nsIAudioManager.PHONE_STATE_IN_CALL) {
request.cancel();
return true;
} else {
let forbid = false;
try {
// nsITelephonyService.enumerateCalls is synchronous.
TelephonyService.enumerateCalls({
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
enumerateCallStateComplete: function() {},
enumerateCallState: function(callInfo) {
if (callInfo.callState == Ci.nsITelephonyService.CALL_STATE_CONNECTED) {
forbid = true;
}
},
});
} catch (e) {
// No restriction if Telephony service doesn't exist.
return false;
}
if (forbid) {
request.cancel();
}
return forbid;
};
})();

View File

@ -12,15 +12,15 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
@ -116,7 +116,7 @@
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdc5a9f9602652c3c2626e020da03674a2c2e1b6"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="8a05fd72770a3b1fc23f3216a45318ad393fc4ca"/>
<project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
<project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>

View File

@ -19,9 +19,9 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>

View File

@ -15,10 +15,10 @@
<project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
@ -118,7 +118,7 @@
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdc5a9f9602652c3c2626e020da03674a2c2e1b6"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="8a05fd72770a3b1fc23f3216a45318ad393fc4ca"/>
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>

View File

@ -12,15 +12,15 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
@ -116,7 +116,7 @@
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdc5a9f9602652c3c2626e020da03674a2c2e1b6"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="8a05fd72770a3b1fc23f3216a45318ad393fc4ca"/>
<project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
<project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>
@ -129,7 +129,7 @@
<default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
<!-- Emulator specific things -->
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="c0e0019a6ec1a6199a9c7bc4ace041259f3b8512"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f5f7fa2fc26b96d2cbd0af4569c0036fe034bb43"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a510f2d2d579e76421b0c84cd225c249b2da6f8a"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="694cecf256122d0cb3b6a1a4efb4b5c7401db223"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="97d63c256a047b491565d624aea1dd5f1f8593ea"/>

View File

@ -19,9 +19,9 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>

View File

@ -12,15 +12,15 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
@ -111,7 +111,7 @@
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdc5a9f9602652c3c2626e020da03674a2c2e1b6"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="8a05fd72770a3b1fc23f3216a45318ad393fc4ca"/>
<project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>
<project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>

View File

@ -17,8 +17,8 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "5e98dc164b17fd6decb48a9eaddef0e55b82e249",
"git_revision": "e45c5dbdcfc2d598c889dfbea72fa11157422afe",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "d60b9f55a77aa72606acb397b3770adc1bcf5110",
"revision": "ecc956a2747963c2db6edf513cd3a8a75ca8884a",
"repo_path": "integration/gaia-central"
}

View File

@ -17,8 +17,8 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>

View File

@ -15,9 +15,9 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>

View File

@ -15,10 +15,10 @@
<project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
@ -118,7 +118,7 @@
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdc5a9f9602652c3c2626e020da03674a2c2e1b6"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="8a05fd72770a3b1fc23f3216a45318ad393fc4ca"/>
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>

View File

@ -17,9 +17,9 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e98dc164b17fd6decb48a9eaddef0e55b82e249"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="320dad6b787c296ba701bca8377f71ab5fd72ee8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e45c5dbdcfc2d598c889dfbea72fa11157422afe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>

View File

@ -260,6 +260,7 @@ let MozLoopServiceInternal = {
*/
setError: function(errorType, error, actionCallback = null) {
log.debug("setError", errorType, error);
log.trace();
let messageString, detailsString, detailsButtonLabelString, detailsButtonCallback;
const NETWORK_ERRORS = [
Cr.NS_ERROR_CONNECTION_REFUSED,
@ -300,15 +301,24 @@ let MozLoopServiceInternal = {
}
error.friendlyMessage = this.localizedStrings.get(messageString);
error.friendlyDetails = detailsString ?
this.localizedStrings.get(detailsString) :
null;
// Default to the generic "retry_button" text even though the button won't be shown if
// error.friendlyDetails is null.
error.friendlyDetailsButtonLabel = detailsButtonLabelString ?
this.localizedStrings.get(detailsButtonLabelString) :
null;
this.localizedStrings.get("retry_button");
error.friendlyDetailsButtonCallback = actionCallback || detailsButtonCallback || null;
if (detailsString) {
error.friendlyDetails = this.localizedStrings.get(detailsString);
} else if (error.friendlyDetailsButtonCallback) {
// If we have a retry callback but no details use the generic try again string.
error.friendlyDetails = this.localizedStrings.get("generic_failure_no_reason2");
} else {
error.friendlyDetails = null;
}
gErrors.set(errorType, error);
this.notifyStatusChanged();
},
@ -1219,7 +1229,8 @@ this.MozLoopService = {
deferredInitialization.resolve("initialized to logged-in status");
}, error => {
log.debug("MozLoopService: error logging in using cached auth token");
MozLoopServiceInternal.setError("login", error);
let retryFunc = () => MozLoopServiceInternal.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA);
MozLoopServiceInternal.setError("login", error, retryFunc);
deferredInitialization.reject("error logging in using cached auth token");
});
yield completedPromise;
@ -1421,27 +1432,17 @@ this.MozLoopService = {
MozLoopServiceInternal.clearError("profile");
return MozLoopServiceInternal.fxAOAuthTokenData;
});
}).then(tokenData => {
let client = new FxAccountsProfileClient({
serverURL: gFxAOAuthClient.parameters.profile_uri,
token: tokenData.access_token
});
client.fetchProfile().then(result => {
MozLoopServiceInternal.fxAOAuthProfile = result;
}, error => {
log.error("Failed to retrieve profile", error);
this.setError("profile", error);
MozLoopServiceInternal.fxAOAuthProfile = null;
MozLoopServiceInternal.notifyStatusChanged();
});
}).then(Task.async(function* fetchProfile(tokenData) {
yield MozLoopService.fetchFxAProfile(tokenData);
return tokenData;
}).catch(error => {
})).catch(error => {
MozLoopServiceInternal.fxAOAuthTokenData = null;
MozLoopServiceInternal.fxAOAuthProfile = null;
MozLoopServiceInternal.deferredRegistrations.delete(LOOP_SESSION_TYPE.FXA);
throw error;
}).catch((error) => {
MozLoopServiceInternal.setError("login", error);
MozLoopServiceInternal.setError("login", error,
() => MozLoopService.logInToFxA());
// Re-throw for testing
throw error;
});
@ -1485,6 +1486,30 @@ this.MozLoopService = {
}
}),
/**
* Fetch/update the FxA Profile for the logged in user.
*
* @return {Promise} resolving if the profile information was succesfully retrieved
* rejecting if the profile information couldn't be retrieved.
* A profile error is registered.
**/
fetchFxAProfile: function() {
log.debug("fetchFxAProfile");
let client = new FxAccountsProfileClient({
serverURL: gFxAOAuthClient.parameters.profile_uri,
token: MozLoopServiceInternal.fxAOAuthTokenData.access_token
});
return client.fetchProfile().then(result => {
MozLoopServiceInternal.fxAOAuthProfile = result;
MozLoopServiceInternal.clearError("profile");
}, error => {
log.error("Failed to retrieve profile", error, this.fetchFxAProfile.bind(this));
MozLoopServiceInternal.setError("profile", error);
MozLoopServiceInternal.fxAOAuthProfile = null;
MozLoopServiceInternal.notifyStatusChanged();
});
},
openFxASettings: Task.async(function() {
try {
let fxAOAuthClient = yield MozLoopServiceInternal.promiseFxAOAuthClient();

View File

@ -296,8 +296,9 @@ add_task(function* basicAuthorizationAndRegistration() {
is(loopButton.getAttribute("state"), "", "state of loop button should be empty when not logged in");
info("Login");
statusChangedPromise = promiseObserverNotified("loop-status-changed", "login");
let tokenData = yield MozLoopService.logInToFxA();
yield promiseObserverNotified("loop-status-changed", "login");
yield statusChangedPromise;
ise(tokenData.access_token, "code1_access_token", "Check access_token");
ise(tokenData.scope, "profile", "Check scope");
ise(tokenData.token_type, "bearer", "Check token_type");

View File

@ -74,7 +74,6 @@ add_task(function* guest_401() {
Assert.strictEqual(err.code, 401);
Assert.strictEqual(err.friendlyMessage, getLoopString("session_expired_error_description"));
Assert.equal(err.friendlyDetails, null);
Assert.equal(err.friendlyDetailsButtonLabel, null);
});
});
@ -115,7 +114,6 @@ add_task(function* error_404() {
Assert.strictEqual(err.code, 404);
Assert.strictEqual(err.friendlyMessage, getLoopString("generic_failure_title"));
Assert.equal(err.friendlyDetails, null);
Assert.equal(err.friendlyDetailsButtonLabel, null);
});
});
@ -149,7 +147,6 @@ add_task(function* profile_500() {
Assert.strictEqual(err.code, 500);
Assert.strictEqual(err.friendlyMessage, getLoopString("problem_accessing_account"));
Assert.equal(err.friendlyDetails, null);
Assert.equal(err.friendlyDetailsButtonLabel, null);
});
});

View File

@ -77,6 +77,9 @@ add_task(function test_initialize_with_invalid_fxa_token() {
"FXA profile pref should be cleared if token was invalid");
Assert.ok(MozLoopServiceInternal.errors.has("login"),
"Initialization error should have been reported to UI");
Assert.ok(MozLoopServiceInternal.errors.has("login"));
Assert.ok(MozLoopServiceInternal.errors.get("login").friendlyDetailsButtonCallback,
"Check that there is a retry callback");
});
});

View File

@ -1038,7 +1038,7 @@ PlacesToolbar.prototype = {
else {
button = document.createElement("toolbarbutton");
button.className = "bookmark-item";
button.setAttribute("label", aChild.title);
button.setAttribute("label", aChild.title || "");
let icon = aChild.icon;
if (icon)
button.setAttribute("image",
@ -1866,7 +1866,7 @@ PlacesPanelMenuView.prototype = {
button.className = "bookmark-item";
if (typeof this.options.extraClasses.entry == "string")
button.classList.add(this.options.extraClasses.entry);
button.setAttribute("label", aChild.title);
button.setAttribute("label", aChild.title || "");
let icon = aChild.icon;
if (icon)
button.setAttribute("image",

View File

@ -4,7 +4,8 @@
EXTRA_JS_MODULES.devtools += [
'resize-commands.js',
'responsivedesign.jsm',
'responsivedesign-child.js',
'responsivedesign.jsm'
]
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -0,0 +1,129 @@
/* 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/. */
const Ci = Components.interfaces;
const gDeviceSizeWasPageSize = docShell.deviceSizeIsPageSize;
const gFloatingScrollbarsStylesheet = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
let gRequiresFloatingScrollbars;
let active = false;
addMessageListener("ResponsiveMode:Start", startResponsiveMode);
addMessageListener("ResponsiveMode:Stop", stopResponsiveMode);
function startResponsiveMode({data:data}) {
if (active) {
return;
}
addMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
addMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_ALL);
docShell.deviceSizeIsPageSize = true;
gRequiresFloatingScrollbars = data.requiresFloatingScrollbars;
// At this point, a content viewer might not be loaded for this
// docshell. makeScrollbarsFloating will be triggered by onLocationChange.
if (docShell.contentViewer) {
makeScrollbarsFloating();
}
active = true;
sendAsyncMessage("ResponsiveMode:Start:Done");
}
function notifiyOnResize() {
content.addEventListener("resize", () => {
sendAsyncMessage("ResponsiveMode:OnContentResize");
}, false);
sendAsyncMessage("ResponsiveMode:NotifyOnResize:Done");
}
function stopResponsiveMode() {
if (!active) {
return;
}
active = false;
removeMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
removeMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress);
webProgress.removeProgressListener(WebProgressListener);
docShell.deviceSizeIsPageSize = gDeviceSizeWasPageSize;
restoreScrollbars();
sendAsyncMessage("ResponsiveMode:Stop:Done");
}
function makeScrollbarsFloating() {
if (!gRequiresFloatingScrollbars) {
return;
}
let allDocShells = [docShell];
for (let i = 0; i < docShell.childCount; i++) {
let child = docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell);
allDocShells.push(child);
}
for (let d of allDocShells) {
let win = d.contentViewer.DOMDocument.defaultView;
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.loadSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
} catch(e) { }
}
flushStyle();
}
function restoreScrollbars() {
let allDocShells = [docShell];
for (let i = 0; i < docShell.childCount; i++) {
allDocShells.push(docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell));
}
for (let d of allDocShells) {
let win = d.contentViewer.DOMDocument.defaultView;
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.removeSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
} catch(e) { }
}
flushStyle();
}
function flushStyle() {
// Force presContext destruction
let isSticky = docShell.contentViewer.sticky;
docShell.contentViewer.sticky = false;
docShell.contentViewer.hide();
docShell.contentViewer.show();
docShell.contentViewer.sticky = isSticky;
}
function screenshot() {
let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
let width = content.innerWidth;
let height = content.innerHeight;
canvas.mozOpaque = true;
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
ctx.drawWindow(content, content.scrollX, content.scrollY, width, height, "#fff");
sendAsyncMessage("ResponsiveMode:RequestScreenshot:Done", canvas.toDataURL());
}
let WebProgressListener = {
onLocationChange: function onLocationChange(aWebProgress) {
makeScrollbarsFloating();
},
QueryInterface: function QueryInterface(aIID) {
if (aIID.equals(Ci.nsIWebProgressListener) ||
aIID.equals(Ci.nsISupportsWeakReference) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};
sendAsyncMessage("ResponsiveMode:ChildScriptReady");

View File

@ -10,8 +10,8 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource:///modules/devtools/FloatingScrollbars.jsm");
Cu.import("resource://gre/modules/devtools/event-emitter.js");
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
"resource://gre/modules/SystemAppProxy.jsm");
@ -33,6 +33,8 @@ const ROUND_RATIO = 10;
const INPUT_PARSER = /(\d+)[^\d]+(\d+)/;
let ActiveTabs = new Map();
this.ResponsiveUIManager = {
/**
* Check if the a tab is in a responsive mode.
@ -43,8 +45,8 @@ this.ResponsiveUIManager = {
* @param aTab the tab targeted.
*/
toggle: function(aWindow, aTab) {
if (aTab.__responsiveUI) {
aTab.__responsiveUI.close();
if (this.isActiveForTab(aTab)) {
ActiveTabs.get(aTab).close();
} else {
new ResponsiveUI(aWindow, aTab);
}
@ -56,7 +58,14 @@ this.ResponsiveUIManager = {
* @param aTab the tab targeted.
*/
isActiveForTab: function(aTab) {
return !!aTab.__responsiveUI;
return ActiveTabs.has(aTab);
},
/**
* Return the responsive UI controller for a tab.
*/
getResponsiveUIForTab: function(aTab) {
return ActiveTabs.get(aTab);
},
/**
@ -70,19 +79,19 @@ this.ResponsiveUIManager = {
handleGcliCommand: function(aWindow, aTab, aCommand, aArgs) {
switch (aCommand) {
case "resize to":
if (!aTab.__responsiveUI) {
if (!this.isActiveForTab(aTab)) {
new ResponsiveUI(aWindow, aTab);
}
aTab.__responsiveUI.setSize(aArgs.width, aArgs.height);
ActiveTabs.get(aTab).setSize(aArgs.width, aArgs.height);
break;
case "resize on":
if (!aTab.__responsiveUI) {
if (!this.isActiveForTab(aTab)) {
new ResponsiveUI(aWindow, aTab);
}
break;
case "resize off":
if (aTab.__responsiveUI) {
aTab.__responsiveUI.close();
if (this.isActiveForTab(aTab)) {
ActiveTabs.get(aTab).close();
}
break;
case "resize toggle":
@ -115,13 +124,28 @@ function ResponsiveUI(aWindow, aTab)
{
this.mainWindow = aWindow;
this.tab = aTab;
this.mm = this.tab.linkedBrowser.messageManager;
this.tabContainer = aWindow.gBrowser.tabContainer;
this.browser = aTab.linkedBrowser;
this.chromeDoc = aWindow.document;
this.container = aWindow.gBrowser.getBrowserContainer(this.browser);
this.stack = this.container.querySelector(".browserStack");
this._telemetry = new Telemetry();
this._floatingScrollbars = !this.mainWindow.matchMedia("(-moz-overlay-scrollbars)").matches;
this.e10s = !this.browser.contentWindow;
let childOn = () => {
this.mm.removeMessageListener("ResponsiveMode:Start:Done", childOn);
ResponsiveUIManager.emit("on", { tab: this.tab });
}
this.mm.addMessageListener("ResponsiveMode:Start:Done", childOn);
let requiresFloatingScrollbars = !this.mainWindow.matchMedia("(-moz-overlay-scrollbars)").matches;
this.mm.loadFrameScript("resource:///modules/devtools/responsivedesign-child.js", true);
this.mm.addMessageListener("ResponsiveMode:ChildScriptReady", () => {
this.mm.sendAsyncMessage("ResponsiveMode:Start", {
requiresFloatingScrollbars: requiresFloatingScrollbars
});
});
// Try to load presets from prefs
if (Services.prefs.prefHasUserValue("devtools.responsiveUI.presets")) {
@ -163,8 +187,6 @@ function ResponsiveUI(aWindow, aTab)
this.stack.setAttribute("responsivemode", "true");
// Let's bind some callbacks.
this.bound_onPageLoad = this.onPageLoad.bind(this);
this.bound_onPageUnload = this.onPageUnload.bind(this);
this.bound_presetSelected = this.presetSelected.bind(this);
this.bound_handleManualInput = this.handleManualInput.bind(this);
this.bound_addPreset = this.addPreset.bind(this);
@ -184,41 +206,22 @@ function ResponsiveUI(aWindow, aTab)
this.buildUI();
this.checkMenus();
this.docShell = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
this._deviceSizeWasPageSize = this.docShell.deviceSizeIsPageSize;
this.docShell.deviceSizeIsPageSize = true;
try {
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
this.rotate();
}
} catch(e) {}
if (this._floatingScrollbars)
switchToFloatingScrollbars(this.tab);
this.tab.__responsiveUI = this;
ActiveTabs.set(aTab, this);
this._telemetry.toolOpened("responsive");
if (!this.e10s) {
// Touch events support
this.touchEnableBefore = false;
this.touchEventHandler = new TouchEventHandler(this.browser);
this.browser.addEventListener("load", this.bound_onPageLoad, true);
this.browser.addEventListener("unload", this.bound_onPageUnload, true);
if (this.browser.contentWindow.document &&
this.browser.contentWindow.document.readyState == "complete") {
this.onPageLoad();
}
// E10S: We should be using target here. See bug 1028234
ResponsiveUIManager.emit("on", { tab: this.tab });
// Hook to display promotional Developer Edition doorhanger. Only displayed once.
showDoorhanger({
window: this.mainWindow,
@ -239,45 +242,14 @@ ResponsiveUI.prototype = {
}
},
/**
* Window onload / onunload
*/
onPageLoad: function() {
this.touchEventHandler = new TouchEventHandler(this.browser);
if (this.touchEnableBefore) {
this.enableTouch();
}
},
onPageUnload: function(evt) {
// Ignore sub frames unload events
if (evt.target != this.browser.contentDocument)
return;
if (this.closing)
return;
if (this.touchEventHandler) {
this.touchEnableBefore = this.touchEventHandler.enabled;
this.disableTouch();
delete this.touchEventHandler;
}
},
/**
* Destroy the nodes. Remove listeners. Reset the style.
*/
close: function RUI_unload() {
close: function RUI_close() {
if (this.closing)
return;
this.closing = true;
this.docShell.deviceSizeIsPageSize = this._deviceSizeWasPageSize;
this.browser.removeEventListener("load", this.bound_onPageLoad, true);
this.browser.removeEventListener("unload", this.bound_onPageUnload, true);
if (this._floatingScrollbars)
switchToNativeScrollbars(this.tab);
this.unCheckMenus();
// Reset style of the stack.
let style = "max-width: none;" +
@ -296,10 +268,12 @@ ResponsiveUI.prototype = {
this.tabContainer.removeEventListener("TabSelect", this);
this.rotatebutton.removeEventListener("command", this.bound_rotate, true);
this.screenshotbutton.removeEventListener("command", this.bound_screenshot, true);
this.touchbutton.removeEventListener("command", this.bound_touch, true);
this.closebutton.removeEventListener("command", this.bound_close, true);
this.addbutton.removeEventListener("command", this.bound_addPreset, true);
this.removebutton.removeEventListener("command", this.bound_removePreset, true);
if (!this.e10s) {
this.touchbutton.removeEventListener("command", this.bound_touch, true);
}
// Removed elements.
this.container.removeChild(this.toolbar);
@ -317,13 +291,40 @@ ResponsiveUI.prototype = {
this.container.removeAttribute("responsivemode");
this.stack.removeAttribute("responsivemode");
delete this.docShell;
delete this.tab.__responsiveUI;
if (this.touchEventHandler)
ActiveTabs.delete(this.tab);
if (!this.e10s && this.touchEventHandler) {
this.touchEventHandler.stop();
}
this._telemetry.toolClosed("responsive");
// E10S: We should be using target here. See bug 1028234
let childOff = () => {
this.mm.removeMessageListener("ResponsiveMode:Stop:Done", childOff);
ResponsiveUIManager.emit("off", { tab: this.tab });
}
this.mm.addMessageListener("ResponsiveMode:Stop:Done", childOff);
this.tab.linkedBrowser.messageManager.sendAsyncMessage("ResponsiveMode:Stop");
},
/**
* Notify when the content has been resized. Only used in tests.
*/
_test_notifyOnResize: function() {
let deferred = promise.defer();
let mm = this.mm;
this.bound_onContentResize = this.onContentResize.bind(this);
mm.addMessageListener("ResponsiveMode:OnContentResize", this.bound_onContentResize);
mm.sendAsyncMessage("ResponsiveMode:NotifyOnResize");
mm.addMessageListener("ResponsiveMode:NotifyOnResize:Done", function onListeningResize() {
mm.removeMessageListener("ResponsiveMode:NotifyOnResize:Done", onListeningResize);
deferred.resolve();
});
return deferred.promise;
},
onContentResize: function() {
ResponsiveUIManager.emit("contentResize", { tab: this.tab });
},
/**
@ -427,12 +428,6 @@ ResponsiveUI.prototype = {
this.screenshotbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-screenshot";
this.screenshotbutton.addEventListener("command", this.bound_screenshot, true);
this.touchbutton = this.chromeDoc.createElement("toolbarbutton");
this.touchbutton.setAttribute("tabindex", "0");
this.touchbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.touch"));
this.touchbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-touch";
this.touchbutton.addEventListener("command", this.bound_touch, true);
this.closebutton = this.chromeDoc.createElement("toolbarbutton");
this.closebutton.setAttribute("tabindex", "0");
this.closebutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-close";
@ -442,7 +437,16 @@ ResponsiveUI.prototype = {
this.toolbar.appendChild(this.closebutton);
this.toolbar.appendChild(this.menulist);
this.toolbar.appendChild(this.rotatebutton);
if (!this.e10s) {
this.touchbutton = this.chromeDoc.createElement("toolbarbutton");
this.touchbutton.setAttribute("tabindex", "0");
this.touchbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.touch"));
this.touchbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-touch";
this.touchbutton.addEventListener("command", this.bound_touch, true);
this.toolbar.appendChild(this.touchbutton);
}
this.toolbar.appendChild(this.screenshotbutton);
// Resizers
@ -583,8 +587,9 @@ ResponsiveUI.prototype = {
this.selectedItem = menuitem;
}
if (preset.custom)
if (preset.custom) {
this.customMenuitem = menuitem;
}
this.setMenuLabel(menuitem, preset);
fragment.appendChild(menuitem);
@ -662,9 +667,7 @@ ResponsiveUI.prototype = {
if (!promptOk) {
// Prompt has been cancelled
let menuitem = this.customMenuitem;
this.menulist.selectedItem = menuitem;
this.currentPresetKey = this.customPreset.key;
this.menulist.selectedItem = this.selectedItem;
return;
}
@ -762,21 +765,7 @@ ResponsiveUI.prototype = {
* @param aFileName name of the screenshot file (used for tests).
*/
screenshot: function RUI_screenshot(aFileName) {
let window = this.browser.contentWindow;
let document = window.document;
let canvas = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
let width = window.innerWidth;
let height = window.innerHeight;
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
ctx.drawWindow(window, window.scrollX, window.scrollY, width, height, "#fff");
let filename = aFileName;
if (!filename) {
let date = new Date();
let month = ("0" + (date.getMonth() + 1)).substr(-2, 2);
@ -785,12 +774,15 @@ ResponsiveUI.prototype = {
let timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
filename = this.strings.formatStringFromName("responsiveUI.screenshotGeneratedFilename", [dateString, timeString], 2);
}
canvas.toBlob(blob => {
let mm = this.tab.linkedBrowser.messageManager;
let chromeWindow = this.chromeDoc.defaultView;
let url = chromeWindow.URL.createObjectURL(blob);
chromeWindow.saveURL(url, filename + ".png", null, true, true, document.documentURIObject, document);
});
let doc = chromeWindow.document;
function onScreenshot(aMessage) {
mm.removeMessageListener("ResponsiveMode:RequestScreenshot:Done", onScreenshot);
chromeWindow.saveURL(aMessage.data, filename + ".png", null, true, true, doc.documentURIObject, doc);
}
mm.addMessageListener("ResponsiveMode:RequestScreenshot:Done", onScreenshot);
mm.sendAsyncMessage("ResponsiveMode:RequestScreenshot");
},
/**

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
subsuite = devtools
support-files =
head.js
@ -7,8 +6,11 @@ support-files =
[browser_responsive_cmd.js]
[browser_responsivecomputedview.js]
skip-if = e10s # Bug ??????
[browser_responsiveruleview.js]
skip-if = e10s # Bug ??????
[browser_responsiveui.js]
[browser_responsiveui_touch.js]
skip-if = e10s # Bug ?????? - [e10s] re-introduce touch feature in responsive mode
[browser_responsiveuiaddcustompreset.js]
[browser_responsive_devicewidth.js]

View File

@ -10,10 +10,11 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
function test() {
function isOpen() {
return !!gBrowser.selectedTab.__responsiveUI;
return gBrowser.getBrowserContainer(gBrowser.selectedTab.linkedBrowser)
.hasAttribute("responsivemode");
}
helpers.addTabWithToolbar("about:blank", function(options) {
helpers.addTabWithToolbar("data:text/html;charset=utf-8,hi", function(options) {
return helpers.audit(options, [
{
setup: "resize toggle",

View File

@ -7,21 +7,19 @@ function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedTab = gBrowser.addTab("about:logo");
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
startTest();
}, true);
content.location = "data:text/html,mop";
function startTest() {
mgr.once("on", function() {executeSoon(onUIOpen)});
document.getElementById("Tools:ResponsiveUI").doCommand();
}
function onUIOpen() {
instance = gBrowser.selectedTab.__responsiveUI;
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
instance.stack.setAttribute("notransition", "true");
ok(instance, "instance of the module is attached to the tab.");

View File

@ -8,11 +8,12 @@ function test() {
let inspector;
waitForExplicitFinish();
let mgr = ResponsiveUI.ResponsiveUIManager;
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
startTest();
}, true);
content.location = "data:text/html;charset=utf-8,<html><style>" +
@ -43,7 +44,7 @@ function test() {
}
function onUIOpen() {
instance = gBrowser.selectedTab.__responsiveUI;
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
instance.stack.setAttribute("notransition", "true");

View File

@ -11,10 +11,7 @@ function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
gBrowser.selectedBrowser.addEventListener("load", startTest, true);
content.location = "data:text/html;charset=utf-8,<html><style>" +
"div {" +
@ -34,12 +31,13 @@ function test() {
}
function startTest() {
gBrowser.selectedBrowser.removeEventListener("load", startTest, true);
document.getElementById("Tools:ResponsiveUI").doCommand();
executeSoon(onUIOpen);
}
function onUIOpen() {
instance = gBrowser.selectedTab.__responsiveUI;
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
instance.stack.setAttribute("notransition", "true");

View File

@ -1,77 +1,12 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Protocol error (unknownError): Error: Got an invalid root window in DocumentWalker");
function test() {
let instance, widthBeforeClose, heightBeforeClose;
let mgr = ResponsiveUI.ResponsiveUIManager;
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
content.location = "data:text/html,mop";
function startTest() {
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
mgr.once("on", function() {executeSoon(onUIOpen)});
synthesizeKeyFromKeyTag("key_responsiveUI");
}
function onUIOpen() {
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
// Menus are correctly updated?
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked");
instance = gBrowser.selectedTab.__responsiveUI;
ok(instance, "instance of the module is attached to the tab.");
if (instance._floatingScrollbars) {
ensureScrollbarsAreFloating();
}
instance.transitionsEnabled = false;
testPresets();
}
function ensureScrollbarsAreFloating() {
let body = gBrowser.contentDocument.body;
let html = gBrowser.contentDocument.documentElement;
let originalWidth = body.getBoundingClientRect().width;
html.style.overflowY = "scroll"; // Force scrollbars
// Flush. Should not be needed as getBoundingClientRect() should flush,
// but just in case.
gBrowser.contentWindow.getComputedStyle(html).overflowY;
let newWidth = body.getBoundingClientRect().width;
is(originalWidth, newWidth, "Floating scrollbars are presents");
}
function testPresets() {
function testOnePreset(c) {
if (c == 0) {
executeSoon(testCustom);
return;
}
instance.menulist.selectedIndex = c;
let item = instance.menulist.firstChild.childNodes[c];
let [width, height] = extractSizeFromString(item.getAttribute("label"));
is(content.innerWidth, width, "preset " + c + ": dimension valid (width)");
is(content.innerHeight, height, "preset " + c + ": dimension valid (height)");
testOnePreset(c - 1);
}
// Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton
testOnePreset(instance.menulist.firstChild.childNodes.length - 4);
}
SimpleTest.requestCompleteLog();
Task.spawn(function() {
function extractSizeFromString(str) {
let numbers = str.match(/(\d+)[^\d]*(\d+)/);
@ -82,22 +17,79 @@ function test() {
}
}
function testCustom() {
function processStringAsKey(str) {
for (let i = 0, l = str.length; i < l; i++) {
EventUtils.synthesizeKey(str.charAt(i), {});
}
}
yield addTab("data:text/html,mop");
let mgr = ResponsiveUI.ResponsiveUIManager;
synthesizeKeyFromKeyTag("key_responsiveUI");
yield once(mgr, "on");
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
// Menus are correctly updated?
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked");
let instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
let originalWidth = content.innerWidth;
content.location = "data:text/html;charset=utf-8,mop<div style%3D'height%3A5000px'><%2Fdiv>";
let newWidth = content.innerWidth;
is(originalWidth, newWidth, "Floating scrollbars are presents");
yield instance._test_notifyOnResize();
yield nextTick();
instance.transitionsEnabled = false;
// Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton
for (let c = instance.menulist.firstChild.childNodes.length - 4; c >= 0; c--) {
let item = instance.menulist.firstChild.childNodes[c];
let [width, height] = extractSizeFromString(item.getAttribute("label"));
let onContentResize = once(mgr, "contentResize");
instance.menulist.selectedIndex = c;
yield onContentResize;
is(content.innerWidth, width, "preset " + c + ": dimension valid (width)");
is(content.innerHeight, height, "preset " + c + ": dimension valid (height)");
}
// test custom
instance.setSize(100, 100);
yield once(mgr, "contentResize");
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
is(initialWidth, 100, "Width reset to 100");
is(initialHeight, 100, "Height reset to 100");
let x = 2, y = 2;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
x += 20; y += 10;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove"}, window);
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
yield once(mgr, "contentResize");
let expectedWidth = initialWidth + 20;
let expectedHeight = initialHeight + 10;
info("initial width: " + initialWidth);
info("initial height: " + initialHeight);
is(content.innerWidth, expectedWidth, "Size correcty updated (width).");
is(content.innerHeight, expectedHeight, "Size correcty updated (height).");
is(content.innerWidth, expectedWidth, "Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected");
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
let value = instance.menulist.value;
@ -108,71 +100,80 @@ function test() {
[width, height] = extractSizeFromString(value);
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustom2();
}
function testCustom2() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
// With "shift" key pressed
let x = 2, y = 2;
instance.setSize(100, 100);
yield once(mgr, "contentResize");
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
x = 2; y = 2;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
x += 23; y += 13;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", shiftKey: true}, window);
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
let expectedWidth = initialWidth + 20;
let expectedHeight = initialHeight + 10;
is(content.innerWidth, expectedWidth, "with shift: Size correcty updated (width).");
is(content.innerHeight, expectedHeight, "with shift: Size correcty updated (height).");
yield once(mgr, "contentResize");
expectedWidth = initialWidth + 20;
expectedHeight = initialHeight + 10;
is(content.innerWidth, expectedWidth, "with shift: Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "with shift: Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "with shift: Custom menuitem cannot be selected");
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
let value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist")
let [width, height] = extractSizeFromString(label);
label = instance.menulist.firstChild.firstChild.getAttribute("label");
value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist");
[width, height] = extractSizeFromString(label);
is(width, expectedWidth, "Label updated (width).");
is(height, expectedHeight, "Label updated (height).");
[width, height] = extractSizeFromString(value);
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustom3();
}
function testCustom3() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
let x = 2, y = 2;
// With "ctrl" key pressed
instance.setSize(100, 100);
yield once(mgr, "contentResize");
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
x = 2; y = 2;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
x += 60; y += 30;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", ctrlKey: true}, window);
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
let expectedWidth = initialWidth + 10;
let expectedHeight = initialHeight + 5;
is(content.innerWidth, expectedWidth, "with ctrl: Size correcty updated (width).");
is(content.innerHeight, expectedHeight, "with ctrl: Size correcty updated (height).");
yield once(mgr, "contentResize");
expectedWidth = initialWidth + 10;
expectedHeight = initialHeight + 5;
is(content.innerWidth, expectedWidth, "with ctrl: Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "with ctrl: Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "with ctrl: Custom menuitem cannot be selected");
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
let value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist")
let [width, height] = extractSizeFromString(label);
label = instance.menulist.firstChild.firstChild.getAttribute("label");
value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist");
[width, height] = extractSizeFromString(label);
is(width, expectedWidth, "Label updated (width).");
is(height, expectedHeight, "Label updated (height).");
[width, height] = extractSizeFromString(value);
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustomInput();
}
function testCustomInput() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
let expectedWidth = initialWidth - 20;
let expectedHeight = initialHeight - 10;
// Test custom input
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
expectedWidth = initialWidth - 20;
expectedHeight = initialHeight - 10;
let index = instance.menulist.selectedIndex;
let label, value, width, height;
let userInput = expectedWidth + " x " + expectedHeight;
@ -187,6 +188,8 @@ function test() {
// Only the `change` event must change the size
EventUtils.synthesizeKey("VK_RETURN", {});
yield once(mgr, "contentResize");
is(content.innerWidth, expectedWidth, "Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected");
@ -200,17 +203,17 @@ function test() {
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustomInput2();
}
function testCustomInput2() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
let index = instance.menulist.selectedIndex;
// Invalid input
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
index = instance.menulist.selectedIndex;
let expectedValue = initialWidth + "x" + initialHeight;
let expectedLabel = instance.menulist.firstChild.firstChild.getAttribute("label");
let userInput = "I'm wrong";
userInput = "I'm wrong";
instance.menulist.inputField.value = "";
instance.menulist.focus();
@ -221,93 +224,75 @@ function test() {
is(content.innerHeight, initialHeight, "Size hasn't changed (height).");
is(instance.menulist.selectedIndex, index, "Selected item hasn't changed.");
is(instance.menulist.value, expectedValue, "Value has been reset")
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
label = instance.menulist.firstChild.firstChild.getAttribute("label");
is(label, expectedLabel, "Custom menuitem's label hasn't changed");
rotate();
}
function rotate() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
// Rotate
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
info("rotate");
instance.rotate();
yield once(mgr, "contentResize");
is(content.innerWidth, initialHeight, "The width is now the height.");
is(content.innerHeight, initialWidth, "The height is now the width.");
let [width, height] = extractSizeFromString(instance.menulist.firstChild.firstChild.getAttribute("label"));
[width, height] = extractSizeFromString(instance.menulist.firstChild.firstChild.getAttribute("label"));
is(width, initialHeight, "Label updated (width).");
is(height, initialWidth, "Label updated (height).");
widthBeforeClose = content.innerWidth;
heightBeforeClose = content.innerHeight;
let widthBeforeClose = content.innerWidth;
let heightBeforeClose = content.innerHeight;
info("XXX BUG 851296: instance.closing: " + !!instance.closing);
// Restart
mgr.once("off", function() {
info("XXX BUG 851296: 'off' received.");
executeSoon(restart);
});
mgr.toggle(window, gBrowser.selectedTab);
}
function restart() {
info("XXX BUG 851296: restarting.");
info("XXX BUG 851296: __responsiveUI: " + gBrowser.selectedTab.__responsiveUI);
mgr.once("on", function() {
info("XXX BUG 851296: 'on' received.");
executeSoon(onUIOpen2);
});
//XXX BUG 851296: synthesizeKeyFromKeyTag("key_responsiveUI");
yield once(mgr, "off");
mgr.toggle(window, gBrowser.selectedTab);
info("XXX BUG 851296: restart() finished.");
}
function onUIOpen2() {
info("XXX BUG 851296: onUIOpen2.");
let container = gBrowser.getBrowserContainer();
yield once(mgr, "on");
container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
// Menus are correctly updated?
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked");
is(content.innerWidth, widthBeforeClose, "width restored.");
is(content.innerHeight, heightBeforeClose, "height restored.");
mgr.once("off", function() {executeSoon(testScreenshot)});
mgr.toggle(window, gBrowser.selectedTab);
}
// Screenshot
function testScreenshot() {
let isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
if (isWinXP) {
// We have issues testing this on Windows XP.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=848760#c17
return finishUp();
}
if (!isWinXP) {
info("screenshot");
instance.screenshot("responsiveui");
let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
// while(1) until we find the file.
while(true) {
// while(true) until we find the file.
// no need for a timeout, the test will get killed anyway.
info("checking if file exists in 200ms");
function checkIfFileExist() {
let file = FileUtils.getFile("DfltDwnld", [ "responsiveui.png" ]);
if (file.exists()) {
ok(true, "Screenshot file exists");
file.remove(false);
finishUp();
} else {
setTimeout(checkIfFileExist, 200);
break;
}
info("checking if file exists in 200ms");
yield wait(200);
}
checkIfFileExist();
}
function finishUp() {
mgr.toggle(window, gBrowser.selectedTab);
yield once(mgr, "off");
// Menus are correctly updated?
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "false", "menu unchecked");
@ -315,39 +300,6 @@ function test() {
delete instance;
gBrowser.removeCurrentTab();
finish();
}
function synthesizeKeyFromKeyTag(aKeyId) {
let key = document.getElementById(aKeyId);
isnot(key, null, "Successfully retrieved the <key> node");
let modifiersAttr = key.getAttribute("modifiers");
let name = null;
if (key.getAttribute("keycode"))
name = key.getAttribute("keycode");
else if (key.getAttribute("key"))
name = key.getAttribute("key");
isnot(name, null, "Successfully retrieved keycode/key");
let modifiers = {
shiftKey: modifiersAttr.match("shift"),
ctrlKey: modifiersAttr.match("ctrl"),
altKey: modifiersAttr.match("alt"),
metaKey: modifiersAttr.match("meta"),
accelKey: modifiersAttr.match("accel")
}
info("XXX BUG 851296: key name: " + name);
info("XXX BUG 851296: key modifiers: " + JSON.stringify(modifiers));
EventUtils.synthesizeKey(name, modifiers);
}
function processStringAsKey(str) {
for (let i = 0, l = str.length; i < l; i++) {
EventUtils.synthesizeKey(str.charAt(i), {});
}
}
});
}

View File

@ -34,7 +34,7 @@ function test() {
}
function testWithTouch() {
gBrowser.selectedTab.__responsiveUI.enableTouch();
mgr.getResponsiveUIForTab(gBrowser.selectedTab).enableTouch();
let div = content.document.querySelector("div");
let x = 2, y = 2;
EventUtils.synthesizeMouse(div, x, y, {type: "mousedown", isSynthesized: false}, content);
@ -47,7 +47,7 @@ function test() {
}
function testWithTouchAgain() {
gBrowser.selectedTab.__responsiveUI.disableTouch();
mgr.getResponsiveUIForTab(gBrowser.selectedTab).disableTouch();
let div = content.document.querySelector("div");
let x = 2, y = 2;
EventUtils.synthesizeMouse(div, x, y, {type: "mousedown", isSynthesized: false}, content);

View File

@ -2,170 +2,10 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let instance, deletedPresetA, deletedPresetB, oldPrompt;
let mgr = ResponsiveUI.ResponsiveUIManager;
waitForExplicitFinish();
SimpleTest.requestCompleteLog();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
content.location = "data:text/html;charset=utf8,test custom presets in responsive mode";
// This test uses executeSoon() when responsive mode is initialized and when
// it is destroyed such that we get out of the init/destroy loops. If we try
// to init/destroy immediately, without waiting for the next loop, we get
// intermittent test failures.
function startTest() {
// Mocking prompt
oldPrompt = Services.prompt;
Services.prompt = {
value: "",
returnBool: true,
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) {
aValue.value = this.value;
return this.returnBool;
}
};
registerCleanupFunction(() => Services.prompt = oldPrompt);
info("test started, waiting for responsive mode to activate");
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
mgr.once("on", onUIOpen);
synthesizeKeyFromKeyTag("key_responsiveUI");
}
function onUIOpen() {
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = gBrowser.selectedTab.__responsiveUI;
ok(instance, "instance of the module is attached to the tab.");
instance.transitionsEnabled = false;
testAddCustomPreset();
}
function testAddCustomPreset() {
// Tries to add a custom preset and cancel the prompt
let idx = instance.menulist.selectedIndex;
let presetCount = instance.presets.length;
Services.prompt.value = "";
Services.prompt.returnBool = false;
instance.addbutton.doCommand();
is(idx, instance.menulist.selectedIndex, "selected item didn't change after add preset and cancel");
is(presetCount, instance.presets.length, "number of presets didn't change after add preset and cancel");
let customHeight = 123, customWidth = 456;
instance.setSize(customWidth, customHeight);
// Adds the custom preset with "Testing preset"
Services.prompt.value = "Testing preset";
Services.prompt.returnBool = true;
instance.addbutton.doCommand();
instance.menulist.selectedIndex = 1;
info("waiting for responsive mode to turn off");
mgr.once("off", restart);
// Force document reflow to avoid intermittent failures.
info("document height " + document.height);
// We're still in the loop of initializing the responsive mode.
// Let's wait next loop to stop it.
executeSoon(function() {
instance.close();
});
}
function restart() {
info("Restarting Responsive Mode");
mgr.once("on", function() {
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = gBrowser.selectedTab.__responsiveUI;
testCustomPresetInList();
});
// We're still in the loop of destroying the responsive mode.
// Let's wait next loop to start it.
executeSoon(function() {
synthesizeKeyFromKeyTag("key_responsiveUI");
});
}
function testCustomPresetInList() {
let customPresetIndex = getPresetIndex("456x123 (Testing preset)");
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
instance.menulist.selectedIndex = customPresetIndex;
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
testDeleteCustomPresets();
}
function testDeleteCustomPresets() {
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetA = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetB = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
info("waiting for responsive mode to turn off");
mgr.once("off", restartAgain);
// We're still in the loop of initializing the responsive mode.
// Let's wait next loop to stop it.
executeSoon(() => instance.close());
}
function restartAgain() {
info("waiting for responsive mode to turn on");
mgr.once("on", () => {
instance = gBrowser.selectedTab.__responsiveUI;
testCustomPresetsNotInListAnymore();
});
// We're still in the loop of destroying the responsive mode.
// Let's wait next loop to start it.
executeSoon(() => synthesizeKeyFromKeyTag("key_responsiveUI"));
}
function testCustomPresetsNotInListAnymore() {
let customPresetIndex = getPresetIndex(deletedPresetA);
is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore");
customPresetIndex = getPresetIndex(deletedPresetB);
is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore");
executeSoon(finishUp);
}
function finishUp() {
delete instance;
gBrowser.removeCurrentTab();
finish();
}
let instance, deletedPresetA, deletedPresetB, oldPrompt;
function getPresetIndex(presetLabel) {
function testOnePreset(c) {
@ -199,4 +39,121 @@ function test() {
key.doCommand();
}
Task.spawn(function() {
yield addTab("data:text/html;charset=utf8,test custom presets in responsive mode");
let mgr = ResponsiveUI.ResponsiveUIManager;
synthesizeKeyFromKeyTag("key_responsiveUI");
yield once(mgr, "on");
oldPrompt = Services.prompt;
Services.prompt = {
value: "",
returnBool: true,
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) {
aValue.value = this.value;
return this.returnBool;
}
};
registerCleanupFunction(() => Services.prompt = oldPrompt);
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
instance.transitionsEnabled = false;
yield instance._test_notifyOnResize();
// Tries to add a custom preset and cancel the prompt
let idx = instance.menulist.selectedIndex;
let presetCount = instance.presets.length;
Services.prompt.value = "";
Services.prompt.returnBool = false;
instance.addbutton.doCommand();
is(idx, instance.menulist.selectedIndex, "selected item didn't change after add preset and cancel");
is(presetCount, instance.presets.length, "number of presets didn't change after add preset and cancel");
// Adds the custom preset with "Testing preset"
Services.prompt.value = "Testing preset";
Services.prompt.returnBool = true;
let customHeight = 123, customWidth = 456;
instance.startResizing({});
instance.setSize(customWidth, customHeight);
instance.stopResizing({});
instance.addbutton.doCommand();
// Force document reflow to avoid intermittent failures.
info("document height " + document.height);
instance.close();
info("waiting for responsive mode to turn off");
yield once(mgr, "off");
// We're still in the loop of initializing the responsive mode.
// Let's wait next loop to stop it.
yield nextTick();
synthesizeKeyFromKeyTag("key_responsiveUI");
yield once(mgr, "on");
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
let customPresetIndex = getPresetIndex("456x123 (Testing preset)");
info(customPresetIndex);
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
instance.menulist.selectedIndex = customPresetIndex;
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetA = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetB = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
yield nextTick();
instance.close();
yield once(mgr, "off");
synthesizeKeyFromKeyTag("key_responsiveUI");
info("waiting for responsive mode to turn on");
yield once(mgr, "on");
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
customPresetIndex = getPresetIndex(deletedPresetA);
is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore");
customPresetIndex = getPresetIndex(deletedPresetB);
is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore");
yield nextTick();
gBrowser.removeCurrentTab();
finish();
});
}

View File

@ -123,3 +123,92 @@ function openComputedView() {
function openRuleView() {
return openInspectorSideBar("ruleview");
}
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab
* @return a promise that resolves to the tab object when the url is loaded
*/
let addTab = Task.async(function* (url) {
info("Adding a new tab with URL: '" + url + "'");
window.focus();
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
let browser = tab.linkedBrowser;
yield once(browser, "load", true);
info("URL '" + url + "' loading complete");
return tab;
});
/**
* Wait for eventName on target.
* @param {Object} target An observable object that either supports on/off or
* addEventListener/removeEventListener
* @param {String} eventName
* @param {Boolean} useCapture Optional, for addEventListener/removeEventListener
* @return A promise that resolves when the event has been handled
*/
function once(target, eventName, useCapture=false) {
info("Waiting for event: '" + eventName + "' on " + target + ".");
let deferred = promise.defer();
for (let [add, remove] of [
["addEventListener", "removeEventListener"],
["addListener", "removeListener"],
["on", "off"]
]) {
if ((add in target) && (remove in target)) {
target[add](eventName, function onEvent(...aArgs) {
info("Got event: '" + eventName + "' on " + target + ".");
target[remove](eventName, onEvent, useCapture);
deferred.resolve.apply(deferred, aArgs);
}, useCapture);
break;
}
}
return deferred.promise;
}
function wait(ms) {
let def = promise.defer();
setTimeout(def.resolve, ms);
return def.promise;
}
function synthesizeKeyFromKeyTag(aKeyId) {
let key = document.getElementById(aKeyId);
isnot(key, null, "Successfully retrieved the <key> node");
let modifiersAttr = key.getAttribute("modifiers");
let name = null;
if (key.getAttribute("keycode"))
name = key.getAttribute("keycode");
else if (key.getAttribute("key"))
name = key.getAttribute("key");
isnot(name, null, "Successfully retrieved keycode/key");
let modifiers = {
shiftKey: modifiersAttr.match("shift"),
ctrlKey: modifiersAttr.match("ctrl"),
altKey: modifiersAttr.match("alt"),
metaKey: modifiersAttr.match("meta"),
accelKey: modifiersAttr.match("accel")
}
EventUtils.synthesizeKey(name, modifiers);
}
function nextTick() {
let def = promise.defer();
executeSoon(() => def.resolve())
return def.promise;
}

View File

@ -1,126 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
this.EXPORTED_SYMBOLS = [ "switchToFloatingScrollbars", "switchToNativeScrollbars" ];
Cu.import("resource://gre/modules/Services.jsm");
let URL = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
let trackedTabs = new WeakMap();
/**
* Switch to floating scrollbars, à la mobile.
*
* @param aTab the targeted tab.
*
*/
this.switchToFloatingScrollbars = function switchToFloatingScrollbars(aTab) {
let mgr = trackedTabs.get(aTab);
if (!mgr) {
mgr = new ScrollbarManager(aTab);
}
mgr.switchToFloating();
}
/**
* Switch to original native scrollbars.
*
* @param aTab the targeted tab.
*
*/
this.switchToNativeScrollbars = function switchToNativeScrollbars(aTab) {
let mgr = trackedTabs.get(aTab);
if (mgr) {
mgr.reset();
}
}
function ScrollbarManager(aTab) {
trackedTabs.set(aTab, this);
this.attachedTab = aTab;
this.attachedBrowser = aTab.linkedBrowser;
this.reset = this.reset.bind(this);
this.switchToFloating = this.switchToFloating.bind(this);
this.attachedTab.addEventListener("TabClose", this.reset, true);
this.attachedBrowser.addEventListener("DOMContentLoaded", this.switchToFloating, true);
}
ScrollbarManager.prototype = {
get win() {
return this.attachedBrowser.contentWindow;
},
/*
* Change the look of the scrollbars.
*/
switchToFloating: function() {
let windows = this.getInnerWindows(this.win);
windows.forEach(this.injectStyleSheet);
this.forceStyle();
},
/*
* Reset the look of the scrollbars.
*/
reset: function() {
let windows = this.getInnerWindows(this.win);
windows.forEach(this.removeStyleSheet);
this.forceStyle(this.attachedBrowser);
this.attachedBrowser.removeEventListener("DOMContentLoaded", this.switchToFloating, true);
this.attachedTab.removeEventListener("TabClose", this.reset, true);
trackedTabs.delete(this.attachedTab);
},
/*
* Toggle the display property of the window to force the style to be applied.
*/
forceStyle: function() {
let parentWindow = this.attachedBrowser.ownerDocument.defaultView;
let display = parentWindow.getComputedStyle(this.attachedBrowser).display; // Save display value
this.attachedBrowser.style.display = "none";
parentWindow.getComputedStyle(this.attachedBrowser).display; // Flush
this.attachedBrowser.style.display = display; // Restore
},
/*
* return all the window objects present in the hiearchy of a window.
*/
getInnerWindows: function(win) {
let iframes = win.document.querySelectorAll("iframe");
let innerWindows = [];
for (let iframe of iframes) {
innerWindows = innerWindows.concat(this.getInnerWindows(iframe.contentWindow));
}
return [win].concat(innerWindows);
},
/*
* Append the new scrollbar style.
*/
injectStyleSheet: function(win) {
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.loadSheet(URL, win.AGENT_SHEET);
}catch(e) {}
},
/*
* Remove the injected stylesheet.
*/
removeStyleSheet: function(win) {
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.removeSheet(URL, win.AGENT_SHEET);
}catch(e) {}
},
}

View File

@ -12,7 +12,6 @@ EXTRA_JS_MODULES.devtools += [
'Curl.jsm',
'DeveloperToolbar.jsm',
'DOMHelpers.jsm',
'FloatingScrollbars.jsm',
'Jsbeautify.jsm',
'Parser.jsm',
'SplitView.jsm',

View File

@ -41,7 +41,7 @@ let WebAudioEditorController = {
/**
* Listen for events emitted by the current tab target.
*/
initialize: function() {
initialize: Task.async(function* () {
telemetry.toolOpened("webaudioeditor");
this._onTabNavigated = this._onTabNavigated.bind(this);
this._onThemeChange = this._onThemeChange.bind(this);
@ -60,7 +60,10 @@ let WebAudioEditorController = {
// the graph's marker styling, since we can't do this
// with CSS
gDevTools.on("pref-changed", this._onThemeChange);
},
// Store the AudioNode definitions from the WebAudioFront
AUDIO_NODE_DEFINITION = yield gFront.getDefinition();
}),
/**
* Remove events emitted by the current tab target.

View File

@ -15,6 +15,7 @@ const { require } = devtools;
let { console } = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
let { EventTarget } = require("sdk/event/target");
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
const { Class } = require("sdk/core/heritage");
const EventEmitter = require("devtools/toolkit/event-emitter");
@ -25,6 +26,10 @@ const telemetry = new Telemetry();
devtools.lazyImporter(this, "LineGraphWidget",
"resource:///modules/devtools/Graphs.jsm");
// `AUDIO_NODE_DEFINITION` defined in the controller's initialization,
// which describes all the properties of an AudioNode
let AUDIO_NODE_DEFINITION;
// Override DOM promises with Promise.jsm helpers
const { defer, all } = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;

View File

@ -35,6 +35,12 @@ const AudioNodeModel = Class({
*/
setup: Task.async(function* () {
yield this.getType();
// Query bypass status on start up
this._bypassed = yield this.isBypassed();
// Store whether or not this node is bypassable in the first place
this.bypassable = !AUDIO_NODE_DEFINITION[this.type].unbypassable;
}),
/**
@ -75,6 +81,26 @@ const AudioNodeModel = Class({
coreEmit(this, "disconnect", this);
},
/**
* Gets the bypass status of the audio node.
*
* @return Promise->Boolean
*/
isBypassed: function () {
return this.actor.isBypassed();
},
/**
* Sets the bypass value of an AudioNode.
*
* @param Boolean enable
* @return Promise
*/
bypass: function (enable) {
this._bypassed = enable;
return this.actor.bypass(enable).then(() => coreEmit(this, "bypass", this, enable));
},
/**
* Returns a promise that resolves to an array of objects containing
* both a `param` name property and a `value` property.
@ -106,7 +132,8 @@ const AudioNodeModel = Class({
graph.addNode(this.id, {
type: this.type,
label: this.type.replace(/Node$/, ""),
id: this.id
id: this.id,
bypassed: this._bypassed
});
},
@ -279,7 +306,7 @@ const AudioNodesCollection = Class({
this.remove(node);
} else {
// Pipe the event to the collection
coreEmit(this, eventName, [node].concat(args));
coreEmit(this, eventName, node, ...args);
}
}
});

View File

@ -52,6 +52,7 @@ support-files =
[browser_wa_inspector.js]
[browser_wa_inspector-toggle.js]
[browser_wa_inspector-bypass-01.js]
[browser_wa_properties-view.js]
[browser_wa_properties-view-edit-01.js]

View File

@ -15,14 +15,22 @@ add_task(function*() {
is((yield gainNode.isBypassed()), false, "Nodes start off unbypassed.");
info("Calling node#bypass(true)");
yield gainNode.bypass(true);
let isBypassed = yield gainNode.bypass(true);
is(isBypassed, true, "node.bypass(true) resolves to true");
is((yield gainNode.isBypassed()), true, "Node is now bypassed.");
info("Calling node#bypass(false)");
yield gainNode.bypass(false);
isBypassed = yield gainNode.bypass(false);
is(isBypassed, false, "node.bypass(false) resolves to false");
is((yield gainNode.isBypassed()), false, "Node back to being unbypassed.");
info("Calling node#bypass(true) on unbypassable node");
isBypassed = yield destNode.bypass(true);
is(isBypassed, false, "node.bypass(true) resolves to false for unbypassable node");
is((yield gainNode.isBypassed()), false, "Unbypassable node is unaffect");
yield removeTab(target.tab);
});

View File

@ -20,11 +20,12 @@ add_task(function*() {
waitForGraphRendered(panelWin, 3, 2)
]);
let nodeIds = actors.map(actor => actor.actorID);
let $tabbox = $("#web-audio-editor-tabs");
// Oscillator node
click(panelWin, findGraphNode(panelWin, nodeIds[1]));
yield waitForInspectorRender(panelWin, EVENTS);
click(panelWin, $("#automation-tab"));
$tabbox.selectedIndex = 1;
ok(isVisible($("#automation-graph-container")), "graph container should be visible");
ok(isVisible($("#automation-content")), "automation content should be visible");
@ -34,17 +35,17 @@ add_task(function*() {
// Gain node
click(panelWin, findGraphNode(panelWin, nodeIds[2]));
yield waitForInspectorRender(panelWin, EVENTS);
click(panelWin, $("#automation-tab"));
$tabbox.selectedIndex = 1;
ok(!isVisible($("#automation-graph-container")), "graph container should be visible");
ok(isVisible($("#automation-content")), "automation content should not be visible");
ok(!isVisible($("#automation-graph-container")), "graph container should not be visible");
ok(isVisible($("#automation-content")), "automation content should be visible");
ok(isVisible($("#automation-no-events")), "no-events panel should be visible");
ok(!isVisible($("#automation-empty")), "empty panel should not be visible");
// destination node
click(panelWin, findGraphNode(panelWin, nodeIds[0]));
yield waitForInspectorRender(panelWin, EVENTS);
click(panelWin, $("#automation-tab"));
$tabbox.selectedIndex = 1;
ok(!isVisible($("#automation-graph-container")), "graph container should not be visible");
ok(!isVisible($("#automation-content")), "automation content should not be visible");

View File

@ -0,0 +1,67 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that nodes are correctly bypassed when bypassing.
*/
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
reload(target);
let [actors] = yield Promise.all([
get3(gFront, "create-node"),
waitForGraphRendered(panelWin, 3, 2)
]);
let nodeIds = actors.map(actor => actor.actorID);
click(panelWin, findGraphNode(panelWin, nodeIds[1]));
// Wait for the node to be set as well as the inspector to come fully into the view
yield Promise.all([
waitForInspectorRender(panelWin, EVENTS),
once(panelWin, EVENTS.UI_INSPECTOR_TOGGLED)
]);
let $bypass = $("toolbarbutton.bypass");
is((yield actors[1].isBypassed()), false, "AudioNodeActor is not bypassed by default.")
is($bypass.checked, true, "Button is 'on' for normal nodes");
is($bypass.disabled, false, "Bypass button is not disabled for normal nodes");
command($bypass);
yield gAudioNodes.once("bypass");
is((yield actors[1].isBypassed()), true, "AudioNodeActor is bypassed.")
is($bypass.checked, false, "Button is 'off' when clicked");
is($bypass.disabled, false, "Bypass button is not disabled after click");
ok(findGraphNode(panelWin, nodeIds[1]).classList.contains("bypassed"),
"AudioNode has 'bypassed' class.");
command($bypass);
yield gAudioNodes.once("bypass");
is((yield actors[1].isBypassed()), false, "AudioNodeActor is no longer bypassed.")
is($bypass.checked, true, "Button is back on when clicked");
is($bypass.disabled, false, "Bypass button is not disabled after click");
ok(!findGraphNode(panelWin, nodeIds[1]).classList.contains("bypassed"),
"AudioNode no longer has 'bypassed' class.");
click(panelWin, findGraphNode(panelWin, nodeIds[0]));
yield once(panelWin, EVENTS.UI_INSPECTOR_NODE_SET);
is((yield actors[0].isBypassed()), false, "Unbypassable AudioNodeActor is not bypassed.");
is($bypass.checked, false, "Button is 'off' for unbypassable nodes");
is($bypass.disabled, true, "Bypass button is disabled for unbypassable nodes");
command($bypass);
is((yield actors[0].isBypassed()), false,
"Clicking button on unbypassable node does not change bypass state on actor.");
is($bypass.checked, false, "Button is still 'off' for unbypassable nodes");
is($bypass.disabled, true, "Bypass button is still disabled for unbypassable nodes");
yield teardown(target);
});

View File

@ -34,8 +34,6 @@ add_task(function*() {
"InspectorView empty message should still be visible.");
ok(!isVisible($("#web-audio-editor-tabs")),
"InspectorView tabs view should still be hidden.");
is($("#web-audio-inspector-title").value, "AudioNode Inspector",
"Inspector should still have default title.");
// Close inspector pane
$("#inspector-pane-toggle").click();
@ -59,8 +57,6 @@ add_task(function*() {
"Empty message hides even when loading node while open.");
ok(isVisible($("#web-audio-editor-tabs")),
"Switches to tab view when loading node while open.");
is($("#web-audio-inspector-title").value, "Oscillator",
"Inspector title updates when loading node while open.");
yield teardown(target);
});

View File

@ -27,8 +27,6 @@ add_task(function*() {
"InspectorView empty message should show when no node's selected.");
ok(!isVisible($("#web-audio-editor-tabs")),
"InspectorView tabs view should be hidden when no node's selected.");
is($("#web-audio-inspector-title").value, "AudioNode Inspector",
"Inspector should have default title when empty.");
// Wait for the node to be set as well as the inspector to come fully into the view
let nodeSet = Promise.all([
@ -44,9 +42,6 @@ add_task(function*() {
ok(isVisible($("#web-audio-editor-tabs")),
"InspectorView tabs view visible when node selected.");
is($("#web-audio-inspector-title").value, "Oscillator",
"Inspector should have the node title when a node is selected.");
is($("#web-audio-editor-tabs").selectedIndex, 0,
"default tab selected should be the parameters tab.");
@ -54,8 +49,5 @@ add_task(function*() {
click(panelWin, findGraphNode(panelWin, nodeIds[2]));
yield nodeSet;
is($("#web-audio-inspector-title").value, "Gain",
"Inspector title updates when a new node is selected.");
yield teardown(target);
});

View File

@ -318,6 +318,12 @@ function mouseOver (win, element) {
EventUtils.sendMouseEvent({ type: "mouseover" }, element, win);
}
function command (button) {
let ev = button.ownerDocument.createEvent("XULCommandEvent");
ev.initCommandEvent("command", true, true, button.ownerDocument.defaultView, 0, false, false, false, false, null);
button.dispatchEvent(ev);
}
function isVisible (element) {
return !element.getAttribute("hidden");
}

View File

@ -36,13 +36,13 @@ let ContextView = {
* Initialization function, called when the tool is started.
*/
initialize: function() {
this._onGraphNodeClick = this._onGraphNodeClick.bind(this);
this._onGraphClick = this._onGraphClick.bind(this);
this._onThemeChange = this._onThemeChange.bind(this);
this._onStartContext = this._onStartContext.bind(this);
this._onEvent = this._onEvent.bind(this);
this.draw = debounce(this.draw.bind(this), GRAPH_DEBOUNCE_TIMER);
$('#graph-target').addEventListener('click', this._onGraphNodeClick, false);
$("#graph-target").addEventListener("click", this._onGraphClick, false);
window.on(EVENTS.THEME_CHANGE, this._onThemeChange);
window.on(EVENTS.START_CONTEXT, this._onStartContext);
@ -58,7 +58,8 @@ let ContextView = {
if (this._zoomBinding) {
this._zoomBinding.on("zoom", null);
}
$('#graph-target').removeEventListener('click', this._onGraphNodeClick, false);
$("#graph-target").removeEventListener("click", this._onGraphClick, false);
window.off(EVENTS.THEME_CHANGE, this._onThemeChange);
window.off(EVENTS.START_CONTEXT, this._onStartContext);
gAudioNodes.off("*", this._onEvent);
@ -126,6 +127,15 @@ let ContextView = {
return $(".nodes > g[data-id='" + actorID + "']");
},
/**
* Sets the appropriate class on an SVG node when its bypass
* status is toggled.
*/
_bypassNode: function (node, enabled) {
let el = this._getNodeByID(node.id);
el.classList[enabled ? "add" : "remove"]("bypassed");
},
/**
* This method renders the nodes currently available in `gAudioNodes` and is
* throttled to be called at most every `GRAPH_DEBOUNCE_TIMER` milliseconds.
@ -143,42 +153,33 @@ let ContextView = {
let oldDrawNodes = renderer.drawNodes();
renderer.drawNodes(function(graph, root) {
let svgNodes = oldDrawNodes(graph, root);
svgNodes.attr("class", (n) => {
svgNodes.each(function (n) {
let node = graph.node(n);
return "audionode type-" + node.type;
});
svgNodes.attr("data-id", (n) => {
let node = graph.node(n);
return node.id;
let classString = "audionode type-" + node.type + (node.bypassed ? " bypassed" : "");
this.setAttribute("class", classString);
this.setAttribute("data-id", node.id);
this.setAttribute("data-type", node.type);
});
return svgNodes;
});
// Post-render manipulation of edges
// TODO do all of this more efficiently, rather than
// using the direct D3 helper utilities to loop over each
// edge several times
let oldDrawEdgePaths = renderer.drawEdgePaths();
let defaultClasses = "edgePath enter";
renderer.drawEdgePaths(function(graph, root) {
let svgEdges = oldDrawEdgePaths(graph, root);
svgEdges.attr("data-source", (n) => {
let edge = graph.edge(n);
return edge.source;
});
svgEdges.attr("data-target", (n) => {
let edge = graph.edge(n);
return edge.target;
});
svgEdges.attr("data-param", (n) => {
let edge = graph.edge(n);
return edge.param ? edge.param : null;
});
svgEdges.each(function (e) {
let edge = graph.edge(e);
// We have to manually specify the default classes on the edges
// as to not overwrite them
let defaultClasses = "edgePath enter";
svgEdges.attr("class", (n) => {
let edge = graph.edge(n);
return defaultClasses + (edge.param ? (" param-connection " + edge.param) : "");
let edgeClass = defaultClasses + (edge.param ? (" param-connection " + edge.param) : "");
this.setAttribute("data-source", edge.source);
this.setAttribute("data-target", edge.target);
this.setAttribute("data-param", edge.param ? edge.param : null);
this.setAttribute("class", edgeClass);
});
return svgEdges;
@ -263,6 +264,11 @@ let ContextView = {
* in GRAPH_REDRAW_EVENTS) qualify as a redraw event.
*/
_onEvent: function (eventName, ...args) {
// If bypassing, just toggle the class on the SVG node
// rather than rerendering everything
if (eventName === "bypass") {
this._bypassNode.apply(this, args);
}
if (~GRAPH_REDRAW_EVENTS.indexOf(eventName)) {
this.draw();
}
@ -280,12 +286,12 @@ let ContextView = {
},
/**
* Fired when a node in the svg graph is clicked. Used to handle triggering the AudioNodePane.
* Fired when a click occurs in the graph.
*
* @param Event e
* Click event.
*/
_onGraphNodeClick: function (e) {
_onGraphClick: function (e) {
let node = findGraphNodeParent(e.target);
// If node not found (clicking outside of an audio node in the graph),
// then ignore this event

View File

@ -43,8 +43,12 @@ let InspectorView = {
this._onNodeSelect = this._onNodeSelect.bind(this);
this._onDestroyNode = this._onDestroyNode.bind(this);
this._onResize = this._onResize.bind(this);
this._onCommandClick = this._onCommandClick.bind(this);
this.splitter.addEventListener("mouseup", this._onResize);
for (let $el of $$("#audio-node-toolbar toolbarbutton")) {
$el.addEventListener("command", this._onCommandClick);
}
window.on(EVENTS.UI_SELECT_NODE, this._onNodeSelect);
gAudioNodes.on("remove", this._onDestroyNode);
},
@ -55,6 +59,11 @@ let InspectorView = {
destroy: function () {
this.unbindToggle();
this.splitter.removeEventListener("mouseup", this._onResize);
$("#audio-node-toolbar toolbarbutton").removeEventListener("command", this._onCommandClick);
for (let $el of $$("#audio-node-toolbar toolbarbutton")) {
$el.removeEventListener("command", this._onCommandClick);
}
window.off(EVENTS.UI_SELECT_NODE, this._onNodeSelect);
gAudioNodes.off("remove", this._onDestroyNode);
@ -67,7 +76,7 @@ let InspectorView = {
* Takes a AudioNodeView `node` and sets it as the current
* node and scaffolds the inspector view based off of the new node.
*/
setCurrentAudioNode: function (node) {
setCurrentAudioNode: Task.async(function* (node) {
this._currentNode = node || null;
// If no node selected, set the inspector back to "no AudioNode selected"
@ -81,10 +90,10 @@ let InspectorView = {
else {
$("#web-audio-editor-details-pane-empty").setAttribute("hidden", "true");
$("#web-audio-editor-tabs").removeAttribute("hidden");
this._setTitle();
yield this._buildToolbar();
window.emit(EVENTS.UI_INSPECTOR_NODE_SET, this._currentNode.id);
}
},
}),
/**
* Returns the current AudioNodeView.
@ -104,14 +113,25 @@ let InspectorView = {
this.hideImmediately();
},
/**
* Sets the title of the Inspector view
*/
_setTitle: function () {
let node = this._currentNode;
let title = node.type.replace(/Node$/, "");
$("#web-audio-inspector-title").setAttribute("value", title);
},
_buildToolbar: Task.async(function* () {
let node = this.getCurrentAudioNode();
let bypassable = node.bypassable;
let bypassed = yield node.isBypassed();
let button = $("#audio-node-toolbar .bypass");
if (!bypassable) {
button.setAttribute("disabled", true);
} else {
button.removeAttribute("disabled");
}
if (!bypassable || bypassed) {
button.removeAttribute("checked");
} else {
button.setAttribute("checked", true);
}
}),
/**
* Event handlers
@ -140,5 +160,26 @@ let InspectorView = {
if (this._currentNode && this._currentNode.id === node.id) {
this.setCurrentAudioNode(null);
}
},
_onCommandClick: function (e) {
let node = this.getCurrentAudioNode();
let button = e.target;
let command = button.getAttribute("data-command");
let checked = button.getAttribute("checked");
if (button.getAttribute("disabled")) {
return;
}
if (command === "bypass") {
if (checked) {
button.removeAttribute("checked");
node.bypass(true);
} else {
button.setAttribute("checked", true);
node.bypass(false);
}
}
}
};

View File

@ -3,10 +3,10 @@
- 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/. -->
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/webaudioeditor.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/webaudioeditor.dtd">
%debuggerDTD;
@ -79,9 +79,6 @@
</hbox>
<splitter id="inspector-splitter" class="devtools-side-splitter"/>
<vbox id="web-audio-inspector" hidden="true">
<hbox class="devtools-toolbar">
<label id="web-audio-inspector-title" value="&webAudioEditorUI.inspectorTitle;"></label>
</hbox>
<deck id="web-audio-editor-details-pane" flex="1">
<vbox id="web-audio-editor-details-pane-empty" flex="1">
<label value="&webAudioEditorUI.inspectorEmpty;"></label>
@ -89,6 +86,13 @@
<tabbox id="web-audio-editor-tabs"
class="devtools-sidebar-tabs"
handleCtrlTab="false">
<toolbar id="audio-node-toolbar" class="devtools-toolbar">
<hbox class="devtools-toolbarbutton-group">
<toolbarbutton class="bypass devtools-toolbarbutton"
data-command="bypass"
tabindex="0"/>
</hbox>
</toolbar>
<tabs>
<tab id="properties-tab"
label="&webAudioEditorUI.tab.properties;"/>

View File

@ -33,3 +33,7 @@ collapseInspector=Collapse inspector
# that expands the inspector in the web audio tool UI.
expandInspector=Expand inspector
# LOCALIZATION NOTE (webAudioEditorTooltipBypass): This is the tooltip for the
# button that bypasses an AudioNode
webAudioEditorTooltipBypass=Bypass AudioNode

View File

@ -229,6 +229,7 @@ browser.jar:
skin/classic/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)

View File

@ -360,6 +360,7 @@ browser.jar:
skin/classic/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)

View File

@ -13,4 +13,15 @@
<feFuncB type="table" tableValues=".6 0"/>
</feComponentTransfer>
</filter>
<!-- Web Audio Gradients -->
<linearGradient id="bypass-light" x1="6%" y1="8%" x2="12%" y2="12%" spreadMethod="repeat">
<stop offset="0%" stop-color="#f0f1f2"/> <!-- theme-toolbar-background -->
<stop offset="50%" stop-color="#fff"/>
</linearGradient>
<linearGradient id="bypass-dark" x1="6%" y1="8%" x2="12%" y2="12%" spreadMethod="repeat">
<stop offset="0%" stop-color="#343c45"/> <!-- theme-toolbar-background -->
<stop offset="50%" stop-color="transparent"/>
</linearGradient>
</svg>

Before

Width:  |  Height:  |  Size: 592 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,14 @@
<!--
Logo from raphaeljs.com, MIT License
Copyright © 2008 Dmitry Baranovskiy
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
-->
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
<path stroke="#edf0f1" d="m10.89891,2.50043c-0.49827,-0.24134 -1.09841,-0.03411 -1.34129,0.46514c-0.24185,0.49928 -0.03311,1.09942 0.46517,1.34128c1.56306,0.76071 2.64193,2.36094 2.64092,4.21555c-0.00501,2.58626 -2.09749,4.6787 -4.68322,4.68321c-2.58623,-0.005 -4.67869,-2.09746 -4.68371,-4.68321c-0.001,-1.85561 1.07834,-3.45731 2.64294,-4.21654c0.49928,-0.24185 0.7065,-0.84201 0.46514,-1.34129c-0.24185,-0.49825 -0.84098,-0.70697 -1.34029,-0.46513c-2.23396,1.08135 -3.77446,3.37351 -3.77545,6.02296c0.00099,3.69518 2.99518,6.68989 6.69138,6.69088c3.6957,-0.00099 6.69037,-2.9957 6.69089,-6.69088c-0.00102,-2.64846 -1.53948,-4.9391 -3.77247,-6.02197zm-2.91842,4.9346c0.55398,0 1.00309,-0.44861 1.00309,-1.00357l0,-4.68373c0,-0.55446 -0.44911,-1.00309 -1.00309,-1.00309c-0.555,0 -1.00358,0.44911 -1.00358,1.00309l0,4.68321c0,0.55499 0.44858,1.00409 1.00358,1.00409z" stroke-width="0" fill="#edf0f1"/>
</svg>

View File

@ -81,13 +81,47 @@ g.edgePath.param-connection {
.nodes rect {
stroke: var(--theme-tab-toolbar-background);
}
.theme-light rect {
fill: var(--theme-tab-toolbar-background);
}
.theme-dark rect {
fill: var(--theme-toolbar-background);
}
/**
* Bypassed Nodes
*/
.theme-light .nodes g.bypassed rect {
fill: url(chrome://browser/skin/devtools/filters.svg#bypass-light);
}
.theme-dark .nodes g.bypassed rect {
fill: url(chrome://browser/skin/devtools/filters.svg#bypass-dark);
}
.nodes g.bypassed.selected rect {
stroke: var(--theme-selection-background);
}
/*
.nodes g.bypassed text {
opacity: 0.8;
}
*/
/**
* Selected Nodes
*/
.nodes g.selected rect {
fill: var(--theme-selection-background);
}
/* Don't style bypassed nodes text different because it'd be illegible in light-theme */
.theme-light g.selected:not(.bypassed) text {
fill: var(--theme-toolbar-background);
}
/* Text in nodes and edges */
text {
cursor: default; /* override the "text" cursor */
@ -100,9 +134,6 @@ text {
fill: var(--theme-body-color-alt);
}
.theme-light g.selected text {
fill: var(--theme-toolbar-background);
}
.nodes text {
cursor: pointer;
@ -178,6 +209,32 @@ text {
}
}
/**
* Inspector toolbar
*/
#audio-node-toolbar .bypass {
list-style-image: url(power.svg);
}
#audio-node-toolbar toolbarbutton[disabled] {
opacity: 0.5;
background-color: transparent;
}
.theme-dark #audio-node-toolbar toolbarbutton[checked] {
background-color: #1d4f73; /* Select Highlight Blue */
}
.theme-light #audio-node-toolbar toolbarbutton[checked] {
background-color: #4c9ed9; /* Select Highlight Blue */
}
/* don't invert checked buttons so we can have white icons on light theme */
#audio-node-toolbar toolbarbutton[checked] > .toolbarbutton-icon {
filter: none;
}
/**
* Responsive Styles
* `.devtools-responsive-container` takes care of most of

View File

@ -266,6 +266,7 @@ browser.jar:
skin/classic/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)
@ -729,6 +730,7 @@ browser.jar:
skin/classic/aero/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/aero/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/aero/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/aero/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/aero/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/aero/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)

View File

@ -39,7 +39,7 @@ if test $android_version -lt MIN_ANDROID_VERSION ; then
fi
case "$target" in
arm-linux*-android*|*-linuxandroid*)
arm-*linux*-android*|*-linuxandroid*)
android_tool_prefix="arm-linux-androideabi"
;;
i?86-*android*)

View File

@ -32,7 +32,7 @@ using dom::ConstrainLongRange;
NS_IMPL_ISUPPORTS(MediaEngineTabVideoSource, nsIDOMEventListener, nsITimerCallback)
MediaEngineTabVideoSource::MediaEngineTabVideoSource()
: mMonitor("MediaEngineTabVideoSource"), mTabSource(nullptr)
: mData(NULL), mDataSize(0), mMonitor("MediaEngineTabVideoSource"), mTabSource(nullptr)
{
}
@ -79,7 +79,6 @@ MediaEngineTabVideoSource::Notify(nsITimer*) {
nsresult
MediaEngineTabVideoSource::InitRunnable::Run()
{
mVideoSource->mData = (unsigned char*)malloc(mVideoSource->mBufW * mVideoSource->mBufH * 4);
if (mVideoSource->mWindowId != -1) {
nsCOMPtr<nsPIDOMWindow> window = nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId);
if (window) {
@ -150,20 +149,10 @@ MediaEngineTabVideoSource::Allocate(const VideoTrackConstraintsN& aConstraints,
}
}
mBufW = aPrefs.GetWidth(false);
mBufH = aPrefs.GetHeight(false);
ConstrainLongRange defaultRange;
if (cWidth.mMin > mBufW) {
mBufW = cWidth.mMin;
} else if (cWidth.mMax < mBufW) {
mBufW = cWidth.mMax;
}
if (cHeight.mMin > mBufH) {
mBufH = cHeight.mMin;
} else if (cHeight.mMax < mBufH) {
mBufH = cHeight.mMax;
}
mBufWidthMax = defaultRange.mMax > cWidth.mMax ? cWidth.mMax : aPrefs.GetWidth(false);
mBufHeightMax = defaultRange.mMax > cHeight.mMax ? cHeight.mMax : aPrefs.GetHeight(false);
mTimePerFrame = aPrefs.mFPS ? 1000 / aPrefs.mFPS : aPrefs.mFPS;
return NS_OK;
@ -213,35 +202,38 @@ MediaEngineTabVideoSource::NotifyPull(MediaStreamGraph*,
void
MediaEngineTabVideoSource::Draw() {
IntSize size(mBufW, mBufH);
nsresult rv;
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mWindow);
if (!win) {
return;
}
int32_t width, height;
win->GetInnerWidth(&width);
win->GetInnerHeight(&height);
int32_t innerWidth, innerHeight;
win->GetInnerWidth(&innerWidth);
win->GetInnerHeight(&innerHeight);
if (width == 0 || height == 0) {
if (innerWidth == 0 || innerHeight == 0) {
return;
}
int32_t srcW;
int32_t srcH;
float aspectRatio = ((float) size.width) / size.height;
if (width / aspectRatio < height) {
srcW = width;
srcH = width / aspectRatio;
IntSize size;
// maintain source aspect ratio
if (mBufWidthMax/innerWidth < mBufHeightMax/innerHeight) {
size = IntSize(mBufWidthMax, (mBufWidthMax * ((float) innerHeight/innerWidth)));
} else {
srcW = height * aspectRatio;
srcH = height;
size = IntSize((mBufHeightMax * ((float) innerWidth/innerHeight)), mBufHeightMax);
}
gfxImageFormat format = gfxImageFormat::RGB24;
uint32_t stride = gfxASurface::FormatStrideForWidth(format, size.width);
if (mDataSize < static_cast<size_t>(stride * size.height)) {
mDataSize = stride * size.height;
mData = static_cast<unsigned char*>(malloc(mDataSize));
}
if (!mData) {
return;
}
nsRefPtr<nsPresContext> presContext;
@ -259,11 +251,8 @@ MediaEngineTabVideoSource::Draw() {
if (!mScrollWithPage) {
renderDocFlags |= nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
}
nsRect r(0, 0, nsPresContext::CSSPixelsToAppUnits((float)srcW),
nsPresContext::CSSPixelsToAppUnits((float)srcH));
gfxImageFormat format = gfxImageFormat::RGB24;
uint32_t stride = gfxASurface::FormatStrideForWidth(format, size.width);
nsRect r(0, 0, nsPresContext::CSSPixelsToAppUnits((float)innerWidth),
nsPresContext::CSSPixelsToAppUnits((float)innerHeight));
nsRefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
RefPtr<DrawTarget> dt =
@ -276,12 +265,10 @@ MediaEngineTabVideoSource::Draw() {
return;
}
nsRefPtr<gfxContext> context = new gfxContext(dt);
context->SetMatrix(context->CurrentMatrix().Scale((float)size.width/srcW,
(float)size.height/srcH));
context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/innerWidth),
(((float) size.height)/innerHeight)));
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
NS_ENSURE_SUCCESS_VOID(rv);
NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
RefPtr<SourceSurface> surface = dt->Snapshot();
if (!surface) {

View File

@ -70,12 +70,13 @@ protected:
~MediaEngineTabVideoSource() {}
private:
int mBufW;
int mBufH;
int mBufWidthMax;
int mBufHeightMax;
int64_t mWindowId;
bool mScrollWithPage;
int mTimePerFrame;
ScopedFreePtr<unsigned char> mData;
size_t mDataSize;
nsCOMPtr<nsIDOMWindow> mWindow;
nsRefPtr<layers::CairoImage> mImage;
nsCOMPtr<nsITimer> mTimer;

View File

@ -2923,6 +2923,7 @@ RilObject.prototype = {
* @param command
* @param deviceIdentities
* @param resultCode
* @param [optional] additionalInformation
* @param [optional] itemIdentifier
* @param [optional] input
* @param [optional] isYesNo
@ -2978,8 +2979,25 @@ RilObject.prototype = {
// Result
GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_RESULT |
COMPREHENSIONTLV_FLAG_CR);
if ("additionalInformation" in response) {
// In |12.12 Result| TS 11.14, the length of additional information is
// varied and all possible values are addressed in 12.12.1-11 of TS 11.14
// and 8.12.1-13 in TS 31.111.
// However,
// 1. Only SEND SS requires info with more than 1 octet.
// 2. In rild design, SEND SS is expected to be handled by modem and
// UNSOLICITED_STK_EVENT_NOTIFY will be sent to application layer to
// indicate appropriate messages to users. TR is not required in this
// case.
// Hence, we simplify the structure of |additionalInformation| to a
// numeric value instead of a octet array.
GsmPDUHelper.writeHexOctet(2);
GsmPDUHelper.writeHexOctet(response.resultCode);
GsmPDUHelper.writeHexOctet(response.additionalInformation);
} else {
GsmPDUHelper.writeHexOctet(1);
GsmPDUHelper.writeHexOctet(response.resultCode);
}
// Item Identifier
if (response.itemIdentifier != null) {
@ -3004,7 +3022,7 @@ RilObject.prototype = {
text = response.input;
}
if (text) {
if (text !== undefined) {
GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TEXT_STRING |
COMPREHENSIONTLV_FLAG_CR);

View File

@ -156,6 +156,77 @@ add_test(function test_stk_terminal_response() {
context.RIL.sendStkTerminalResponse(response);
});
/**
* Verify STK terminal response : GET INPUT with empty string.
*
* @See |TERMINAL RESPONSE: GET INPUT 1.9.1A| of 27.22.4.3.1 GET INPUT (normal)
* in TS 102 384.
*/
add_test(function test_stk_terminal_response_get_input_empty_string() {
let worker = newUint8SupportOutgoingIndexWorker();
let context = worker.ContextPool._contexts[0];
let buf = context.Buf;
let pduHelper = context.GsmPDUHelper;
buf.sendParcel = function() {
// Type
do_check_eq(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
// Token : we don't care
this.readInt32();
// Data Size, 30 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
// TLV_DEVICE_ID_SIZE(4) +
// TLV_RESULT_SIZE(3) +
// TEXT LENGTH(3))
do_check_eq(this.readInt32(), 30);
// Command Details, Type-Length-Value
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
COMPREHENSIONTLV_FLAG_CR);
do_check_eq(pduHelper.readHexOctet(), 3);
do_check_eq(pduHelper.readHexOctet(), 0x01);
do_check_eq(pduHelper.readHexOctet(), STK_CMD_GET_INPUT);
do_check_eq(pduHelper.readHexOctet(), 0x00);
// Device Identifies, Type-Length-Value(Source ID-Destination ID)
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
do_check_eq(pduHelper.readHexOctet(), 2);
do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
// Result
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
COMPREHENSIONTLV_FLAG_CR);
do_check_eq(pduHelper.readHexOctet(), 1);
do_check_eq(pduHelper.readHexOctet(), STK_RESULT_OK);
// Text
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
COMPREHENSIONTLV_FLAG_CR);
do_check_eq(pduHelper.readHexOctet(), 1);
do_check_eq(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
run_next_test();
};
let response = {
command: {
commandNumber: 0x01,
typeOfCommand: STK_CMD_GET_INPUT,
commandQualifier: 0x00,
options: {
minLength: 0,
maxLength: 1,
defaultText: "<SEND>"
}
},
input: "",
resultCode: STK_RESULT_OK
};
context.RIL.sendStkTerminalResponse(response);
});
/**
* Verify STK terminal response : GET_INKEY - YES/NO request
*/
@ -205,8 +276,6 @@ add_test(function test_stk_terminal_response_get_inkey() {
do_check_eq(pduHelper.readHexOctet(), 2);
do_check_eq(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
do_check_eq(pduHelper.readHexOctet(), isYesNo ? 0x01 : 0x00);
run_next_test();
};
let response = {
@ -229,6 +298,73 @@ add_test(function test_stk_terminal_response_get_inkey() {
do_test(true);
// Test "No" response
do_test(false);
run_next_test();
});
/**
* Verify STK terminal response with additional information.
*/
add_test(function test_stk_terminal_response_with_additional_info() {
function do_test(aInfo) {
let worker = newUint8SupportOutgoingIndexWorker();
let context = worker.ContextPool._contexts[0];
let buf = context.Buf;
let pduHelper = context.GsmPDUHelper;
buf.sendParcel = function() {
// Type
do_check_eq(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
// Token : we don't care
this.readInt32();
// Data Length 26 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
// TLV_DEVICE_ID_SIZE(4) +
// TLV_RESULT_SIZE(4))
do_check_eq(this.readInt32(), 26);
// Command Details, Type-Length-Value(commandNumber, typeOfCommand, commandQualifier)
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
COMPREHENSIONTLV_FLAG_CR);
do_check_eq(pduHelper.readHexOctet(), 3);
do_check_eq(pduHelper.readHexOctet(), 0x01);
do_check_eq(pduHelper.readHexOctet(), STK_CMD_DISPLAY_TEXT);
do_check_eq(pduHelper.readHexOctet(), 0x01);
// Device Identifies, Type-Length-Value(Source ID-Destination ID)
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
do_check_eq(pduHelper.readHexOctet(), 2);
do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
// Result, Type-Length-Value(General result, Additional information on result)
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
COMPREHENSIONTLV_FLAG_CR);
do_check_eq(pduHelper.readHexOctet(), 2);
do_check_eq(pduHelper.readHexOctet(), STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
do_check_eq(pduHelper.readHexOctet(), aInfo);
};
let response = {
command: {
commandNumber: 0x01,
typeOfCommand: STK_CMD_DISPLAY_TEXT,
commandQualifier: 0x01,
options: {
isHighPriority: true
}
},
resultCode: STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS,
additionalInformation: aInfo
};
context.RIL.sendStkTerminalResponse(response);
};
do_test(0x01); // 'Screen is busy'
run_next_test();
});
// Test ComprehensionTlvHelper

View File

@ -149,6 +149,20 @@ interface MozIccManager : EventTarget
/** Bearer independent protocol error */
const unsigned short STK_RESULT_BIP_ERROR = 0x3a;
/**
* Additional information on result:
*
* TS 11.14, 12.12.1-11 and TS 31.111,8.12.1-13 defines additional infomation
* for different categories such as SEND SS, ME problem, network problem, etc.
*
* Note: We define these information here by category when needed.
*/
/**
* 12.12.2 Additional information for ME problem:
*/
const unsigned short STK_ADDITIONAL_INFO_ME_PROBLEM_SCREEN_IS_BUSY = 0x01;
/**
* STK event list.
*/

View File

@ -90,7 +90,7 @@ dictionary MozStkTextMessage : MozStkIconContainer
* or a low battery warning. In that situation, the resolution is left to
* the terminal. If the command is rejected in spite of the high priority,
* the terminal shall inform the ICC with resultCode is
* TERMINAL_CRNTLY_UNABLE_TO_PROCESS in MozStkResponse.
* MozIccManager.STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS in MozStkResponse.
*
* true: high priority
* false: normal priority
@ -104,7 +104,7 @@ dictionary MozStkTextMessage : MozStkIconContainer
*
* If this attribute is true, but user doesn't give any input within a period
* of time(said 30 secs), the terminal shall inform the ICC with resultCode
* is NO_RESPONSE_FROM_USER in MozStkResponse.
* is MozIccManager.STK_RESULT_NO_RESPONSE_FROM_USER in MozStkResponse.
*
* true: Wait for user to clear message.
* false: clear message after a delay.
@ -151,7 +151,7 @@ dictionary MozStkMenu : MozStkIconContainer
sequence<MozStkItem> items;
/**
* Presentation type, one of TYPE_*.
* Presentation type, one of MozIccManager.STK_MENU_TYPE_*.
*/
unsigned short presentationType;
@ -177,10 +177,10 @@ dictionary MozStkMenu : MozStkIconContainer
/**
* List of Next Action Indicators.
* Each element should be one of nsIDOMMozIccManager.STK_CMD_*
* or nsIDOMMozIccManager.STK_NEXT_ACTION_*
* If it's STK_NEXT_ACTION_NULL, the terminal should ignore this action
* in corresponding item.
* Each element should be one of MozIccManager.STK_CMD_*
* or MozIccManager.STK_NEXT_ACTION_*
* If it's MozIccManager.STK_NEXT_ACTION_NULL, the terminal should ignore this
* action in corresponding item.
*
* @see TS 11.14, clause 12.24, Items Next Action Indicator.
*/
@ -293,9 +293,7 @@ dictionary MozStkBrowserSetting
DOMString url;
/**
* One of STK_BROWSER_MODE_*.
*
* @see nsIDOMMozIccManager.STK_BROWSER_MODE_*
* One of MozIccManager.STK_BROWSER_MODE_*.
*/
unsigned short mode;
};
@ -332,7 +330,7 @@ dictionary MozStkSetUpEventList
* When this valus is null, means an indication to remove the existing list
* of events in ME.
*
* @see nsIDOMMozIccManager.STK_EVENT_TYPE_*
* @see MozIccManager.STK_EVENT_TYPE_*
*/
sequence<unsigned short> eventList;
};
@ -363,7 +361,7 @@ dictionary MozStkLocationInfo
dictionary MozStkDuration
{
/**
* Time unit used, should be one of STK_TIME_UNIT_*.
* Time unit used, should be one of MozIccManager.STK_TIME_UNIT_*.
*/
unsigned short timeUnit;
@ -381,7 +379,7 @@ dictionary MozStkPlayTone : MozStkIconContainer
DOMString text;
/**
* One of STK_TONE_TYPE_*.
* One of MozIccManager.STK_TONE_TYPE_*.
*/
unsigned short tone;
@ -403,10 +401,10 @@ dictionary MozStkProvideLocalInfo
/**
* Indicate which local information is required.
* It shall be one of following:
* - nsIDOMMozIccManager.STK_LOCAL_INFO_LOCATION_INFO
* - nsIDOMMozIccManager.STK_LOCAL_INFO_IMEI
* - nsIDOMMozIccManager.STK_LOCAL_INFO_DATE_TIME_ZONE
* - nsIDOMMozIccManager.STK_LOCAL_INFO_LANGUAGE
* - MozIccManager.STK_LOCAL_INFO_LOCATION_INFO
* - MozIccManager.STK_LOCAL_INFO_IMEI
* - MozIccManager.STK_LOCAL_INFO_DATE_TIME_ZONE
* - MozIccManager.STK_LOCAL_INFO_LANGUAGE
*/
unsigned short localInfoType;
};
@ -415,23 +413,23 @@ dictionary MozStkLocationEvent
{
/**
* The type of this event.
* It shall be nsIDOMMozIccManager.STK_EVENT_TYPE_LOCATION_STATUS;
* It shall be MozIccManager.STK_EVENT_TYPE_LOCATION_STATUS;
*/
unsigned short eventType;
/**
* Indicate current service state of the MS with one of the values listed
* below:
* - nsIDOMMozIccManager.STK_SERVICE_STATE_NORMAL
* - nsIDOMMozIccManager.STK_SERVICE_STATE_LIMITED
* - nsIDOMMozIccManager.STK_SERVICE_STATE_UNAVAILABLE
* - MozIccManager.STK_SERVICE_STATE_NORMAL
* - MozIccManager.STK_SERVICE_STATE_LIMITED
* - MozIccManager.STK_SERVICE_STATE_UNAVAILABLE
*/
unsigned short locationStatus;
/**
* See MozStkLocationInfo.
* This value shall only be provided if the locationStatus indicates
* 'STK_SERVICE_STATE_NORMAL'.
* MozIccManager.STK_SERVICE_STATE_NORMAL.
*/
MozStkLocationInfo locationInfo;
};
@ -452,9 +450,9 @@ dictionary MozStkTimer
/**
* The action requested from UICC.
* It shall be one of below:
* - nsIDOMMozIccManager.STK_TIMER_START
* - nsIDOMMozIccManager.STK_TIMER_DEACTIVATE
* - nsIDOMMozIccManager.STK_TIMER_GET_CURRENT_VALUE
* - MozIccManager.STK_TIMER_START
* - MozIccManager.STK_TIMER_DEACTIVATE
* - MozIccManager.STK_TIMER_GET_CURRENT_VALUE
*/
unsigned short timerAction;
};
@ -478,7 +476,7 @@ dictionary MozStkCommand
unsigned short commandNumber;
/**
* One of STK_CMD_*
* One of MozIccManager.STK_CMD_*
*/
unsigned short typeOfCommand;
@ -491,62 +489,62 @@ dictionary MozStkCommand
* options varies accrording to the typeOfCommand in MozStkCommand.
*
* When typeOfCommand is
* - STK_CMD_DISPLAY_TEXT
* - STK_CMD_SET_UP_IDLE_MODE_TEXT
* - STK_CMD_SEND_{SS|USSD|SMS|DTMF},
* - MozIccManager.STK_CMD_DISPLAY_TEXT
* - MozIccManager.STK_CMD_SET_UP_IDLE_MODE_TEXT
* - MozIccManager.STK_CMD_SEND_{SS|USSD|SMS|DTMF},
* options is MozStkTextMessage.
*
* When typeOfCommand is
* - STK_CMD_SELECT_ITEM
* - STK_CMD_SET_UP_MENU
* - MozIccManager.STK_CMD_SELECT_ITEM
* - MozIccManager.STK_CMD_SET_UP_MENU
* options is MozStkMenu.
*
* When typeOfCommand is
* - STK_CMD_GET_INKEY
* - STK_CMD_GET_INPUT,
* - MozIccManager.STK_CMD_GET_INKEY
* - MozIccManager.STK_CMD_GET_INPUT,
* options is MozStkInput.
*
* When typeOfCommand is
* - STK_CMD_LAUNCH_BROWSER
* - MozIccManager.STK_CMD_LAUNCH_BROWSER
* options is MozStkBrowserSetting.
*
* When typeOfCommand is
* - STK_CMD_SET_UP_CALL
* - MozIccManager.STK_CMD_SET_UP_CALL
* options is MozStkSetUpCall.
*
* When typeOfCommand is
* - STK_CMD_SET_UP_EVENT_LIST
* - MozIccManager.STK_CMD_SET_UP_EVENT_LIST
* options is MozStkSetUpEventList.
*
* When typeOfCommand is
* - STK_CMD_PLAY_TONE
* - MozIccManager.STK_CMD_PLAY_TONE
* options is MozStkPlayTone.
*
* When typeOfCommand is
* - STK_CMD_POLL_INTERVAL
* - MozIccManager.STK_CMD_POLL_INTERVAL
* options is MozStkDuration.
*
* When typeOfCommand is
* - STK_CMD_PROVIDE_LOCAL_INFO
* - MozIccManager.STK_CMD_PROVIDE_LOCAL_INFO
* options is MozStkProvideLocalInfo.
*
* When typeOfCommand is
* - STK_CMD_TIMER_MANAGEMENT
* - MozIccManager.STK_CMD_TIMER_MANAGEMENT
* option is MozStkTimer
*
* When typeOfCommand is
* - STK_CMD_OPEN_CHANNEL
* - STK_CMD_CLOSE_CHANNEL
* - STK_CMD_SEND_DATA
* - STK_CMD_RECEIVE_DATA
* - MozIccManager.STK_CMD_OPEN_CHANNEL
* - MozIccManager.STK_CMD_CLOSE_CHANNEL
* - MozIccManager.STK_CMD_SEND_DATA
* - MozIccManager.STK_CMD_RECEIVE_DATA
* options is MozStkBipMessage
*
* When typeOfCommand is
* - STK_CMD_POLL_OFF
* - MozIccManager.STK_CMD_POLL_OFF
* options is null.
*
* When typeOfCommand is
* - STK_CMD_REFRESH
* - MozIccManager.STK_CMD_REFRESH
* options is null.
*/
any options;
@ -555,10 +553,15 @@ dictionary MozStkCommand
dictionary MozStkResponse
{
/**
* One of RESULT_*
* One of MozIccManager.STK_RESULT_*
*/
unsigned short resultCode;
/**
* One of MozIccManager.STK_ADDITIONAL_INFO_*
*/
unsigned short additionalInformation;
/**
* The identifier of the item selected by user.
*
@ -579,7 +582,8 @@ dictionary MozStkResponse
boolean isYesNo;
/**
* User has confirmed or rejected the call during STK_CMD_CALL_SET_UP.
* User has confirmed or rejected the call during
* MozIccManager.STK_CMD_CALL_SET_UP.
*
* @see RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM
*
@ -589,15 +593,16 @@ dictionary MozStkResponse
boolean hasConfirmed;
/**
* The response for STK_CMD_PROVIDE_LOCAL_INFO
* The response for MozIccManager.STK_CMD_PROVIDE_LOCAL_INFO
*/
MozStkLocalInfo localInfo;
/**
* The response for STK_CMD_TIMER_MANAGEMENT.
* The 'timerValue' is needed if the action of STK_CMD_TIMER_MANAGEMENT is
* 'STK_TIMER_DEACTIVATE' or 'STK_TIMER_GET_CURRENT_VALUE'. It shall state
* the current value of a timer. And the resolution is 1 second.
* The response for MozIccManager.STK_CMD_TIMER_MANAGEMENT.
* The 'timerValue' is needed if the action of
* MozIccManager.STK_CMD_TIMER_MANAGEMENT is MozIccManager.STK_TIMER_DEACTIVATE
* or MozIccManager.STK_TIMER_GET_CURRENT_VALUE.
* It shall state the current value of a timer. And the resolution is 1 second.
*/
MozStkTimer timer;
};
@ -607,9 +612,9 @@ dictionary MozStkCallEvent
/**
* The type of this event.
* It shall be one of following:
* - nsIDOMMozIccManager.STK_EVENT_TYPE_MT_CALL,
* - nsIDOMMozIccManager.STK_EVENT_TYPE_CALL_CONNECTED,
* - nsIDOMMozIccManager.STK_EVENT_TYPE_CALL_DISCONNECTED.
* - MozIccManager.STK_EVENT_TYPE_MT_CALL,
* - MozIccManager.STK_EVENT_TYPE_CALL_CONNECTED,
* - MozIccManager.STK_EVENT_TYPE_CALL_DISCONNECTED.
*/
unsigned short eventType;
@ -619,19 +624,20 @@ dictionary MozStkCallEvent
DOMString number;
/**
* This field is available in 'STK_EVENT_TYPE_CALL_CONNECTED' and
* 'STK_EVENT_TYPE_CALL_DISCONNECTED' events.
* For the STK_EVENT_TYPE_CALL_CONNECTED event, setting this to true means the
* connection is answered by remote end, that is, this is an outgoing call.
* For the STK_EVENT_TYPE_CALL_DISCONNECTED event, setting this to true
* indicates the connection is hung up by remote.
* This field is available in MozIccManager.STK_EVENT_TYPE_CALL_CONNECTED and
* MozIccManager.STK_EVENT_TYPE_CALL_DISCONNECTED events.
* For the MozIccManager.STK_EVENT_TYPE_CALL_CONNECTED event, setting this to
* true means the connection is answered by remote end, that is, this is an
* outgoing call.
* For the MozIccManager.STK_EVENT_TYPE_CALL_DISCONNECTED event, setting this
* to true indicates the connection is hung up by remote.
*/
boolean isIssuedByRemote;
/**
* This field is available in Call Disconnected event to indicate the cause
* of disconnection. The cause string is passed to gaia through the error
* listener of nsIDOMCallEvent. Null if there's no error.
* listener of CallEvent. Null if there's no error.
*/
DOMString error;
};
@ -665,7 +671,7 @@ dictionary MozStkLanguageSelectionEvent
{
/**
* The type of this event.
* It shall be nsIDOMMozIccManager.STK_EVENT_TYPE_LANGUAGE_SELECTION.
* It shall be MozIccManager.STK_EVENT_TYPE_LANGUAGE_SELECTION.
*/
unsigned short eventType;
@ -682,15 +688,15 @@ dictionary MozStkBrowserTerminationEvent
{
/**
* The type of this event.
* It shall be nsIDOMMozIccManager.STK_EVENT_TYPE_BROWSER_TERMINATION
* It shall be MozIccManager.STK_EVENT_TYPE_BROWSER_TERMINATION
*/
unsigned short eventType;
/**
* This object shall contain the browser termination cause.
* See TZ 102 223 8.51. It shall be one of following:
* - nsIDOMMozIccManager.STK_BROWSER_TERMINATION_CAUSE_USER
* - nsIDOMMozIccManager.STK_BROWSER_TERMINATION_CAUSE_ERROR
* - MozIccManager.STK_BROWSER_TERMINATION_CAUSE_USER
* - MozIccManager.STK_BROWSER_TERMINATION_CAUSE_ERROR
*/
unsigned short terminationCause;
};
@ -700,8 +706,8 @@ dictionary MozStkGeneralEvent
/**
* The type of this event, MozStkGeneralEvent can be used for all Stk Event
* requires no more parameter than event type, including
* nsIDOMMozIccManager.STK_EVENT_TYPE_USER_ACTIVITY.
* nsIDOMMozIccManager.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE.
* MozIccManager.STK_EVENT_TYPE_USER_ACTIVITY.
* MozIccManager.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE.
* HCI Connectivity Event(Not defined in interface yet).
*/
unsigned short eventType;

View File

@ -11179,248 +11179,250 @@
46753a52402,52403
> terahertz/M
> terapixel/MS
46806,46807c52456
46756a52407
> teriyaki
46806,46807c52457
< test's/AFK
< test/AKFCDGS
---
> test/AKFCDGSM
46817a52467
46817a52468
> testcase/MS
46831a52482
46831a52483
> testsuite/MS
46845a52497
46845a52498
> textbox/SM
46925a52578
46925a52579
> theremin/MS
46999c52652
46999c52653
< thinking's
---
> thinking/M
47095,47096c52748
47095,47096c52749
< throne's
< throne/CDS
---
> throne/CDSM
47188,47189c52840
47188,47189c52841
< tie's
< tie/AUSD
---
> tie/AUSDM
47213,47214c52864
47213,47214c52865
< till's
< till/EDRZGS
---
> till/EDRZGSM
47303,47304c52953
47303,47304c52954
< tire's
< tire/AGDS
---
> tire/AGDSM
47433,47434c53082
47433,47434c53083
< tone's
< tone/IZGDRS
---
> tone/IZGDRSM
47453,47455c53101,53102
47453,47455c53102,53103
< tool's
< tool/ADGS
< toolbar
---
> tool/ADGSM
> toolbar/MS
47540,47541c53187
47540,47541c53188
< tort's
< tort/FEAS
---
> tort/FEASM
47644a53291
47644a53292
> traceur/SM
47657,47658c53304
47657,47658c53305
< tract's
< tract/CEKFAS
---
> tract/CEKFASM
47755a53402
47755a53403
> transfect/DSMG
47774a53422,53423
47774a53423,53424
> transgenderism
> transgene/MS
47807,47808c53456
47807,47808c53457
< transmission's
< transmission/AS
---
> transmission/ASM
47928,47929c53576
47928,47929c53577
< trench's
< trench/AIGSD
---
> trench/AIGSDM
47951c53598
47951c53599
< triage/M
---
> triage/MGS
47976,47977c53623
47976,47977c53624
< tribute's
< tribute/FS
---
> tribute/FSM
47997a53644
47997a53645
> trifecta/S
48165,48166c53812
48165,48166c53813
< trust's/E
< trust/IESGD
---
> trust/IESGDM
48180,48181c53826
48180,48181c53827
< try's
< try/AGDS
---
> try/AGDSM
48271a53917
48271a53918
> turducken
48334a53981
48334a53982
> tweep/S
48371,48372c54018
48371,48372c54019
< twist's
< twist/USDG
---
> twist/USDGM
48396,48397c54042
48396,48397c54043
< type's
< type/AGDS
---
> type/AGDSM
48869a54515
48869a54516
> unlikeable
49163,49164c54809
49163,49164c54810
< usual's
< usual/UY
---
> usual/UYM
49211c54856
49211c54857
< vagina/M
---
> vagina/MS
49249,49250c54894
49249,49250c54895
< value's
< value/CAGSD
---
> value/CAGSDM
49292,49293c54936
49292,49293c54937
< variant's
< variant/IS
---
> variant/ISM
49356,49357c54999
49356,49357c55000
< veil's
< veil/UDGS
---
> veil/UDGSM
49368,49369c55010
49368,49369c55011
< velour's
< velours's
---
> velour/MS
49398,49399c55039
49398,49399c55040
< vent's
< vent/DGS
---
> vent/DGSM
49435,49436c55075
49435,49436c55076
< verge's
< verge/FDSG
---
> verge/FDSGM
49478a55118
49478a55119
> vertices
49488,49489c55128
49488,49489c55129
< vest's
< vest/ILDGS
---
> vest/ILDGSM
49681,49682c55320
49681,49682c55321
< visit's
< visit/ASGD
---
> visit/ASGDM
49772a55411,55413
49772a55412,55414
> volcanological
> volcanologist/MS
> volcanology/M
49807,49808c55448
49807,49808c55449
< vote's
< vote/CGVDS
---
> vote/CGVDSM
50148a55789
50148a55790
> weaponize/DSG
50215,50216c55856
50215,50216c55857
< weigh's
< weigh/AGD
---
> weigh/AGDM
50260,50261d55899
50260,50261d55900
< werwolf/M
< werwolves
50555,50556c56193
50555,50556c56194
< wind's
< wind/UASG
---
> wind/UASGM
50626,50627c56263
50626,50627c56264
< wire's
< wire/AGDS
---
> wire/AGDSM
50728c56364
50728c56365
< women
---
> women/M
50794,50796c56430,56431
50794,50796c56431,56432
< wop/S!
< word's
< word/AJDSG
---
> wop/MS!
> word/AJDSGM
50801c56436
50801c56437
< wording's
---
> wording/M
50808,50809c56443
50808,50809c56444
< work's
< work/ADJSG
---
> work/ADJSGM
50824c56458
50824c56459
< working's
---
> working/M
50884,50885c56518
50884,50885c56519
< worthy's
< worthy/UPRT
---
> worthy/UPRTM
50903,50904c56536
50903,50904c56537
< wrap's
< wrap/US
---
> wrap/USM
50945c56577
50945c56578
< writing's
---
> writing/M
51118,51119c56750
51118,51119c56751
< yoke's
< yoke/UGDS
---
> yoke/UGDSM
51212,51213c56843
51212,51213c56844
< zip's
< zip/US
---
> zip/USM
51228,51229c56858
51228,51229c56859
< zone's
< zone/AGDS
---

View File

@ -1,4 +1,4 @@
57245
57246
0/nm
0th/pt
1/n1
@ -52757,6 +52757,7 @@ terapixel/MS
terbium/M
tercentenary/SM
tercentennial/MS
teriyaki
term/MDYGS
termagant/MS
terminable/IC

View File

@ -250,7 +250,7 @@ class FilePickerResultHandler implements ActivityResultHandler {
// will eventually does the cleanup for us.
@Override
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
if (tab.getId() != tabId) {
if ((tab == null) || (tab.getId() != tabId)) {
return;
}

View File

@ -1,4 +1,3 @@
#filter substitution
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* 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

View File

@ -1,4 +1,3 @@
#filter substitution
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* 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
@ -10,6 +9,7 @@ let Ci = Components.interfaces;
let Cu = Components.utils;
let Cr = Components.results;
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AddonManager.jsm");
@ -17,9 +17,9 @@ Cu.import('resource://gre/modules/Payment.jsm');
Cu.import("resource://gre/modules/NotificationDB.jsm");
Cu.import("resource://gre/modules/SpatialNavigation.jsm");
#ifdef ACCESSIBILITY
if (AppConstants.ACCESSIBILITY) {
Cu.import("resource://gre/modules/accessibility/AccessFu.jsm");
#endif
}
XPCOMUtils.defineLazyModuleGetter(this, "DownloadNotifications",
"resource://gre/modules/DownloadNotifications.jsm");
@ -57,10 +57,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
#ifdef MOZ_SAFE_BROWSING
if (AppConstants.MOZ_SAFE_BROWSING) {
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
#endif
}
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
@ -87,10 +87,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
"resource://gre/modules/SimpleServiceDiscovery.jsm");
#ifdef NIGHTLY_BUILD
if (AppConstants.NIGHTLY_BUILD) {
XPCOMUtils.defineLazyModuleGetter(this, "ShumwayUtils",
"resource://shumway/ShumwayUtils.jsm");
#endif
}
XPCOMUtils.defineLazyModuleGetter(this, "WebappManager",
"resource://gre/modules/WebappManager.jsm");
@ -113,8 +113,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Notifications",
XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
"resource://gre/modules/GMPInstallManager.jsm");
// Lazily-loaded browser scripts:
[
let lazilyLoadedBrowserScripts = [
["SelectHelper", "chrome://browser/content/SelectHelper.js"],
["InputWidgetHelper", "chrome://browser/content/InputWidgetHelper.js"],
["MasterPassword", "chrome://browser/content/MasterPassword.js"],
@ -123,10 +122,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
["Linkifier", "chrome://browser/content/Linkify.js"],
["ZoomHelper", "chrome://browser/content/ZoomHelper.js"],
["CastingApps", "chrome://browser/content/CastingApps.js"],
#ifdef NIGHTLY_BUILD
["WebcompatReporter", "chrome://browser/content/WebcompatReporter.js"],
#endif
].forEach(function (aScript) {
];
if (AppConstants.NIGHTLY_BUILD) {
lazilyLoadedBrowserScripts.push(
["WebcompatReporter", "chrome://browser/content/WebcompatReporter.js"]);
}
lazilyLoadedBrowserScripts.forEach(function (aScript) {
let [name, script] = aScript;
XPCOMUtils.defineLazyGetter(window, name, function() {
let sandbox = {};
@ -135,10 +137,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
});
});
[
#ifdef MOZ_WEBRTC
["WebrtcUI", ["getUserMedia:request", "recording-device-events"], "chrome://browser/content/WebrtcUI.js"],
#endif
let lazilyLoadedObserverScripts = [
["MemoryObserver", ["memory-pressure", "Memory:Dump"], "chrome://browser/content/MemoryObserver.js"],
["ConsoleAPI", ["console-api-log-event"], "chrome://browser/content/ConsoleAPI.js"],
["FindHelper", ["FindInPage:Opened", "FindInPage:Closed", "Tab:Selected"], "chrome://browser/content/FindHelper.js"],
@ -148,7 +147,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
["SelectionHandler", ["TextSelection:Get"], "chrome://browser/content/SelectionHandler.js"],
["EmbedRT", ["GeckoView:ImportScript"], "chrome://browser/content/EmbedRT.js"],
["Reader", ["Reader:Added", "Reader:Removed", "Gesture:DoubleTap"], "chrome://browser/content/Reader.js"],
].forEach(function (aScript) {
];
if (AppConstants.MOZ_WEBRTC) {
lazilyLoadedObserverScripts.push(
["WebrtcUI", ["getUserMedia:request", "recording-device-events"], "chrome://browser/content/WebrtcUI.js"])
}
lazilyLoadedObserverScripts.forEach(function (aScript) {
let [name, notifications, script] = aScript;
XPCOMUtils.defineLazyGetter(window, name, function() {
let sandbox = {};
@ -227,10 +232,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "DOMUtils",
XPCOMUtils.defineLazyServiceGetter(window, "URIFixup",
"@mozilla.org/docshell/urifixup;1", "nsIURIFixup");
#ifdef MOZ_WEBRTC
if (AppConstants.MOZ_WEBRTC) {
XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
"@mozilla.org/mediaManagerService;1", "nsIMediaManagerService");
#endif
}
const kStateActive = 0x00000001; // :active pseudoclass for elements
@ -287,12 +292,6 @@ function convertFromTwipsToPx(aSize) {
return aSize/240 * 16.0;
}
#ifdef MOZ_CRASHREPORTER
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
"@mozilla.org/xre/app-info;1", "nsICrashReporter");
#endif
XPCOMUtils.defineLazyGetter(this, "ContentAreaUtils", function() {
let ContentAreaUtils = {};
Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", ContentAreaUtils);
@ -382,17 +381,18 @@ var BrowserApp = {
}, 1000 * 60);
}, Ci.nsIThread.DISPATCH_NORMAL);
#ifdef MOZ_SAFE_BROWSING
if (AppConstants.MOZ_SAFE_BROWSING) {
Services.tm.mainThread.dispatch(function() {
// Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
SafeBrowsing.init();
}, Ci.nsIThread.DISPATCH_NORMAL);
#endif
#ifdef NIGHTLY_BUILD
}
if (AppConstants.NIGHTLY_BUILD) {
WebcompatReporter.init();
Telemetry.addData("TRACKING_PROTECTION_ENABLED",
Services.prefs.getBoolPref("privacy.trackingprotection.enabled"));
#endif
}
} catch(ex) { console.log(ex); }
}, false);
@ -483,12 +483,12 @@ var BrowserApp = {
Distribution.init();
Tabs.init();
SearchEngines.init();
#ifdef ACCESSIBILITY
if (AppConstants.ACCESSIBILITY) {
AccessFu.attach(window);
#endif
#ifdef NIGHTLY_BUILD
}
if (AppConstants.NIGHTLY_BUILD) {
ShumwayUtils.init();
#endif
}
let url = null;
if ("arguments" in window) {
@ -548,7 +548,7 @@ var BrowserApp = {
savedMilestone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
} catch (e) {
}
#expand let ourMilestone = "__MOZ_APP_VERSION__";
let ourMilestone = AppConstants.MOZ_APP_VERSION;
this._startupStatus = "";
if (ourMilestone != savedMilestone) {
Services.prefs.setCharPref("browser.startup.homepage_override.mstone", ourMilestone);
@ -1335,14 +1335,15 @@ var BrowserApp = {
pref.value = MasterPassword.enabled;
prefs.push(pref);
continue;
#ifdef MOZ_CRASHREPORTER
// Crash reporter submit pref must be fetched from nsICrashReporter service.
case "datareporting.crashreporter.submitEnabled":
let crashReporterBuilt = "nsICrashReporter" in Ci && Services.appinfo instanceof Ci.nsICrashReporter;
if (crashReporterBuilt) {
pref.type = "bool";
pref.value = CrashReporter.submitReports;
pref.value = Services.appinfo.submitReports;
prefs.push(pref);
}
continue;
#endif
}
try {
@ -1421,12 +1422,14 @@ var BrowserApp = {
Services.prefs.setBoolPref(SearchEngines.PREF_SUGGEST_PROMPTED, true);
break;
#ifdef MOZ_CRASHREPORTER
// Crash reporter preference is in a service; set and return.
case "datareporting.crashreporter.submitEnabled":
CrashReporter.submitReports = json.value;
let crashReporterBuilt = "nsICrashReporter" in Ci && Services.appinfo instanceof Ci.nsICrashReporter;
if (crashReporterBuilt) {
Services.appinfo.submitReports = json.value;
}
return;
#endif
// When sending to Java, we normalized special preferences that use
// integers and strings to represent booleans. Here, we convert them back
// to their actual types so we can store them.
@ -3066,8 +3069,7 @@ var DesktopUserAgent = {
},
onRequest: function(channel, defaultUA) {
#ifdef NIGHTLY_BUILD
if (this.TCO_DOMAIN == channel.URI.host) {
if (AppConstants.NIGHTLY_BUILD && this.TCO_DOMAIN == channel.URI.host) {
// Force the referrer
channel.referrer = channel.URI;
@ -3075,7 +3077,6 @@ var DesktopUserAgent = {
// "Gecko/x.y Firefox/x.y" part
return defaultUA.replace(this.TCO_REPLACE, "");
}
#endif
let channelWindow = this._getWindowForRequest(channel);
let tab = BrowserApp.getTabForWindow(channelWindow);
@ -5868,12 +5869,9 @@ let HealthReportStatusListener = {
PREF_ACCEPT_LANG: "intl.accept_languages",
PREF_BLOCKLIST_ENABLED: "extensions.blocklist.enabled",
PREF_TELEMETRY_ENABLED:
#ifdef MOZ_TELEMETRY_REPORTING
"toolkit.telemetry.enabled",
#else
PREF_TELEMETRY_ENABLED: AppConstants.MOZ_TELEMETRY_REPORTING ?
"toolkit.telemetry.enabled" :
null,
#endif
init: function () {
try {

View File

@ -24,18 +24,18 @@ chrome.jar:
content/Reader.js (content/Reader.js)
content/aboutHome.xhtml (content/aboutHome.xhtml)
content/aboutRights.xhtml (content/aboutRights.xhtml)
* content/aboutApps.xhtml (content/aboutApps.xhtml)
* content/aboutApps.js (content/aboutApps.js)
content/aboutApps.xhtml (content/aboutApps.xhtml)
content/aboutApps.js (content/aboutApps.js)
content/blockedSite.xhtml (content/blockedSite.xhtml)
content/languages.properties (content/languages.properties)
content/browser.xul (content/browser.xul)
* content/browser.js (content/browser.js)
content/browser.js (content/browser.js)
content/bindings/checkbox.xml (content/bindings/checkbox.xml)
content/bindings/settings.xml (content/bindings/settings.xml)
content/netError.xhtml (content/netError.xhtml)
content/SelectHelper.js (content/SelectHelper.js)
content/SelectionHandler.js (content/SelectionHandler.js)
* content/WebappRT.js (content/WebappRT.js)
content/WebappRT.js (content/WebappRT.js)
content/EmbedRT.js (content/EmbedRT.js)
content/InputWidgetHelper.js (content/InputWidgetHelper.js)
content/WebrtcUI.js (content/WebrtcUI.js)
@ -53,7 +53,7 @@ chrome.jar:
content/CastingApps.js (content/CastingApps.js)
#ifdef MOZ_SERVICES_HEALTHREPORT
content/aboutHealthReport.xhtml (content/aboutHealthReport.xhtml)
* content/aboutHealthReport.js (content/aboutHealthReport.js)
content/aboutHealthReport.js (content/aboutHealthReport.js)
#endif
#ifdef MOZ_DEVICES
content/aboutDevices.xhtml (content/aboutDevices.xhtml)

View File

@ -3,8 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let modules = {
// about:
@ -30,11 +32,9 @@ let modules = {
},
rights: {
#ifdef MOZ_OFFICIAL_BRANDING
uri: "chrome://browser/content/aboutRights.xhtml",
#else
uri: "chrome://global/content/aboutRights-unbranded.xhtml",
#endif
uri: AppConstants.MOZ_OFFICIAL_BRANDING ?
"chrome://browser/content/aboutRights.xhtml" :
"chrome://global/content/aboutRights-unbranded.xhtml",
privileged: false
},
blocked: {
@ -72,24 +72,25 @@ let modules = {
uri: "chrome://browser/content/aboutPrivateBrowsing.xhtml",
privileged: true
},
#ifdef MOZ_SERVICES_HEALTHREPORT
healthreport: {
}
if (AppConstants.MOZ_SERVICES_HEALTHREPORT) {
modules['healthreport'] = {
uri: "chrome://browser/content/aboutHealthReport.xhtml",
privileged: true
},
#endif
#ifdef MOZ_DEVICES
devices: {
};
}
if (AppConstants.MOZ_DEVICES) {
modules['devices'] = {
uri: "chrome://browser/content/aboutDevices.xhtml",
privileged: true
},
#endif
#ifdef NIGHTLY_BUILD
passwords: {
};
}
if (AppConstants.NIGHTLY_BUILD) {
modules['passwords'] = {
uri: "chrome://browser/content/aboutPasswords.xhtml",
privileged: true
}
#endif
};
}
function AboutRedirector() {}

View File

@ -2,12 +2,11 @@
* 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/. */
#filter substitution
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -27,7 +26,7 @@ const ENVVAR_UPDATE_DIR = "UPDATES_DIRECTORY";
const WEBAPPS_DIR = "webappsDir";
const DOWNLOAD_DIR = "DfltDwnld";
const SYSTEM_DIST_PATH = "/system/@ANDROID_PACKAGE_NAME@/distribution";
const SYSTEM_DIST_PATH = `/system/${AppConstants.ANDROID_PACKAGE_NAME}/distribution`;
function DirectoryProvider() {}
@ -172,4 +171,3 @@ DirectoryProvider.prototype = {
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DirectoryProvider]);

View File

@ -10,11 +10,6 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
#ifdef MOZ_CRASHREPORTER
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
"@mozilla.org/xre/app-info;1", "nsICrashReporter");
#endif
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
@ -565,7 +560,10 @@ SessionStore.prototype = {
},
_updateCrashReportURL: function ss_updateCrashReportURL(aWindow) {
#ifdef MOZ_CRASHREPORTER
let crashReporterBuilt = "nsICrashReporter" in Ci && Services.appinfo instanceof Ci.nsICrashReporter;
if (!crashReporterBuilt)
return;
if (!aWindow.BrowserApp.selectedBrowser)
return;
@ -577,14 +575,13 @@ SessionStore.prototype = {
}
catch (ex) { } // ignore failures on about: URIs
CrashReporter.annotateCrashReport("URL", currentURI.spec);
Services.appinfo.annotateCrashReport("URL", currentURI.spec);
}
catch (ex) {
// don't make noise when crashreporter is built but not enabled
if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED)
Components.utils.reportError("SessionStore:" + ex);
if (ex.result != Cr.NS_ERROR_NOT_INITIALIZED)
Cu.reportError("SessionStore:" + ex);
}
#endif
},
_serializeHistoryEntry: function _serializeHistoryEntry(aEntry) {

View File

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
/* This 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/. */
const Ci = Components.interfaces;
const Cc = Components.classes;

View File

@ -11,16 +11,22 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'MobileComponents'
EXTRA_COMPONENTS += [
'AboutRedirector.js',
'ActivitiesGlue.js',
'AddonUpdateService.js',
'BlocklistPrompt.js',
'BrowserCLH.js',
'ColorPicker.js',
'ContentDispatchChooser.js',
'ContentPermissionPrompt.js',
'DirectoryProvider.js',
'FilePicker.js',
'HelperAppDialog.js',
'LoginManagerPrompter.js',
'NSSDialogService.js',
'PromptService.js',
'SessionStore.js',
'Sidebar.js',
'SiteSpecificUserAgent.js',
'Snippets.js',
'TabSource.js',
@ -34,16 +40,10 @@ if CONFIG['MOZ_PAY']:
'PaymentsUI.js'
]
# Keep it this way if at all possible. If you need preprocessing,
# consider adding fields to AppConstants.jsm.
EXTRA_PP_COMPONENTS += [
'AboutRedirector.js',
'BrowserCLH.js',
'DirectoryProvider.js',
'HelperAppDialog.js',
'MobileComponents.manifest',
'SessionStore.js',
'Sidebar.js',
]
DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']
DIRS += ['build']

View File

@ -0,0 +1,97 @@
#filter substitution;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["AppConstants"];
// Immutable for export.
let AppConstants = Object.freeze({
// See this wiki page for more details about channel specific build
// defines: https://wiki.mozilla.org/Platform/Channel-specific_build_defines
NIGHTLY_BUILD:
#ifdef NIGHTLY_BUILD
true,
#else
false,
#endif
RELEASE_BUILD:
#ifdef RELEASE_BUILD
true,
#else
false,
#endif
ACCESSIBILITY:
#ifdef MOZ_ACCESSIBILITY
true,
#else
false,
#endif
// Official corresponds, roughly, to whether this build is performed
// on Mozilla's continuous integration infrastructure. You should
// disable developer-only functionality when this flag is set.
MOZILLA_OFFICIAL:
#ifdef MOZILLA_OFFICIAL
true,
#else
false,
#endif
MOZ_OFFICIAL_BRANDING:
#ifdef MOZ_OFFICIAL_BRANDING
true,
#else
false,
#endif
MOZ_SERVICES_HEALTHREPORT:
#ifdef MOZ_SERVICES_HEALTHREPORT
true,
#else
false,
#endif
MOZ_DEVICES:
#ifdef MOZ_DEVICES
true,
#else
false,
#endif
MOZ_DEVICES:
#ifdef MOZ_DEVICES
true,
#else
false,
#endif
MOZ_SAFE_BROWSING:
#ifdef MOZ_SAFE_BROWSING
true,
#else
false,
#endif
MOZ_TELEMETRY_REPORTING:
#ifdef MOZ_TELEMETRY_REPORTING
true,
#else
false,
#endif
MOZ_WEBRTC:
#ifdef MOZ_WEBRTC
true,
#else
false,
#endif
MOZ_APP_VERSION: "@MOZ_APP_VERSION@",
ANDROID_PACKAGE_NAME: "@ANDROID_PACKAGE_NAME@",
});

View File

@ -41,30 +41,16 @@ TabMirror.prototype = {
this._pc.onicecandidate = this._onIceCandidate.bind(this);
let windowId = this._window.BrowserApp.selectedBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
let viewport = this._window.BrowserApp.selectedTab.getViewport();
let maxWidth = Math.max(viewport.cssWidth, viewport.width);
let maxHeight = Math.max(viewport.cssHeight, viewport.height);
let videoWidth = 0;
let videoHeight = 0;
if (this._screenSize.width/this._screenSize.height < maxWidth / maxHeight) {
videoWidth = this._screenSize.width;
videoHeight = Math.ceil(videoWidth * maxHeight / maxWidth);
} else {
videoHeight = this._screenSize.height;
videoWidth = Math.ceil(videoHeight * maxWidth / maxHeight);
}
let constraints = {
video: {
mediaSource: "browser",
browserWindow: windowId,
scrollWithPage: true,
advanced: [
{ width: { min: videoWidth, max: videoWidth },
height: { min: videoHeight, max: videoHeight }
{ width: { min: 0, max: this._screenSize.width },
height: { min: 0, max: this._screenSize.height }
},
{ aspectRatio: maxWidth / maxHeight }
{ aspectRatio: this._screenSize.width / this._screenSize.height }
]
}
};

View File

@ -27,9 +27,21 @@ EXTRA_JS_MODULES += [
'SharedPreferences.jsm',
'SSLExceptions.jsm',
'TabMirror.jsm',
'WebappManager.jsm',
'WebappManagerWorker.js',
]
for var in ('ANDROID_PACKAGE_NAME', 'MOZ_APP_VERSION'):
DEFINES[var] = CONFIG[var]
for var in ('NIGHTLY_BUILD', 'RELEASE_BUILD', 'MOZ_ACCESSIBILITY',
'MOZILLA_OFFICIAL', 'MOZ_OFFICIAL_BRANDING', 'MOZ_SERVICES_HEALTHREPORT',
'MOZ_DEVICES', 'MOZ_DEVICES', 'MOZ_SAFE_BROWSING',
'MOZ_TELEMETRY_REPORTING', 'MOZ_WEBRTC'):
if CONFIG[var]:
DEFINES[var] = 1
# Keep it this way if at all possible.
EXTRA_PP_JS_MODULES += [
'WebappManager.jsm',
'AppConstants.jsm',
]

View File

@ -20,7 +20,7 @@ chrome.jar:
skin/aboutHealthReport.css (aboutHealthReport.css)
#endif
skin/aboutMemory.css (aboutMemory.css)
* skin/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css)
skin/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css)
skin/aboutReader.css (aboutReader.css)
skin/aboutSupport.css (aboutSupport.css)
skin/browser.css (browser.css)

View File

@ -1558,6 +1558,23 @@ nsHttpChannel::ProcessResponse()
Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_VERSION,
mResponseHead->Version());
#if defined(ANDROID) || defined(MOZ_B2G)
if (gHttpHandler->IsTelemetryEnabled()) {
// Gather telemetry on being sent a WAP content-type
// This check will catch (at least) the following content types:
// application/wml+xml, application/vnd.wap.xhtml+xml,
// text/vnd.wap.wml, application/vnd.wap.wmlc
bool isWap = false;
if (!mResponseHead->ContentType().IsEmpty() && (
mResponseHead->ContentType().Find(".wap") != -1 ||
mResponseHead->ContentType().Find("/wml") != -1)) {
isWap = true;
}
Telemetry::Accumulate(Telemetry::HTTP_WAP_CONTENT_TYPE_RECEIVED, isWap);
}
#endif
return rv;
}

View File

@ -262,6 +262,7 @@ user_pref("browser.newtabpage.directory.source", 'data:application/json,{"testin
user_pref("browser.newtabpage.directory.ping", "");
// Enable Loop
user_pref("loop.debug.loglevel", "All");
user_pref("loop.enabled", true);
user_pref("loop.throttled", false);
user_pref("loop.oauth.google.URL", "http://%(server)s/browser/browser/components/loop/test/mochitest/google_service.sjs?action=");

View File

@ -52,7 +52,8 @@ add_task(function* test_searchEngine_autoFill() {
}
yield promiseAddVisits(visits);
addBookmark({ uri: uri, title: "Example bookmark" });
ok(frecencyForUrl(uri) > 10000, "Adeded URI should have expected high frecency");
yield promiseAsyncUpdates();
ok(frecencyForUrl(uri) > 10000, "Added URI should have expected high frecency");
do_log_info("Check search domain is autoFilled even if there's an higher frecency match");
yield check_autocomplete({

View File

@ -1210,6 +1210,11 @@
"kind": "boolean",
"description": "Whether a HTTP transaction routed via Alt-Svc was scheme=http"
},
"HTTP_WAP_CONTENT_TYPE_RECEIVED": {
"expires_in_version": "40",
"kind": "boolean",
"description": "Whether a WAP content type response is served to the browser."
},
"SSL_HANDSHAKE_VERSION": {
"expires_in_version": "never",
"kind": "enumerated",

View File

@ -44,6 +44,7 @@ const NODE_ROUTING_METHODS = [
const NODE_PROPERTIES = {
"OscillatorNode": {
"properties": {
"type": {},
"frequency": {
"param": true
@ -51,34 +52,34 @@ const NODE_PROPERTIES = {
"detune": {
"param": true
}
}
},
"GainNode": {
"gain": {
"param": true
}
"properties": { "gain": { "param": true }}
},
"DelayNode": {
"delayTime": {
"param": true
}
"properties": { "delayTime": { "param": true }}
},
// TODO deal with figuring out adding `detune` AudioParam
// for AudioBufferSourceNode, which is in the spec
// but not yet added in implementation
// bug 1116852
"AudioBufferSourceNode": {
"properties": {
"buffer": { "Buffer": true },
"playbackRate": {
"param": true,
"param": true
},
"loop": {},
"loopStart": {},
"loopEnd": {}
}
},
"ScriptProcessorNode": {
"bufferSize": { "readonly": true }
"properties": { "bufferSize": { "readonly": true }}
},
"PannerNode": {
"properties": {
"panningModel": {},
"distanceModel": {},
"refDistance": {},
@ -87,66 +88,70 @@ const NODE_PROPERTIES = {
"coneInnerAngle": {},
"coneOuterAngle": {},
"coneOuterGain": {}
}
},
"ConvolverNode": {
"properties": {
"buffer": { "Buffer": true },
"normalize": {},
}
},
"DynamicsCompressorNode": {
"threshold": {
"param": true
},
"knee": {
"param": true
},
"ratio": {
"param": true
},
"properties": {
"threshold": { "param": true },
"knee": { "param": true },
"ratio": { "param": true },
"reduction": {},
"attack": {
"param": true
},
"release": {
"param": true
"attack": { "param": true },
"release": { "param": true }
}
},
"BiquadFilterNode": {
"properties": {
"type": {},
"frequency": {
"param": true
},
"Q": {
"param": true
},
"detune": {
"param": true
},
"gain": {
"param": true
"frequency": { "param": true },
"Q": { "param": true },
"detune": { "param": true },
"gain": { "param": true }
}
},
"WaveShaperNode": {
"properties": {
"curve": { "Float32Array": true },
"oversample": {}
}
},
"AnalyserNode": {
"properties": {
"fftSize": {},
"minDecibels": {},
"maxDecibels": {},
"smoothingTimeConstant": {},
"frequencyBinCount": { "readonly": true },
}
},
"AudioDestinationNode": {
"unbypassable": true
},
"ChannelSplitterNode": {
"unbypassable": true
},
"ChannelMergerNode": {
"unbypassable": true
},
"AudioDestinationNode": {},
"ChannelSplitterNode": {},
"ChannelMergerNode": {},
"MediaElementAudioSourceNode": {},
"MediaStreamAudioSourceNode": {},
"MediaStreamAudioDestinationNode": {
"unbypassable": true,
"properties": {
"stream": { "MediaStream": true }
}
},
"StereoPannerNode": {
"properties": {
"pan": {}
}
}
};
/**
@ -184,7 +189,7 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
}
// Create automation timelines for all AudioParams
Object.keys(NODE_PROPERTIES[this.type])
Object.keys(NODE_PROPERTIES[this.type].properties || {})
.filter(isAudioParam.bind(null, node))
.forEach(paramName => {
this.automation[paramName] = new AutomationTimeline(node[paramName].defaultValue);
@ -223,7 +228,9 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
return false;
}
return node.passThrough;
// Cast to boolean incase `passThrough` is undefined,
// like for AudioDestinationNode
return !!node.passThrough;
}, {
response: { bypassed: RetVal("boolean") }
}),
@ -231,10 +238,12 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
/**
* Takes a boolean, either enabling or disabling the "passThrough" option
* on an AudioNode. If a node is bypassed, an effects processing node (like gain, biquad),
* will allow the audio stream to pass through the node, unaffected.
* will allow the audio stream to pass through the node, unaffected. Returns
* the bypass state of the node.
*
* @param Boolean enable
* Whether the bypass value should be set on or off.
* @return Boolean
*/
bypass: method(function (enable) {
let node = this.node.get();
@ -243,10 +252,15 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
return;
}
let bypassable = !NODE_PROPERTIES[this.type].unbypassable;
if (bypassable) {
node.passThrough = enable;
}
return this.isBypassed();
}, {
request: { enable: Arg(0, "boolean") },
oneway: true
response: { bypassed: RetVal("boolean") }
}),
/**
@ -331,7 +345,7 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
* Name of the AudioParam whose flags are desired.
*/
getParamFlags: method(function (param) {
return (NODE_PROPERTIES[this.type] || {})[param];
return ((NODE_PROPERTIES[this.type] || {}).properties || {})[param];
}, {
request: { param: Arg(0, "string") },
response: { flags: RetVal("nullable:primitive") }
@ -341,8 +355,8 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
* Get an array of objects each containing a `param` and `value` property,
* corresponding to a property name and current value of the audio node.
*/
getParams: method(function () {
let props = Object.keys(NODE_PROPERTIES[this.type]);
getParams: method(function (param) {
let props = Object.keys(NODE_PROPERTIES[this.type].properties || {});
return props.map(prop =>
({ param: prop, value: this.getParam(prop), flags: this.getParamFlags(prop) }));
}, {
@ -600,6 +614,16 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({
this.finalize();
},
/**
* Returns definition of all AudioNodes, such as AudioParams, and
* flags.
*/
getDefinition: method(function () {
return NODE_PROPERTIES;
}, {
response: { definition: RetVal("json") }
}),
/**
* Starts waiting for the current tab actor's document global to be
* created, in order to instrument the Canvas context and become
@ -810,7 +834,7 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({
*/
_instrumentParams: function (node) {
let type = getConstructorName(node);
Object.keys(NODE_PROPERTIES[type])
Object.keys(NODE_PROPERTIES[type].properties || {})
.filter(isAudioParam.bind(null, node))
.forEach(paramName => {
let param = node[paramName];

View File

@ -489,9 +489,9 @@ let NetworkHelper = {
* @param object securityInfo
* The securityInfo object of a request. If null channel is assumed
* to be insecure.
* @param nsIRequest request
* The nsIRequest object for the request used to dig more information
* about this request.
* @param object httpActivity
* The httpActivity object for the request with at least members
* { private, hostname }.
*
* @return object
* Returns an object containing following members:
@ -510,7 +510,7 @@ let NetworkHelper = {
* - hsts: true if host uses Strict Transport Security, false otherwise
* - hpkp: true if host uses Public Key Pinning, false otherwise
*/
parseSecurityInfo: function NH_parseSecurityInfo(securityInfo, request) {
parseSecurityInfo: function NH_parseSecurityInfo(securityInfo, httpActivity) {
const info = {
state: "insecure",
};
@ -574,25 +574,24 @@ let NetworkHelper = {
info.cert = this.parseCertificateInfo(SSLStatus.serverCert);
// HSTS and HPKP if available.
if (request.URI) {
if (httpActivity.hostname) {
const sss = Cc["@mozilla.org/ssservice;1"]
.getService(Ci.nsISiteSecurityService);
request.QueryInterface(Ci.nsIPrivateBrowsingChannel);
// SiteSecurityService uses different storage if the channel is
// private. Thus we must give isSecureHost correct flags or we
// might get incorrect results.
let flags = (request.isChannelPrivate) ?
let flags = (httpActivity.private) ?
Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
let host = request.URI.host;
let host = httpActivity.hostname;
info.hsts = sss.isSecureHost(sss.HEADER_HSTS, host, flags);
info.hpkp = sss.isSecureHost(sss.HEADER_HPKP, host, flags);
} else {
DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
"Could not get HSTS/HPKP status as request.URI not available.");
"Could not get HSTS/HPKP status as hostname is not available.");
info.hsts = false;
info.hpkp = false;
}

View File

@ -12,7 +12,6 @@ loader.lazyGetter(this, "NetworkHelper", () => require("devtools/toolkit/webcons
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyImporter(this, "DevToolsUtils", "resource://gre/modules/devtools/DevToolsUtils.jsm");
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
loader.lazyImporter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm");
loader.lazyServiceGetter(this, "gActivityDistributor",
"@mozilla.org/network/http-activity-distributor;1",
"nsIHttpActivityDistributor");
@ -175,7 +174,7 @@ NetworkResponseListener.prototype = {
// was a redirect from http to https, the request object seems to contain
// security info for the https request after redirect.
let secinfo = this.httpActivity.channel.securityInfo;
let info = NetworkHelper.parseSecurityInfo(secinfo, this.request);
let info = NetworkHelper.parseSecurityInfo(secinfo, this.httpActivity);
this.httpActivity.owner.addSecurityInfo(info);
}),
@ -665,7 +664,9 @@ NetworkMonitor.prototype = {
// see NM__onRequestBodySent()
httpActivity.charset = win ? win.document.characterSet : null;
httpActivity.private = win ? PrivateBrowsingUtils.isWindowPrivate(win) : false;
aChannel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
httpActivity.private = aChannel.isChannelPrivate;
httpActivity.timings.REQUEST_HEADER = {
first: aTimestamp,
@ -751,6 +752,7 @@ NetworkMonitor.prototype = {
channel: aChannel,
charset: null, // see NM__onRequestHeader()
url: aChannel.URI.spec,
hostname: aChannel.URI.host, // needed for host specific security info
discardRequestBody: !this.saveRequestAndResponseBodies,
discardResponseBody: !this.saveRequestAndResponseBodies,
timings: {}, // internal timing information, see NM_observeActivity()

View File

@ -34,14 +34,12 @@ const MockSecurityInfo = {
}
};
const MockRequest = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrivateBrowsingChannel]),
URI: {
host: "include-subdomains.pinning.example.com"
}
const MockHttpInfo = {
hostname: "include-subdomains.pinning.example.com",
private: false,
};
function run_test() {
let result = NetworkHelper.parseSecurityInfo(MockSecurityInfo, MockRequest);
let result = NetworkHelper.parseSecurityInfo(MockSecurityInfo, MockHttpInfo);
equal(result.hpkp, true, "Static HPKP detected.");
}

View File

@ -288,24 +288,9 @@ function RemoteMirror(url, win, viewport, mirrorStartedCallback, contentWindow)
// This code insures the generated tab mirror is not wider than 1280 nor taller than 720
// Better dimensions should be chosen after the Roku Channel is working.
let windowId = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
let cWidth = Math.max(viewport.cssWidth, viewport.width);
let cHeight = Math.max(viewport.cssHeight, viewport.height);
const MAX_WIDTH = 1280;
const MAX_HEIGHT = 720;
let tWidth = 0;
let tHeight = 0;
// division and multiplication by 4 to ensure dimensions are multiples of 4
if ((cWidth / MAX_WIDTH) > (cHeight / MAX_HEIGHT)) {
tHeight = Math.ceil((MAX_WIDTH / (4* cWidth)) * cHeight) * 4;
tWidth = MAX_WIDTH;
} else {
tWidth = Math.ceil((MAX_HEIGHT / (4 * cHeight)) * cWidth) * 4;
tHeight = MAX_HEIGHT;
}
let constraints = {
video: {
mediaSource: "browser",
@ -313,10 +298,10 @@ function RemoteMirror(url, win, viewport, mirrorStartedCallback, contentWindow)
scrollWithPage: true,
advanced: [
{
width: { min: tWidth, max: tWidth },
height: { min: tHeight, max: tHeight }
width: { min: 0, max: MAX_WIDTH },
height: { min: 0, max: MAX_HEIGHT }
},
{ aspectRatio: cWidth / cHeight }
{ aspectRatio: MAX_WIDTH/MAX_HEIGHT }
]
}
};

View File

@ -26,6 +26,10 @@ xul|button {
margin-right: 4px;
}
xul|caption {
-moz-padding-start: 0;
}
xul|groupbox > xul|*.groupbox-body {
padding: 0;
}