зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
31441571eb
|
@ -19,13 +19,13 @@
|
|||
<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="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9100fa82fc355f5201e23e400fc6b40e875304ed"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="librecovery" patch="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<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="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
<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="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9100fa82fc355f5201e23e400fc6b40e875304ed"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -118,7 +118,7 @@
|
|||
<!-- Flame specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
|
||||
<project name="device/qcom/common" path="device/qcom/common" revision="34ed8345250bb97262d70a052217a92e83444ede"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="76f960b9512ec5c4726b5f52dd94bdf3c07e5071"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="75c65fce94693c9b990a7b1dab751bd2a536559b"/>
|
||||
<project name="kernel/msm" path="kernel" revision="228d59147ff524e90774c566eef03260cc6857b8"/>
|
||||
<project name="platform/bootable/recovery" path="bootable/recovery" revision="f2914eacee9120680a41463708bb6ee8291749fc"/>
|
||||
<project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="81c4a859d75d413ad688067829d21b7ba9205f81"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "01ae06e7d0c3c72d51e6801986339d6c06229c9b",
|
||||
"revision": "e204b914c3ddada45ae5ff5c9fc5e8f55f906ca7",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
<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="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<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="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
<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="82679a5ce84d1b6bf388da6536d5682a3ad56de3"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8341cddb04773957069ac1334692a888b8bb1091"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c629a8c1e0101d3937ceb4c52a60f7569b9d4243"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
|
||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
|
|
|
@ -66,3 +66,6 @@ MOZ_JSDOWNLOADS=1
|
|||
MOZ_SERVICES_FXACCOUNTS=1
|
||||
|
||||
MOZ_BUNDLED_FONTS=1
|
||||
|
||||
# Enable exact rooting on b2g.
|
||||
JSGC_USE_EXACT_ROOTING=1
|
||||
|
|
|
@ -3,6 +3,37 @@
|
|||
# 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/.
|
||||
|
||||
<menugroup id="context-navigation">
|
||||
<menuitem id="context-back"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&backButton.tooltip;"
|
||||
aria-label="&backCmd.label;"
|
||||
command="Browser:BackOrBackDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-forward"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&forwardButton.tooltip;"
|
||||
aria-label="&forwardCmd.label;"
|
||||
command="Browser:ForwardOrForwardDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-reload"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&reloadButton.tooltip;"
|
||||
aria-label="&reloadCmd.label;"
|
||||
oncommand="gContextMenu.reload(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-stop"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&stopButton.tooltip;"
|
||||
aria-label="&stopCmd.label;"
|
||||
command="Browser:Stop"/>
|
||||
<menuitem id="context-bookmarkpage"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&bookmarkPageCmd2.label;"
|
||||
aria-label="&bookmarkPageCmd2.label;"
|
||||
oncommand="gContextMenu.bookmarkThisPage();"/>
|
||||
</menugroup>
|
||||
<menuseparator id="context-sep-navigation"/>
|
||||
<menuseparator id="page-menu-separator"/>
|
||||
<menuitem id="spell-no-suggestions"
|
||||
disabled="true"
|
||||
|
@ -219,37 +250,6 @@
|
|||
accesskey="&hidePluginCmd.accesskey;"
|
||||
oncommand="gContextMenu.hidePlugin();"/>
|
||||
<menuseparator id="context-sep-ctp"/>
|
||||
<menugroup id="context-navigation">
|
||||
<menuitem id="context-back"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&backButton.tooltip;"
|
||||
aria-label="&backCmd.label;"
|
||||
command="Browser:BackOrBackDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-forward"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&forwardButton.tooltip;"
|
||||
aria-label="&forwardCmd.label;"
|
||||
command="Browser:ForwardOrForwardDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-reload"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&reloadButton.tooltip;"
|
||||
aria-label="&reloadCmd.label;"
|
||||
oncommand="gContextMenu.reload(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-stop"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&stopButton.tooltip;"
|
||||
aria-label="&stopCmd.label;"
|
||||
command="Browser:Stop"/>
|
||||
<menuitem id="context-bookmarkpage"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&bookmarkPageCmd2.label;"
|
||||
aria-label="&bookmarkPageCmd2.label;"
|
||||
oncommand="gContextMenu.bookmarkThisPage();"/>
|
||||
</menugroup>
|
||||
<menuseparator id="context-sep-navigation"/>
|
||||
<menuitem id="context-sharepage"
|
||||
label="&sharePageCmd.label;"
|
||||
accesskey="&sharePageCmd.accesskey;"
|
||||
|
|
|
@ -312,7 +312,7 @@
|
|||
oncommand="BrowserFullScreen();"/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="contentAreaContextMenu" pagemenu="start"
|
||||
<menupopup id="contentAreaContextMenu" pagemenu="#page-menu-separator"
|
||||
onpopupshowing="if (event.target != this)
|
||||
return true;
|
||||
gContextMenu = new nsContextMenu(this, event.shiftKey);
|
||||
|
|
|
@ -449,7 +449,13 @@ function runTest(testNum) {
|
|||
|
||||
case 19:
|
||||
// Context menu for element with assigned content context menu
|
||||
checkContextMenu(["+Plain item", {type: "", icon: "", checked: false, disabled: false},
|
||||
checkContextMenu(["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"+Plain item", {type: "", icon: "", checked: false, disabled: false},
|
||||
"+Disabled item", {type: "", icon: "", checked: false, disabled: true},
|
||||
"+Item w/ textContent", {type: "", icon: "", checked: false, disabled: false},
|
||||
"---", null,
|
||||
|
@ -469,12 +475,6 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"+Checkbox", {type: "checkbox", icon: "", checked: false, disabled: false}], null,
|
||||
"---", null,
|
||||
"context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -501,14 +501,14 @@ function runTest(testNum) {
|
|||
|
||||
case 20:
|
||||
// Context menu for DOM Fullscreen mode (NOTE: this is *NOT* on an img)
|
||||
checkContextMenu(["context-leave-dom-fullscreen", true,
|
||||
"---", null,
|
||||
"context-navigation", null,
|
||||
checkContextMenu(["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-leave-dom-fullscreen", true,
|
||||
"---", null,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -694,15 +694,15 @@ function runTest(testNum) {
|
|||
|
||||
case 27:
|
||||
// Context menu for click-to-play blocked plugin
|
||||
checkContextMenu(["context-ctp-play", true,
|
||||
"context-ctp-hide", true,
|
||||
"---", null,
|
||||
"context-navigation", null,
|
||||
checkContextMenu(["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-ctp-play", true,
|
||||
"context-ctp-hide", true,
|
||||
"---", null,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
|
|
@ -130,6 +130,12 @@ let UI = {
|
|||
rootButton.setAttribute("hidden", "true");
|
||||
}
|
||||
}
|
||||
let tabsButton = document.querySelector(".tab.browser-tabs");
|
||||
if (response.tabs.length > 0) {
|
||||
tabsButton.classList.remove("hidden");
|
||||
} else {
|
||||
tabsButton.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<button class="help">&device.help;</button>
|
||||
</a>
|
||||
</div>
|
||||
<div onclick="UI.setTab('browser-tabs')" class="tab sidebar-item browser-tabs" title="&device.browserTabsTooltip;">&device.browserTabs;</div>
|
||||
<div onclick="UI.setTab('browser-tabs')" class="tab sidebar-item browser-tabs" hidden="true" title="&device.browserTabsTooltip;">&device.browserTabs;</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// Tests that graph widgets can properly add data and regions.
|
||||
|
||||
const TEST_DATA = {"112":48,"213":59,"313":60,"413":59,"530":59,"646":58,"747":60,"863":48,"980":37,"1097":30,"1213":29,"1330":23,"1430":10,"1534":17,"1645":20,"1746":22,"1846":39,"1963":26,"2080":27,"2197":35,"2312":47,"2412":53,"2514":60,"2630":37,"2730":36,"2830":37,"2946":36,"3046":40,"3163":47,"3280":41,"3380":35,"3480":27,"3580":39,"3680":42,"3780":49,"3880":55,"3980":60,"4080":60,"4180":60};
|
||||
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
|
||||
const TEST_REGIONS = [{ start: 320, end: 460 }, { start: 780, end: 860 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// Tests that graph widgets can correctly determine which regions are hovered.
|
||||
|
||||
const TEST_DATA = {"112":48,"213":59,"313":60,"413":59,"530":59,"646":58,"747":60,"863":48,"980":37,"1097":30,"1213":29,"1330":23,"1430":10,"1534":17,"1645":20,"1746":22,"1846":39,"1963":26,"2080":27,"2197":35,"2312":47,"2412":53,"2514":60,"2630":37,"2730":36,"2830":37,"2946":36,"3046":40,"3163":47,"3280":41,"3380":35,"3480":27,"3580":39,"3680":42,"3780":49,"3880":55,"3980":60,"4080":60,"4180":60};
|
||||
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
|
||||
const TEST_REGIONS = [{ start: 320, end: 460 }, { start: 780, end: 860 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// Tests if clicking on regions adds a selection spanning that region.
|
||||
|
||||
const TEST_DATA = {"112":48,"213":59,"313":60,"413":59,"530":59,"646":58,"747":60,"863":48,"980":37,"1097":30,"1213":29,"1330":23,"1430":10,"1534":17,"1645":20,"1746":22,"1846":39,"1963":26,"2080":27,"2197":35,"2312":47,"2412":53,"2514":60,"2630":37,"2730":36,"2830":37,"2946":36,"3046":40,"3163":47,"3280":41,"3380":35,"3480":27,"3580":39,"3680":42,"3780":49,"3880":55,"3980":60,"4080":60,"4180":60};
|
||||
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
|
||||
const TEST_REGIONS = [{ start: 320, end: 460 }, { start: 780, end: 860 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// Tests if selecting, resizing, moving selections and zooming in/out works.
|
||||
|
||||
const TEST_DATA = {"112":48,"213":59,"313":60,"413":59,"530":59,"646":58,"747":60,"863":48,"980":37,"1097":30,"1213":29,"1330":23,"1430":10,"1534":17,"1645":20,"1746":22,"1846":39,"1963":26,"2080":27,"2197":35,"2312":47,"2412":53,"2514":60,"2630":37,"2730":36,"2830":37,"2946":36,"3046":40,"3163":47,"3280":41,"3380":35,"3480":27,"3580":39,"3680":42,"3780":49,"3880":55,"3980":60,"4080":60,"4180":60};
|
||||
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// Tests if a selection is dropped when clicking outside of it.
|
||||
|
||||
const TEST_DATA = {"112":48,"213":59,"313":60,"413":59,"530":59,"646":58,"747":60,"863":48,"980":37,"1097":30,"1213":29,"1330":23,"1430":10,"1534":17,"1645":20,"1746":22,"1846":39,"1963":26,"2080":27,"2197":35,"2312":47,"2412":53,"2514":60,"2630":37,"2730":36,"2830":37,"2946":36,"3046":40,"3163":47,"3280":41,"3380":35,"3480":27,"3580":39,"3680":42,"3780":49,"3880":55,"3980":60,"4080":60,"4180":60};
|
||||
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// Tests that line graphs properly create the gutter and tooltips.
|
||||
|
||||
const TEST_DATA = {"112":48,"213":59,"313":60,"413":59,"530":59,"646":58,"747":60,"863":48,"980":37,"1097":30,"1213":29,"1330":23,"1430":10,"1534":17,"1645":20,"1746":22,"1846":39,"1963":26,"2080":27,"2197":35,"2312":47,"2412":53,"2514":60,"2630":37,"2730":36,"2830":37,"2946":36,"3046":40,"3163":47,"3280":41,"3380":35,"3480":27,"3580":39,"3680":42,"3780":49,"3880":55,"3980":60,"4080":60,"4180":60};
|
||||
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that line graph properly handles resizing.
|
||||
// Tests that line graphs properly handle resizing.
|
||||
|
||||
const TEST_DATA = {"112":48,"213":59,"313":60,"413":59,"530":59,"646":58,"747":60,"863":48,"980":37,"1097":30,"1213":29,"1330":23,"1430":10,"1534":17,"1645":20,"1746":22,"1846":39,"1963":26,"2080":27,"2197":35,"2312":47,"2412":53,"2514":60,"2630":37,"2730":36,"2830":37,"2946":36,"3046":40,"3163":47,"3280":41,"3380":35,"3480":27,"3580":39,"3680":42,"3780":49,"3880":55,"3980":60,"4080":60,"4180":60};
|
||||
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
|
||||
|
|
|
@ -941,6 +941,12 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
regionBackgroundColor: LINE_GRAPH_REGION_BACKGROUND_COLOR,
|
||||
regionStripesColor: LINE_GRAPH_REGION_STRIPES_COLOR,
|
||||
|
||||
/**
|
||||
* Points that are too close too each other in the graph will not be rendered.
|
||||
* This scalar specifies the required minimum squared distance between points.
|
||||
*/
|
||||
minDistanceBetweenPoints: LINE_GRAPH_MIN_SQUARED_DISTANCE_BETWEEN_POINTS,
|
||||
|
||||
/**
|
||||
* Renders the graph on a canvas.
|
||||
* @see AbstractCanvasGraph.prototype.buildGraphImage
|
||||
|
@ -958,16 +964,16 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
let firstTick;
|
||||
let lastTick;
|
||||
|
||||
for (let [tick, value] of Iterator(this._data)) {
|
||||
for (let { delta, value } of this._data) {
|
||||
maxValue = Math.max(value, maxValue);
|
||||
minValue = Math.min(value, minValue);
|
||||
sumValues += value;
|
||||
totalTicks++;
|
||||
|
||||
if (!firstTick) {
|
||||
firstTick = tick;
|
||||
firstTick = delta;
|
||||
} else {
|
||||
lastTick = tick;
|
||||
lastTick = delta;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -997,23 +1003,23 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
let prevX = 0;
|
||||
let prevY = 0;
|
||||
|
||||
for (let [tick, value] of Iterator(this._data)) {
|
||||
let currX = tick * dataScaleX;
|
||||
for (let { delta, value } of this._data) {
|
||||
let currX = delta * dataScaleX;
|
||||
let currY = height - value * dataScaleY;
|
||||
|
||||
if (tick == firstTick) {
|
||||
if (delta == firstTick) {
|
||||
ctx.moveTo(-LINE_GRAPH_STROKE_WIDTH, height);
|
||||
ctx.lineTo(-LINE_GRAPH_STROKE_WIDTH, currY);
|
||||
}
|
||||
|
||||
let distance = distSquared(prevX, prevY, currX, currY);
|
||||
if (distance > LINE_GRAPH_MIN_SQUARED_DISTANCE_BETWEEN_POINTS) {
|
||||
if (distance > this.minDistanceBetweenPoints) {
|
||||
ctx.lineTo(currX, currY);
|
||||
prevX = currX;
|
||||
prevY = currY;
|
||||
}
|
||||
|
||||
if (tick == lastTick) {
|
||||
if (delta == lastTick) {
|
||||
ctx.lineTo(width + LINE_GRAPH_STROKE_WIDTH, currY);
|
||||
ctx.lineTo(width + LINE_GRAPH_STROKE_WIDTH, height);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 1.0.266
|
||||
Current extension version is: 1.0.277
|
||||
|
||||
|
|
|
@ -60,6 +60,10 @@ function getObjectUrl(window) {
|
|||
}
|
||||
|
||||
// Checking if overlay is a proper PlayPreview overlay.
|
||||
if (element.displayedType !== element.TYPE_NULL ||
|
||||
element.pluginFallbackType !== element.PLUGIN_PLAY_PREVIEW) {
|
||||
return null; // invalid plugin element overlay state
|
||||
}
|
||||
for (var i = 0; i < element.children.length; i++) {
|
||||
if (element.children[i] === containerElement) {
|
||||
return null; // invalid plugin element overlay
|
||||
|
|
|
@ -21,8 +21,8 @@ if (typeof PDFJS === 'undefined') {
|
|||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '1.0.266';
|
||||
PDFJS.build = '5b16323';
|
||||
PDFJS.version = '1.0.277';
|
||||
PDFJS.build = '250d394';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -3750,6 +3750,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
|||
this.fontSize = 0;
|
||||
this.fontSizeScale = 1;
|
||||
this.textMatrix = IDENTITY_MATRIX;
|
||||
this.textMatrixScale = 1;
|
||||
this.fontMatrix = FONT_IDENTITY_MATRIX;
|
||||
this.leading = 0;
|
||||
// Current point (in user coordinates)
|
||||
|
@ -4516,6 +4517,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
// Text
|
||||
beginText: function CanvasGraphics_beginText() {
|
||||
this.current.textMatrix = IDENTITY_MATRIX;
|
||||
this.current.textMatrixScale = 1;
|
||||
this.current.x = this.current.lineX = 0;
|
||||
this.current.y = this.current.lineY = 0;
|
||||
},
|
||||
|
@ -4620,6 +4622,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
},
|
||||
setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
|
||||
this.current.textMatrix = [a, b, c, d, e, f];
|
||||
this.current.textMatrixScale = Math.sqrt(a * a + b * b);
|
||||
|
||||
this.current.x = this.current.lineX = 0;
|
||||
this.current.y = this.current.lineY = 0;
|
||||
|
@ -4627,24 +4630,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
nextLine: function CanvasGraphics_nextLine() {
|
||||
this.moveText(0, this.current.leading);
|
||||
},
|
||||
applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y + current.textRise);
|
||||
if (current.fontDirection > 0) {
|
||||
ctx.scale(current.textHScale, -1);
|
||||
} else {
|
||||
ctx.scale(-current.textHScale, 1);
|
||||
}
|
||||
},
|
||||
|
||||
paintChar: function CanvasGraphics_paintChar(character, x, y) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize / current.fontSizeScale;
|
||||
var textRenderingMode = current.textRenderingMode;
|
||||
var fontSize = current.fontSize / current.fontSizeScale;
|
||||
var fillStrokeMode = textRenderingMode &
|
||||
TextRenderingMode.FILL_STROKE_MASK;
|
||||
var isAddToPathSet = !!(textRenderingMode &
|
||||
|
@ -4710,181 +4702,182 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
},
|
||||
|
||||
showText: function CanvasGraphics_showText(glyphs) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize;
|
||||
var fontSizeScale = current.fontSizeScale;
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var textHScale = current.textHScale * current.fontDirection;
|
||||
var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
|
||||
var glyphsLength = glyphs.length;
|
||||
var vertical = font.vertical;
|
||||
var defaultVMetrics = font.defaultVMetrics;
|
||||
var i, glyph, width;
|
||||
if (font.isType3Font) {
|
||||
return this.showType3Text(glyphs);
|
||||
}
|
||||
|
||||
var fontSize = current.fontSize;
|
||||
if (fontSize === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Type3 fonts - each glyph is a "mini-PDF"
|
||||
if (font.isType3Font) {
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y);
|
||||
var ctx = this.ctx;
|
||||
var fontSizeScale = current.fontSizeScale;
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var fontDirection = current.fontDirection;
|
||||
var textHScale = current.textHScale * fontDirection;
|
||||
var glyphsLength = glyphs.length;
|
||||
var vertical = font.vertical;
|
||||
var defaultVMetrics = font.defaultVMetrics;
|
||||
var widthAdvanceScale = fontSize * current.fontMatrix[0];
|
||||
|
||||
ctx.scale(textHScale, 1);
|
||||
var simpleFillText =
|
||||
current.textRenderingMode === TextRenderingMode.FILL &&
|
||||
!font.disableFontFace;
|
||||
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
this.ctx.translate(wordSpacing, 0);
|
||||
current.x += wordSpacing * textHScale;
|
||||
continue;
|
||||
}
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y + current.textRise);
|
||||
|
||||
this.processingType3 = glyph;
|
||||
this.save();
|
||||
ctx.scale(fontSize, fontSize);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
var operatorList = font.charProcOperatorList[glyph.operatorListId];
|
||||
this.executeOperatorList(operatorList);
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
width = ((transformed[0] * fontSize + charSpacing) *
|
||||
current.fontDirection);
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width * textHScale;
|
||||
}
|
||||
ctx.restore();
|
||||
this.processingType3 = null;
|
||||
if (fontDirection > 0) {
|
||||
ctx.scale(textHScale, -1);
|
||||
} else {
|
||||
ctx.save();
|
||||
this.applyTextTransforms();
|
||||
ctx.scale(textHScale, 1);
|
||||
}
|
||||
|
||||
var lineWidth = current.lineWidth;
|
||||
var a1 = current.textMatrix[0], b1 = current.textMatrix[1];
|
||||
var scale = Math.sqrt(a1 * a1 + b1 * b1);
|
||||
if (scale === 0 || lineWidth === 0) {
|
||||
lineWidth = this.getSinglePixelWidth();
|
||||
var lineWidth = current.lineWidth;
|
||||
var scale = current.textMatrixScale;
|
||||
if (scale === 0 || lineWidth === 0) {
|
||||
lineWidth = this.getSinglePixelWidth();
|
||||
} else {
|
||||
lineWidth /= scale;
|
||||
}
|
||||
|
||||
if (fontSizeScale != 1.0) {
|
||||
ctx.scale(fontSizeScale, fontSizeScale);
|
||||
lineWidth /= fontSizeScale;
|
||||
}
|
||||
|
||||
ctx.lineWidth = lineWidth;
|
||||
|
||||
var x = 0, i;
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
var glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
x += fontDirection * wordSpacing;
|
||||
continue;
|
||||
} else if (isNum(glyph)) {
|
||||
x += -glyph * fontSize * 0.001;
|
||||
continue;
|
||||
}
|
||||
|
||||
var restoreNeeded = false;
|
||||
var character = glyph.fontChar;
|
||||
var accent = glyph.accent;
|
||||
var scaledX, scaledY, scaledAccentX, scaledAccentY;
|
||||
var width = glyph.width;
|
||||
if (vertical) {
|
||||
var vmetric, vx, vy;
|
||||
vmetric = glyph.vmetric || defaultVMetrics;
|
||||
vx = glyph.vmetric ? vmetric[1] : width * 0.5;
|
||||
vx = -vx * widthAdvanceScale;
|
||||
vy = vmetric[2] * widthAdvanceScale;
|
||||
|
||||
width = vmetric ? -vmetric[0] : width;
|
||||
scaledX = vx / fontSizeScale;
|
||||
scaledY = (x + vy) / fontSizeScale;
|
||||
} else {
|
||||
lineWidth /= scale;
|
||||
scaledX = x / fontSizeScale;
|
||||
scaledY = 0;
|
||||
}
|
||||
|
||||
if (fontSizeScale != 1.0) {
|
||||
ctx.scale(fontSizeScale, fontSizeScale);
|
||||
lineWidth /= fontSizeScale;
|
||||
if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) {
|
||||
// some standard fonts may not have the exact width, trying to
|
||||
// rescale per character
|
||||
var measuredWidth = ctx.measureText(character).width * 1000 /
|
||||
fontSize * fontSizeScale;
|
||||
var characterScaleX = width / measuredWidth;
|
||||
restoreNeeded = true;
|
||||
ctx.save();
|
||||
ctx.scale(characterScaleX, 1);
|
||||
scaledX /= characterScaleX;
|
||||
}
|
||||
|
||||
ctx.lineWidth = lineWidth;
|
||||
|
||||
var x = 0;
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
x += current.fontDirection * wordSpacing;
|
||||
continue;
|
||||
}
|
||||
|
||||
var restoreNeeded = false;
|
||||
var character = glyph.fontChar;
|
||||
var vmetric = glyph.vmetric || defaultVMetrics;
|
||||
if (vertical) {
|
||||
var vx = glyph.vmetric ? vmetric[1] : glyph.width * 0.5;
|
||||
vx = -vx * fontSize * current.fontMatrix[0];
|
||||
var vy = vmetric[2] * fontSize * current.fontMatrix[0];
|
||||
}
|
||||
width = vmetric ? -vmetric[0] : glyph.width;
|
||||
var charWidth = width * fontSize * current.fontMatrix[0] +
|
||||
charSpacing * current.fontDirection;
|
||||
var accent = glyph.accent;
|
||||
|
||||
var scaledX, scaledY, scaledAccentX, scaledAccentY;
|
||||
|
||||
if (vertical) {
|
||||
scaledX = vx / fontSizeScale;
|
||||
scaledY = (x + vy) / fontSizeScale;
|
||||
} else {
|
||||
scaledX = x / fontSizeScale;
|
||||
scaledY = 0;
|
||||
}
|
||||
|
||||
if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) {
|
||||
// some standard fonts may not have the exact width, trying to
|
||||
// rescale per character
|
||||
var measuredWidth = ctx.measureText(character).width * 1000 /
|
||||
current.fontSize * current.fontSizeScale;
|
||||
var characterScaleX = width / measuredWidth;
|
||||
restoreNeeded = true;
|
||||
ctx.save();
|
||||
ctx.scale(characterScaleX, 1);
|
||||
scaledX /= characterScaleX;
|
||||
if (accent) {
|
||||
scaledAccentX /= characterScaleX;
|
||||
}
|
||||
}
|
||||
|
||||
if (simpleFillText && !accent) {
|
||||
// common case
|
||||
ctx.fillText(character, scaledX, scaledY);
|
||||
} else {
|
||||
this.paintChar(character, scaledX, scaledY);
|
||||
if (accent) {
|
||||
scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
|
||||
scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
|
||||
this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY);
|
||||
}
|
||||
|
||||
x += charWidth;
|
||||
|
||||
if (restoreNeeded) {
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
if (vertical) {
|
||||
current.y -= x * textHScale;
|
||||
} else {
|
||||
current.x += x * textHScale;
|
||||
|
||||
var charWidth = width * widthAdvanceScale + charSpacing * fontDirection;
|
||||
x += charWidth;
|
||||
|
||||
if (restoreNeeded) {
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
if (vertical) {
|
||||
current.y -= x * textHScale;
|
||||
} else {
|
||||
current.x += x * textHScale;
|
||||
}
|
||||
ctx.restore();
|
||||
},
|
||||
showSpacedText: function CanvasGraphics_showSpacedText(arr) {
|
||||
|
||||
showType3Text: function CanvasGraphics_showType3Text(glyphs) {
|
||||
// Type3 fonts - each glyph is a "mini-PDF"
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize;
|
||||
// TJ array's number is independent from fontMatrix
|
||||
var textHScale = current.textHScale * 0.001 * current.fontDirection;
|
||||
var arrLength = arr.length;
|
||||
var vertical = font.vertical;
|
||||
var fontDirection = current.fontDirection;
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var textHScale = current.textHScale * fontDirection;
|
||||
var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
|
||||
var glyphsLength = glyphs.length;
|
||||
var i, glyph, width;
|
||||
|
||||
for (var i = 0; i < arrLength; ++i) {
|
||||
var e = arr[i];
|
||||
if (isNum(e)) {
|
||||
var spacingLength = -e * fontSize * textHScale;
|
||||
if (vertical) {
|
||||
current.y += spacingLength;
|
||||
} else {
|
||||
current.x += spacingLength;
|
||||
}
|
||||
|
||||
} else {
|
||||
this.showText(e);
|
||||
}
|
||||
if (fontSize === 0) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
|
||||
this.nextLine();
|
||||
this.showText(text);
|
||||
},
|
||||
nextLineSetSpacingShowText:
|
||||
function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
|
||||
charSpacing,
|
||||
text) {
|
||||
this.setWordSpacing(wordSpacing);
|
||||
this.setCharSpacing(charSpacing);
|
||||
this.nextLineShowText(text);
|
||||
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y);
|
||||
|
||||
ctx.scale(textHScale, 1);
|
||||
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
this.ctx.translate(wordSpacing, 0);
|
||||
current.x += wordSpacing * textHScale;
|
||||
continue;
|
||||
} else if (isNum(glyph)) {
|
||||
var spacingLength = -glyph * 0.001 * fontSize;
|
||||
this.ctx.translate(spacingLength, 0);
|
||||
current.x += spacingLength * textHScale;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.processingType3 = glyph;
|
||||
this.save();
|
||||
ctx.scale(fontSize, fontSize);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
var operatorList = font.charProcOperatorList[glyph.operatorListId];
|
||||
this.executeOperatorList(operatorList);
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
width = ((transformed[0] * fontSize + charSpacing) * fontDirection);
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width * textHScale;
|
||||
}
|
||||
ctx.restore();
|
||||
this.processingType3 = null;
|
||||
},
|
||||
|
||||
// Type3 fonts
|
||||
|
|
|
@ -21,8 +21,8 @@ if (typeof PDFJS === 'undefined') {
|
|||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '1.0.266';
|
||||
PDFJS.build = '5b16323';
|
||||
PDFJS.version = '1.0.277';
|
||||
PDFJS.build = '250d394';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -15606,7 +15606,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
assert(isName(type),
|
||||
'XObject should have a Name subtype');
|
||||
|
||||
if ('Form' == type.name) {
|
||||
if (type.name === 'Form') {
|
||||
stateManager.save();
|
||||
return self.buildFormXObject(resources, xobj, null,
|
||||
operatorList,
|
||||
|
@ -15615,11 +15615,16 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
stateManager.restore();
|
||||
next(resolve, reject);
|
||||
}, reject);
|
||||
} else if ('Image' == type.name) {
|
||||
} else if (type.name === 'Image') {
|
||||
self.buildPaintImageXObject(resources, xobj, false,
|
||||
operatorList, name, imageCache);
|
||||
args = [];
|
||||
continue;
|
||||
} else if (type.name === 'PS') {
|
||||
// PostScript XObjects are unused when viewing documents.
|
||||
// See section 4.7.1 of Adobe's PDF reference.
|
||||
info('Ignored XObject subtype PS');
|
||||
continue;
|
||||
} else {
|
||||
error('Unhandled XObject subtype ' + type.name);
|
||||
}
|
||||
|
@ -15651,18 +15656,31 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
break;
|
||||
case OPS.showSpacedText:
|
||||
var arr = args[0];
|
||||
var combinedGlyphs = [];
|
||||
var arrLength = arr.length;
|
||||
for (i = 0; i < arrLength; ++i) {
|
||||
if (isString(arr[i])) {
|
||||
arr[i] = self.handleText(arr[i], stateManager.state);
|
||||
var arrItem = arr[i];
|
||||
if (isString(arrItem)) {
|
||||
Array.prototype.push.apply(combinedGlyphs,
|
||||
self.handleText(arrItem, stateManager.state));
|
||||
} else if (isNum(arrItem)) {
|
||||
combinedGlyphs.push(arrItem);
|
||||
}
|
||||
}
|
||||
args[0] = combinedGlyphs;
|
||||
fn = OPS.showText;
|
||||
break;
|
||||
case OPS.nextLineShowText:
|
||||
operatorList.addOp(OPS.nextLine);
|
||||
args[0] = self.handleText(args[0], stateManager.state);
|
||||
fn = OPS.showText;
|
||||
break;
|
||||
case OPS.nextLineSetSpacingShowText:
|
||||
args[2] = self.handleText(args[2], stateManager.state);
|
||||
operatorList.addOp(OPS.nextLine);
|
||||
operatorList.addOp(OPS.setWordSpacing, [args.shift()]);
|
||||
operatorList.addOp(OPS.setCharSpacing, [args.shift()]);
|
||||
args[0] = self.handleText(args[0], stateManager.state);
|
||||
fn = OPS.showText;
|
||||
break;
|
||||
case OPS.setTextRenderingMode:
|
||||
stateManager.state.textRenderingMode = args[0];
|
||||
|
|
|
@ -246,27 +246,8 @@ var Stepper = (function StepperClosure() {
|
|||
return d;
|
||||
}
|
||||
|
||||
function glyphsToString(glyphs) {
|
||||
var out = '';
|
||||
for (var i = 0; i < glyphs.length; i++) {
|
||||
if (glyphs[i] === null) {
|
||||
out += ' ';
|
||||
} else {
|
||||
out += glyphs[i].fontChar;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
var opMap = null;
|
||||
|
||||
var glyphCommands = {
|
||||
'showText': 0,
|
||||
'showSpacedText': 0,
|
||||
'nextLineShowText': 0,
|
||||
'nextLineSetSpacingShowText': 2
|
||||
};
|
||||
|
||||
function simplifyArgs(args) {
|
||||
if (typeof args === 'string') {
|
||||
var MAX_STRING_LENGTH = 75;
|
||||
|
@ -367,24 +348,26 @@ var Stepper = (function StepperClosure() {
|
|||
line.appendChild(c('td', i.toString()));
|
||||
var fn = opMap[operatorList.fnArray[i]];
|
||||
var decArgs = args;
|
||||
if (fn in glyphCommands) {
|
||||
var glyphIndex = glyphCommands[fn];
|
||||
var glyphs = args[glyphIndex];
|
||||
decArgs = args.slice();
|
||||
var newArg;
|
||||
if (fn === 'showSpacedText') {
|
||||
newArg = [];
|
||||
for (var j = 0; j < glyphs.length; j++) {
|
||||
if (typeof glyphs[j] === 'number') {
|
||||
newArg.push(glyphs[j]);
|
||||
} else {
|
||||
newArg.push(glyphsToString(glyphs[j]));
|
||||
if (fn === 'showText') {
|
||||
var glyphs = args[0];
|
||||
var newArgs = [];
|
||||
var str = [];
|
||||
for (var j = 0; j < glyphs.length; j++) {
|
||||
var glyph = glyphs[j];
|
||||
if (typeof glyph === 'object' && glyph !== null) {
|
||||
str.push(glyph.fontChar);
|
||||
} else {
|
||||
if (str.length > 0) {
|
||||
newArgs.push(str.join(''));
|
||||
str = [];
|
||||
}
|
||||
newArgs.push(glyph); // null or number
|
||||
}
|
||||
} else {
|
||||
newArg = glyphsToString(glyphs);
|
||||
}
|
||||
decArgs[glyphIndex] = newArg;
|
||||
if (str.length > 0) {
|
||||
newArgs.push(str.join(''));
|
||||
}
|
||||
decArgs = [newArgs];
|
||||
}
|
||||
line.appendChild(c('td', fn));
|
||||
line.appendChild(c('td', JSON.stringify(simplifyArgs(decArgs))));
|
||||
|
|
|
@ -322,6 +322,10 @@ header {
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
.browser-tabs.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app, .browser-tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -652,6 +652,7 @@ GK_ATOM(ona2dpstatuschanged, "ona2dpstatuschanged")
|
|||
GK_ATOM(onabort, "onabort")
|
||||
GK_ATOM(onactivate, "onactivate")
|
||||
GK_ATOM(onadapteradded, "onadapteradded")
|
||||
GK_ATOM(onadapterremoved, "onadapterremoved")
|
||||
GK_ATOM(onafterprint, "onafterprint")
|
||||
GK_ATOM(onafterscriptexecute, "onafterscriptexecute")
|
||||
GK_ATOM(onalerting, "onalerting")
|
||||
|
|
|
@ -3198,7 +3198,7 @@ nsDOMWindowUtils::GetPlugins(JSContext* cx, JS::MutableHandle<JS::Value> aPlugin
|
|||
doc->GetPlugins(plugins);
|
||||
|
||||
JS::Rooted<JSObject*> jsPlugins(cx);
|
||||
nsresult rv = nsTArrayToJSArray(cx, plugins, jsPlugins.address());
|
||||
nsresult rv = nsTArrayToJSArray(cx, plugins, &jsPlugins);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aPlugins.setObject(*jsPlugins);
|
||||
|
|
|
@ -104,7 +104,7 @@ public:
|
|||
}
|
||||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
JSObject* JsDevices = nullptr;
|
||||
JS::Rooted<JSObject*> JsDevices(cx);
|
||||
rv = nsTArrayToJSArray(cx, devices, &JsDevices);
|
||||
if (!JsDevices) {
|
||||
BT_WARNING("Cannot create JS array!");
|
||||
|
@ -260,7 +260,7 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
|||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
JS::Rooted<JSObject*> uuids(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &uuids))) {
|
||||
BT_WARNING("Cannot set JS UUIDs object!");
|
||||
return;
|
||||
}
|
||||
|
@ -276,8 +276,7 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
|||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
JS::Rooted<JSObject*> deviceAddresses(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mDeviceAddresses,
|
||||
deviceAddresses.address()))) {
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mDeviceAddresses, &deviceAddresses))) {
|
||||
BT_WARNING("Cannot set JS Devices object!");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
|||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
|
||||
JS::Rooted<JSObject*> uuids(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &uuids))) {
|
||||
BT_WARNING("Cannot set JS UUIDs object!");
|
||||
return;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
|||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
|
||||
JS::Rooted<JSObject*> services(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mServices, services.address()))) {
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mServices, &services))) {
|
||||
BT_WARNING("Cannot set JS Services object!");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,12 @@ extern bool gBluetoothDebugFlag;
|
|||
#define BT_WARNING(msg, ...) printf("%s: " msg, __FUNCTION__, ##__VA_ARGS__))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Prints 'R'ELEASE build logs for WebBluetooth API v2.
|
||||
*/
|
||||
#define BT_API2_LOGR(msg, ...) \
|
||||
BT_LOGR("[WEBBT-API2] " msg, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Wrap literal name and value into a BluetoothNamedValue
|
||||
* and append it to the array.
|
||||
|
|
|
@ -11,14 +11,13 @@
|
|||
#include "BluetoothService.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
|
||||
#include "DOMRequest.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/BluetoothManager2Binding.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/BluetoothManager2Binding.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -31,61 +30,49 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
|||
NS_IMPL_ADDREF_INHERITED(BluetoothManager, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothManager, DOMEventTargetHelper)
|
||||
|
||||
class GetAdapterTask : public BluetoothReplyRunnable
|
||||
class GetAdaptersTask : public BluetoothReplyRunnable
|
||||
{
|
||||
public:
|
||||
GetAdapterTask(BluetoothManager* aManager,
|
||||
nsIDOMDOMRequest* aReq) :
|
||||
BluetoothReplyRunnable(aReq),
|
||||
mManagerPtr(aManager)
|
||||
{
|
||||
}
|
||||
public:
|
||||
GetAdaptersTask(BluetoothManager* aManager)
|
||||
: BluetoothReplyRunnable(nullptr)
|
||||
, mManager(aManager)
|
||||
{ }
|
||||
|
||||
bool
|
||||
ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
/**
|
||||
* Unwrap BluetoothReply.BluetoothReplySuccess.BluetoothValue =
|
||||
* BluetoothNamedValue[]
|
||||
* |
|
||||
* |__ BluetoothNamedValue =
|
||||
* | {"Adapter", BluetoothValue = BluetoothNamedValue[]}
|
||||
* |
|
||||
* |__ BluetoothNamedValue =
|
||||
* | {"Adapter", BluetoothValue = BluetoothNamedValue[]}
|
||||
* ...
|
||||
*/
|
||||
|
||||
// Extract the array of all adapters' properties
|
||||
const BluetoothValue& adaptersProperties =
|
||||
mReply->get_BluetoothReplySuccess().value();
|
||||
NS_ENSURE_TRUE(adaptersProperties.type() ==
|
||||
BluetoothValue::TArrayOfBluetoothNamedValue, false);
|
||||
|
||||
const InfallibleTArray<BluetoothNamedValue>& adaptersPropertiesArray =
|
||||
adaptersProperties.get_ArrayOfBluetoothNamedValue();
|
||||
BT_API2_LOGR("GetAdaptersTask: len[%d]", adaptersPropertiesArray.Length());
|
||||
|
||||
// Append a BluetoothAdapter into adapters array for each properties array
|
||||
uint32_t numAdapters = adaptersPropertiesArray.Length();
|
||||
for (uint32_t i = 0; i < numAdapters; i++) {
|
||||
MOZ_ASSERT(adaptersPropertiesArray[i].name().EqualsLiteral("Adapter"));
|
||||
|
||||
const BluetoothValue& properties = adaptersPropertiesArray[i].value();
|
||||
mManager->AppendAdapter(properties);
|
||||
}
|
||||
|
||||
aValue.setUndefined();
|
||||
|
||||
const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
|
||||
if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
|
||||
BT_WARNING("Not a BluetoothNamedValue array!");
|
||||
SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mManagerPtr->GetOwner()) {
|
||||
BT_WARNING("Bluetooth manager was disconnected from owner window.");
|
||||
|
||||
// Stop to create adapter since owner window of Bluetooth manager was
|
||||
// gone. These is no need to create a DOMEvent target which has no owner
|
||||
// to reply to.
|
||||
return false;
|
||||
}
|
||||
|
||||
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||
v.get_ArrayOfBluetoothNamedValue();
|
||||
nsRefPtr<BluetoothAdapter> adapter =
|
||||
BluetoothAdapter::Create(mManagerPtr->GetOwner(), values);
|
||||
|
||||
nsresult rv;
|
||||
nsIScriptContext* sc = mManagerPtr->GetContextForEventHandlers(&rv);
|
||||
if (!sc) {
|
||||
BT_WARNING("Cannot create script context!");
|
||||
SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
|
||||
JS::Rooted<JSObject*> scope(cx, sc->GetWindowProxy());
|
||||
JSAutoCompartment ac(cx, scope);
|
||||
rv = nsContentUtils::WrapNative(cx, adapter, aValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("Cannot create native object!");
|
||||
SetError(NS_LITERAL_STRING("BluetoothNativeObjectError"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -93,94 +80,88 @@ public:
|
|||
ReleaseMembers()
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
mManagerPtr = nullptr;
|
||||
mManager = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothManager> mManagerPtr;
|
||||
nsRefPtr<BluetoothManager> mManager;
|
||||
};
|
||||
|
||||
BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, BluetoothPropertyContainer(BluetoothObjectType::TYPE_MANAGER)
|
||||
, mDefaultAdapterIndex(-1)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(IsDOMBinding());
|
||||
|
||||
mPath.Assign('/');
|
||||
ListenToBluetoothSignal(true);
|
||||
BT_API2_LOGR("aWindow %p", aWindow);
|
||||
|
||||
// Query adapters list from bluetooth backend
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> result = new GetAdaptersTask(this);
|
||||
NS_ENSURE_SUCCESS_VOID(bs->GetAdaptersInternal(result));
|
||||
}
|
||||
|
||||
BluetoothManager::~BluetoothManager()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
ListenToBluetoothSignal(false);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::DisconnectFromOwner()
|
||||
{
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
ListenToBluetoothSignal(false);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
const nsString& name = aValue.name();
|
||||
nsCString warningMsg;
|
||||
warningMsg.AssignLiteral("Not handling manager property: ");
|
||||
warningMsg.Append(NS_ConvertUTF16toUTF8(name));
|
||||
BT_WARNING(warningMsg.get());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothManager::GetEnabled(ErrorResult& aRv)
|
||||
BluetoothManager::ListenToBluetoothSignal(bool aStart)
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (!bs) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return false;
|
||||
}
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
return bs->IsEnabled();
|
||||
if (aStart) {
|
||||
bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
} else {
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<dom::DOMRequest>
|
||||
BluetoothManager::GetDefaultAdapter(ErrorResult& aRv)
|
||||
BluetoothAdapter*
|
||||
BluetoothManager::GetDefaultAdapter()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
BT_API2_LOGR("mDefaultAdapterIndex: %d", mDefaultAdapterIndex);
|
||||
|
||||
return DefaultAdapterExists() ? mAdapters[mDefaultAdapterIndex] : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::AppendAdapter(const BluetoothValue& aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
|
||||
// Create a new BluetoothAdapter and append it to adapters array
|
||||
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||
aValue.get_ArrayOfBluetoothNamedValue();
|
||||
nsRefPtr<BluetoothAdapter> adapter =
|
||||
BluetoothAdapter::Create(GetOwner(), values);
|
||||
|
||||
mAdapters.AppendElement(adapter);
|
||||
|
||||
// Set this adapter as default adapter if no adapter exists
|
||||
if (!DefaultAdapterExists()) {
|
||||
MOZ_ASSERT(mAdapters.Length() == 1);
|
||||
ReselectDefaultAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<DOMRequest> request = new DOMRequest(win);
|
||||
nsRefPtr<BluetoothReplyRunnable> results =
|
||||
new GetAdapterTask(this, request);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (!bs) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult rv = bs->GetDefaultAdapterPathInternal(results);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return request.forget();
|
||||
void
|
||||
BluetoothManager::GetAdapters(nsTArray<nsRefPtr<BluetoothAdapter> >& aAdapters)
|
||||
{
|
||||
aAdapters = mAdapters;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -195,36 +176,122 @@ BluetoothManager::Create(nsPIDOMWindow* aWindow)
|
|||
}
|
||||
|
||||
void
|
||||
BluetoothManager::Notify(const BluetoothSignal& aData)
|
||||
BluetoothManager::HandleAdapterAdded(const BluetoothValue& aValue)
|
||||
{
|
||||
BT_LOGD("[M] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
BT_API2_LOGR();
|
||||
|
||||
if (aData.name().EqualsLiteral("AdapterAdded")) {
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("adapteradded"));
|
||||
} else if (aData.name().EqualsLiteral("Enabled")) {
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("enabled"));
|
||||
} else if (aData.name().EqualsLiteral("Disabled")) {
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("disabled"));
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
nsCString warningMsg;
|
||||
warningMsg.AssignLiteral("Not handling manager signal: ");
|
||||
warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
|
||||
BT_WARNING(warningMsg.get());
|
||||
#endif
|
||||
}
|
||||
AppendAdapter(aValue);
|
||||
|
||||
// Notify application of added adapter
|
||||
BluetoothAdapterEventInit init;
|
||||
init.mAdapter = mAdapters.LastElement();
|
||||
DispatchAdapterEvent(NS_LITERAL_STRING("adapteradded"), init);
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothManager::IsConnected(uint16_t aProfileId, ErrorResult& aRv)
|
||||
void
|
||||
BluetoothManager::HandleAdapterRemoved(const BluetoothValue& aValue)
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (!bs) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return false;
|
||||
MOZ_ASSERT(aValue.type() == BluetoothValue::TnsString);
|
||||
MOZ_ASSERT(DefaultAdapterExists());
|
||||
|
||||
// Remove the adapter of given address from adapters array
|
||||
nsString addressToRemove = aValue.get_nsString();
|
||||
|
||||
uint32_t numAdapters = mAdapters.Length();
|
||||
for (uint32_t i = 0; i < numAdapters; i++) {
|
||||
nsString address;
|
||||
mAdapters[i]->GetAddress(address);
|
||||
if (address.Equals(addressToRemove)) {
|
||||
mAdapters.RemoveElementAt(i);
|
||||
|
||||
if (mDefaultAdapterIndex == (int)i) {
|
||||
ReselectDefaultAdapter();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bs->IsConnected(aProfileId);
|
||||
// Notify application of removed adapter
|
||||
BluetoothAdapterEventInit init;
|
||||
init.mAddress = addressToRemove;
|
||||
DispatchAdapterEvent(NS_LITERAL_STRING("adapterremoved"), init);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::ReselectDefaultAdapter()
|
||||
{
|
||||
// Select the first of existing/remaining adapters as default adapter
|
||||
mDefaultAdapterIndex = mAdapters.IsEmpty() ? -1 : 0;
|
||||
BT_API2_LOGR("mAdapters length: %d => NEW mDefaultAdapterIndex: %d",
|
||||
mAdapters.Length(), mDefaultAdapterIndex);
|
||||
|
||||
// Notify application of default adapter change
|
||||
DispatchAttributeEvent();
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::DispatchAdapterEvent(const nsAString& aType,
|
||||
const BluetoothAdapterEventInit& aInit)
|
||||
{
|
||||
BT_API2_LOGR("aType (%s)", NS_ConvertUTF16toUTF8(aType).get());
|
||||
|
||||
nsRefPtr<BluetoothAdapterEvent> event =
|
||||
BluetoothAdapterEvent::Constructor(this, aType, aInit);
|
||||
DispatchTrustedEvent(event);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::DispatchAttributeEvent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
BT_API2_LOGR();
|
||||
|
||||
// Wrap default adapter
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> value(cx, JS::NullValue());
|
||||
if (DefaultAdapterExists()) {
|
||||
BluetoothAdapter* adapter = mAdapters[mDefaultAdapterIndex];
|
||||
nsCOMPtr<nsIGlobalObject> global =
|
||||
do_QueryInterface(adapter->GetParentObject());
|
||||
NS_ENSURE_TRUE_VOID(global);
|
||||
|
||||
JS::Rooted<JSObject*> scope(cx, global->GetGlobalJSObject());
|
||||
NS_ENSURE_TRUE_VOID(scope);
|
||||
|
||||
JSAutoCompartment ac(cx, scope);
|
||||
if (!ToJSValue(cx, adapter, &value)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_API2_LOGR("Default adapter is wrapped");
|
||||
}
|
||||
|
||||
// Notify application of default adapter change
|
||||
RootedDictionary<BluetoothAttributeEventInit> init(cx);
|
||||
init.mAttr = (uint16_t)BluetoothManagerAttribute::DefaultAdapter;
|
||||
init.mValue = value;
|
||||
nsRefPtr<BluetoothAttributeEvent> event =
|
||||
BluetoothAttributeEvent::Constructor(this,
|
||||
NS_LITERAL_STRING("attributechanged"),
|
||||
init);
|
||||
DispatchTrustedEvent(event);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[M] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
|
||||
if (aData.name().EqualsLiteral("AdapterAdded")) {
|
||||
HandleAdapterAdded(aData.value());
|
||||
} else if (aData.name().EqualsLiteral("AdapterRemoved")) {
|
||||
HandleAdapterRemoved(aData.value());
|
||||
} else {
|
||||
BT_WARNING("Not handling manager signal: %s",
|
||||
NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
|
|
@ -7,59 +7,130 @@
|
|||
#ifndef mozilla_dom_bluetooth_bluetoothmanager_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothmanager_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BluetoothAdapterEvent.h"
|
||||
#include "mozilla/dom/BluetoothAttributeEvent.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/Observer.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothPropertyContainer.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class DOMRequest;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothNamedValue;
|
||||
class BluetoothAdapter;
|
||||
class BluetoothValue;
|
||||
|
||||
class BluetoothManager : public DOMEventTargetHelper
|
||||
, public BluetoothSignalObserver
|
||||
, public BluetoothPropertyContainer
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// Never returns null
|
||||
static already_AddRefed<BluetoothManager>
|
||||
Create(nsPIDOMWindow* aWindow);
|
||||
static already_AddRefed<BluetoothManager> Create(nsPIDOMWindow* aWindow);
|
||||
static bool CheckPermission(nsPIDOMWindow* aWindow);
|
||||
void Notify(const BluetoothSignal& aData);
|
||||
virtual void SetPropertyByValue(const BluetoothNamedValue& aValue) MOZ_OVERRIDE;
|
||||
|
||||
bool GetEnabled(ErrorResult& aRv);
|
||||
bool IsConnected(uint16_t aProfileId, ErrorResult& aRv);
|
||||
/**
|
||||
* Return default adapter if it exists, nullptr otherwise. The function is
|
||||
* called when applications access property BluetoothManager.defaultAdapter
|
||||
*/
|
||||
BluetoothAdapter* GetDefaultAdapter();
|
||||
|
||||
already_AddRefed<DOMRequest> GetDefaultAdapter(ErrorResult& aRv);
|
||||
/**
|
||||
* Return adapters array. The function is called when applications call
|
||||
* method BluetoothManager.getAdapters()
|
||||
*
|
||||
* @param aAdapters [out] Adapters array to return
|
||||
*/
|
||||
void GetAdapters(nsTArray<nsRefPtr<BluetoothAdapter> >& aAdapters);
|
||||
|
||||
IMPL_EVENT_HANDLER(enabled);
|
||||
IMPL_EVENT_HANDLER(disabled);
|
||||
/**
|
||||
* Create a BluetoothAdapter object based on properties array
|
||||
* and append it into adapters array.
|
||||
*
|
||||
* @param aValue [in] Properties array to create BluetoothAdapter object
|
||||
*/
|
||||
void AppendAdapter(const BluetoothValue& aValue);
|
||||
|
||||
IMPL_EVENT_HANDLER(attributechanged);
|
||||
IMPL_EVENT_HANDLER(adapteradded);
|
||||
IMPL_EVENT_HANDLER(adapterremoved);
|
||||
|
||||
void Notify(const BluetoothSignal& aData); // BluetoothSignalObserver
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
virtual void DisconnectFromOwner() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
BluetoothManager(nsPIDOMWindow* aWindow);
|
||||
~BluetoothManager();
|
||||
|
||||
/**
|
||||
* Start/Stop listening to bluetooth signal.
|
||||
*
|
||||
* @param aStart [in] Whether to start or stop listening to bluetooth signal
|
||||
*/
|
||||
void ListenToBluetoothSignal(bool aStart);
|
||||
|
||||
/**
|
||||
* Check whether default adapter exists.
|
||||
*/
|
||||
bool DefaultAdapterExists()
|
||||
{
|
||||
return (mDefaultAdapterIndex >= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle "AdapterAdded" bluetooth signal.
|
||||
*
|
||||
* @param aValue [in] Properties array of the added adapter
|
||||
*/
|
||||
void HandleAdapterAdded(const BluetoothValue& aValue);
|
||||
|
||||
/**
|
||||
* Handle "AdapterRemoved" bluetooth signal.
|
||||
*
|
||||
* @param aValue [in] Address of the removed adapter
|
||||
*/
|
||||
void HandleAdapterRemoved(const BluetoothValue& aValue);
|
||||
|
||||
/**
|
||||
* Re-select default adapter from adapters array. The function is called
|
||||
* when an adapter is added/removed.
|
||||
*/
|
||||
void ReselectDefaultAdapter();
|
||||
|
||||
/**
|
||||
* Fire BluetoothAdapterEvent to trigger
|
||||
* onadapteradded/onadapterremoved event handler.
|
||||
*
|
||||
* @param aType [in] Event type to fire
|
||||
* @param aInit [in] Event initialization value
|
||||
*/
|
||||
void DispatchAdapterEvent(const nsAString& aType,
|
||||
const BluetoothAdapterEventInit& aInit);
|
||||
|
||||
/**
|
||||
* Fire BluetoothAttributeEvent to trigger onattributechanged event handler.
|
||||
*/
|
||||
void DispatchAttributeEvent();
|
||||
|
||||
/****************************************************************************
|
||||
* Variables
|
||||
***************************************************************************/
|
||||
/**
|
||||
* The index of default adapter in the adapters array.
|
||||
*/
|
||||
int mDefaultAdapterIndex;
|
||||
|
||||
/**
|
||||
* The adapters array.
|
||||
*/
|
||||
nsTArray<nsRefPtr<BluetoothAdapter> > mAdapters;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
|
|
@ -34,6 +34,8 @@ BluetoothReplyRunnable::~BluetoothReplyRunnable()
|
|||
nsresult
|
||||
BluetoothReplyRunnable::FireReply(JS::Handle<JS::Value> aVal)
|
||||
{
|
||||
NS_ENSURE_TRUE(mDOMRequest, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIDOMRequestService> rs =
|
||||
do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
|
||||
|
@ -46,6 +48,8 @@ BluetoothReplyRunnable::FireReply(JS::Handle<JS::Value> aVal)
|
|||
nsresult
|
||||
BluetoothReplyRunnable::FireErrorString()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDOMRequest, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIDOMRequestService> rs =
|
||||
do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
|
||||
|
@ -57,7 +61,6 @@ NS_IMETHODIMP
|
|||
BluetoothReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mDOMRequest);
|
||||
MOZ_ASSERT(mReply);
|
||||
|
||||
nsresult rv;
|
||||
|
|
|
@ -48,6 +48,10 @@ private:
|
|||
nsresult FireReply(JS::Handle<JS::Value> aVal);
|
||||
nsresult FireErrorString();
|
||||
|
||||
/**
|
||||
* mDOMRequest is nullptr for internal IPC that require no DOMRequest,
|
||||
* e.g., GetAdaptersTask triggered by BluetoothManager
|
||||
*/
|
||||
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
|
||||
nsString mErrorString;
|
||||
};
|
||||
|
|
|
@ -375,11 +375,8 @@ BluetoothService::DistributeSignal(const BluetoothSignal& aSignal)
|
|||
|
||||
BluetoothSignalObserverList* ol;
|
||||
if (!mBluetoothSignalObserverTable.Get(aSignal.path(), &ol)) {
|
||||
#if DEBUG
|
||||
nsAutoCString msg("No observer registered for path ");
|
||||
msg.Append(NS_ConvertUTF16toUTF8(aSignal.path()));
|
||||
BT_WARNING(msg.get());
|
||||
#endif
|
||||
BT_WARNING("No observer registered for path %s",
|
||||
NS_ConvertUTF16toUTF8(aSignal.path()).get());
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(ol->Length());
|
||||
|
|
|
@ -123,13 +123,13 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the path of the default adapter, implemented via a platform
|
||||
* Returns an array of each adapter's properties, implemented via a platform
|
||||
* specific method.
|
||||
*
|
||||
* @return NS_OK on success, NS_ERROR_FAILURE otherwise
|
||||
*/
|
||||
virtual nsresult
|
||||
GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0;
|
||||
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Returns the properties of paired devices, implemented via a platform
|
||||
|
|
|
@ -808,30 +808,45 @@ BluetoothServiceBluedroid::StopInternal()
|
|||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceBluedroid::GetDefaultAdapterPathInternal(
|
||||
BluetoothServiceBluedroid::GetAdaptersInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BluetoothValue v = InfallibleTArray<BluetoothNamedValue>();
|
||||
/**
|
||||
* Wrap BluetoothValue =
|
||||
* BluetoothNamedValue[]
|
||||
* |
|
||||
* |__ BluetoothNamedValue =
|
||||
* | {"Adapter", BluetoothValue = BluetoothNamedValue[]}
|
||||
* |
|
||||
* |__ BluetoothNamedValue =
|
||||
* | {"Adapter", BluetoothValue = BluetoothNamedValue[]}
|
||||
* ...
|
||||
*/
|
||||
BluetoothValue adaptersProperties = InfallibleTArray<BluetoothNamedValue>();
|
||||
uint32_t numAdapters = 1; // Bluedroid supports single adapter only
|
||||
|
||||
BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
|
||||
"Address", sAdapterBdAddress);
|
||||
for (uint32_t i = 0; i < numAdapters; i++) {
|
||||
BluetoothValue properties = InfallibleTArray<BluetoothNamedValue>();
|
||||
|
||||
BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
|
||||
"Name", sAdapterBdName);
|
||||
// TODO: Revise here based on new BluetoothAdapter interface
|
||||
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
|
||||
"Address", sAdapterBdAddress);
|
||||
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
|
||||
"Name", sAdapterBdName);
|
||||
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
|
||||
"Discoverable", sAdapterDiscoverable);
|
||||
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
|
||||
"DiscoverableTimeout", sAdapterDiscoverableTimeout);
|
||||
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
|
||||
"Devices", sAdapterBondedAddressArray);
|
||||
|
||||
BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
|
||||
"Discoverable", sAdapterDiscoverable);
|
||||
|
||||
BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
|
||||
"DiscoverableTimeout", sAdapterDiscoverableTimeout);
|
||||
|
||||
BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
|
||||
"Devices", sAdapterBondedAddressArray);
|
||||
|
||||
DispatchBluetoothReply(aRunnable, v, EmptyString());
|
||||
BT_APPEND_NAMED_VALUE(adaptersProperties.get_ArrayOfBluetoothNamedValue(),
|
||||
"Adapter", properties);
|
||||
}
|
||||
|
||||
DispatchBluetoothReply(aRunnable, adaptersProperties, EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,15 +25,16 @@ public:
|
|||
virtual nsresult StartInternal();
|
||||
virtual nsresult StopInternal();
|
||||
|
||||
virtual nsresult GetDefaultAdapterPathInternal(
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
virtual nsresult
|
||||
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual nsresult GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
virtual nsresult
|
||||
GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual nsresult GetPairedDevicePropertiesInternal(
|
||||
const nsTArray<nsString>& aDeviceAddress,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
virtual nsresult
|
||||
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddress,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
|
||||
virtual nsresult StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
|
||||
|
|
|
@ -2376,11 +2376,14 @@ private:
|
|||
};
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::GetDefaultAdapterPathInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
BluetoothDBusService::GetAdaptersInternal(BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
/**
|
||||
* TODO: implement method GetAdaptersInternal for bluez
|
||||
*/
|
||||
|
||||
if (!IsReady()) {
|
||||
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
|
||||
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
|
||||
|
|
|
@ -51,15 +51,16 @@ public:
|
|||
|
||||
virtual nsresult StopInternal() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult GetDefaultAdapterPathInternal(
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
virtual nsresult
|
||||
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult GetConnectedDevicePropertiesInternal(uint16_t aServiceUuid,
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
virtual nsresult
|
||||
GetConnectedDevicePropertiesInternal(uint16_t aServiceUuid,
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult GetPairedDevicePropertiesInternal(
|
||||
const nsTArray<nsString>& aDeviceAddresses,
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
virtual nsresult
|
||||
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -183,8 +183,8 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
|
|||
#endif
|
||||
|
||||
switch (aRequest.type()) {
|
||||
case Request::TDefaultAdapterPathRequest:
|
||||
return actor->DoRequest(aRequest.get_DefaultAdapterPathRequest());
|
||||
case Request::TGetAdaptersRequest:
|
||||
return actor->DoRequest(aRequest.get_GetAdaptersRequest());
|
||||
case Request::TSetPropertyRequest:
|
||||
return actor->DoRequest(aRequest.get_SetPropertyRequest());
|
||||
case Request::TStartDiscoveryRequest:
|
||||
|
@ -303,12 +303,12 @@ BluetoothRequestParent::RequestComplete()
|
|||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const DefaultAdapterPathRequest& aRequest)
|
||||
BluetoothRequestParent::DoRequest(const GetAdaptersRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType == Request::TDefaultAdapterPathRequest);
|
||||
MOZ_ASSERT(mRequestType == Request::TGetAdaptersRequest);
|
||||
|
||||
nsresult rv = mService->GetDefaultAdapterPathInternal(mReplyRunnable.get());
|
||||
nsresult rv = mService->GetAdaptersInternal(mReplyRunnable.get());
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -126,7 +126,7 @@ protected:
|
|||
RequestComplete();
|
||||
|
||||
bool
|
||||
DoRequest(const DefaultAdapterPathRequest& aRequest);
|
||||
DoRequest(const GetAdaptersRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const SetPropertyRequest& aRequest);
|
||||
|
|
|
@ -96,10 +96,10 @@ BluetoothServiceChildProcess::UnregisterBluetoothSignalHandler(
|
|||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::GetDefaultAdapterPathInternal(
|
||||
BluetoothServiceChildProcess::GetAdaptersInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable, DefaultAdapterPathRequest());
|
||||
SendRequest(aRunnable, GetAdaptersRequest());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace bluetooth {
|
|||
* Bluetooth request types.
|
||||
*/
|
||||
|
||||
struct DefaultAdapterPathRequest
|
||||
struct GetAdaptersRequest
|
||||
{ };
|
||||
|
||||
struct SetPropertyRequest
|
||||
|
@ -165,7 +165,7 @@ struct SendPlayStatusRequest
|
|||
|
||||
union Request
|
||||
{
|
||||
DefaultAdapterPathRequest;
|
||||
GetAdaptersRequest;
|
||||
SetPropertyRequest;
|
||||
GetPropertyRequest;
|
||||
StartDiscoveryRequest;
|
||||
|
|
|
@ -485,11 +485,11 @@ MmsMessage::GetSender(nsAString& aSender)
|
|||
NS_IMETHODIMP
|
||||
MmsMessage::GetReceivers(JSContext* aCx, JS::MutableHandle<JS::Value> aReceivers)
|
||||
{
|
||||
JS::Rooted<JSObject*> reveiversObj(aCx);
|
||||
nsresult rv = nsTArrayToJSArray(aCx, mReceivers, reveiversObj.address());
|
||||
JS::Rooted<JSObject*> receiversObj(aCx);
|
||||
nsresult rv = nsTArrayToJSArray(aCx, mReceivers, &receiversObj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aReceivers.setObject(*reveiversObj);
|
||||
aReceivers.setObject(*receiversObj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ MobileMessageThread::GetParticipants(JSContext* aCx,
|
|||
{
|
||||
JS::Rooted<JSObject*> obj(aCx);
|
||||
|
||||
nsresult rv = nsTArrayToJSArray(aCx, mData.participants(), obj.address());
|
||||
nsresult rv = nsTArrayToJSArray(aCx, mData.participants(), &obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aParticipants.setObject(*obj);
|
||||
|
|
|
@ -97,9 +97,8 @@ GetParamsFromSendMmsMessageRequest(JSContext* aCx,
|
|||
|
||||
// receivers
|
||||
JS::Rooted<JSObject*> receiverArray(aCx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(aCx,
|
||||
aRequest.receivers(),
|
||||
receiverArray.address()))) {
|
||||
if (NS_FAILED(nsTArrayToJSArray(aCx, aRequest.receivers(), &receiverArray)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!JS_DefineProperty(aCx, paramsObj, "receivers", receiverArray, 0)) {
|
||||
|
|
|
@ -3,16 +3,20 @@
|
|||
* 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/. */
|
||||
|
||||
interface BluetoothManager : EventTarget {
|
||||
[Throws]
|
||||
readonly attribute boolean enabled;
|
||||
[CheckPermissions="bluetooth"]
|
||||
interface BluetoothManager: EventTarget
|
||||
{
|
||||
readonly attribute BluetoothAdapter? defaultAdapter;
|
||||
|
||||
attribute EventHandler onenabled;
|
||||
attribute EventHandler ondisabled;
|
||||
attribute EventHandler onattributechanged;
|
||||
attribute EventHandler onadapteradded;
|
||||
attribute EventHandler onadapterremoved;
|
||||
|
||||
[Throws]
|
||||
boolean isConnected(unsigned short aProfile);
|
||||
[NewObject, Throws]
|
||||
DOMRequest? getDefaultAdapter();
|
||||
sequence<BluetoothAdapter> getAdapters();
|
||||
};
|
||||
|
||||
enum BluetoothManagerAttribute
|
||||
{
|
||||
"unknown",
|
||||
"defaultAdapter"
|
||||
};
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"expect-hazards": 2
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
template <class T>
|
||||
inline nsresult
|
||||
nsTArrayToJSArray(JSContext* aCx, const nsTArray<T>& aSourceArray,
|
||||
JSObject** aResultArray)
|
||||
JS::MutableHandle<JSObject*> aResultArray)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
|
||||
|
@ -45,7 +45,7 @@ nsTArrayToJSArray(JSContext* aCx, const nsTArray<T>& aSourceArray,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResultArray = arrayObj;
|
||||
aResultArray.set(arrayObj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ template <>
|
|||
inline nsresult
|
||||
nsTArrayToJSArray<nsString>(JSContext* aCx,
|
||||
const nsTArray<nsString>& aSourceArray,
|
||||
JSObject** aResultArray)
|
||||
JS::MutableHandle<JSObject*> aResultArray)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
|
||||
|
@ -85,7 +85,7 @@ nsTArrayToJSArray<nsString>(JSContext* aCx,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResultArray = arrayObj;
|
||||
aResultArray.set(arrayObj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,6 @@ public class GeckoEvent {
|
|||
SENSOR_EVENT(3),
|
||||
LOCATION_EVENT(5),
|
||||
IME_EVENT(6),
|
||||
DRAW(7),
|
||||
SIZE_CHANGED(8),
|
||||
APP_BACKGROUNDING(9),
|
||||
APP_FOREGROUNDING(10),
|
||||
|
@ -659,12 +658,6 @@ public class GeckoEvent {
|
|||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createDrawEvent(Rect rect) {
|
||||
GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.DRAW);
|
||||
event.mRect = rect;
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createSizeChangedEvent(int w, int h, int screenw, int screenh) {
|
||||
GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.SIZE_CHANGED);
|
||||
event.mPoints = new Point[2];
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
android:layout_marginTop="16dp"
|
||||
android:layout_alignLeft="@id/tabs"/>
|
||||
|
||||
<!-- In editing mode, the toolbar shrinks by changing to
|
||||
dynamically constructed LayoutParams. -->
|
||||
<ImageView android:id="@+id/url_bar_entry"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
|
@ -63,7 +65,7 @@
|
|||
<org.mozilla.gecko.toolbar.ToolbarEditLayout android:id="@+id/edit_layout"
|
||||
style="@style/UrlBar.Button"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="4dp"
|
||||
android:paddingRight="12dp"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal"
|
||||
android:layout_toRightOf="@id/back"
|
||||
|
@ -105,4 +107,15 @@
|
|||
android:background="@color/url_bar_shadow"
|
||||
android:contentDescription="@null"/>
|
||||
|
||||
<!-- We draw after the menu items so when they are hidden, the cancel button,
|
||||
which is thus drawn on top, may be pressed. -->
|
||||
<ImageView android:id="@+id/edit_cancel"
|
||||
style="@style/UrlBar.ImageButton.Icon"
|
||||
android:layout_alignParentRight="true"
|
||||
android:src="@drawable/close_edit_mode"
|
||||
android:paddingLeft="2dp"
|
||||
android:paddingRight="2dp"
|
||||
android:contentDescription="@string/edit_mode_cancel"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</merge>
|
||||
|
|
|
@ -143,12 +143,17 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
|
||||
private final ImageView editCancel;
|
||||
|
||||
private final View[] tabletDisplayModeViews;
|
||||
private boolean hidForwardButtonOnStartEditing = false;
|
||||
|
||||
private boolean shouldShrinkURLBar = false;
|
||||
|
||||
private OnActivateListener activateListener;
|
||||
private OnFocusChangeListener focusChangeListener;
|
||||
private OnStartEditingListener startEditingListener;
|
||||
private OnStopEditingListener stopEditingListener;
|
||||
private final PropertyAnimator.PropertyAnimationListener showEditingPhoneAnimationListener;
|
||||
private final PropertyAnimator.PropertyAnimationListener stopEditingPhoneAnimationListener;
|
||||
|
||||
private final BrowserApp activity;
|
||||
private boolean hasSoftMenuButton;
|
||||
|
@ -199,8 +204,13 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
// to ViewGroup.MarginLayoutParams to ensure consistency across platforms.
|
||||
urlBarEntryShrunkenLayoutParams = new RelativeLayout.LayoutParams(
|
||||
(ViewGroup.MarginLayoutParams) urlBarEntryDefaultLayoutParams);
|
||||
urlBarEntryShrunkenLayoutParams.addRule(RelativeLayout.ALIGN_RIGHT, R.id.edit_layout);
|
||||
urlBarEntryShrunkenLayoutParams.rightMargin = 0;
|
||||
// Note: a shrunken phone layout is not displayed on any known devices,
|
||||
// and thus shrunken layout params for phone are not maintained.
|
||||
if (HardwareUtils.isTablet()) {
|
||||
urlBarEntryShrunkenLayoutParams.addRule(RelativeLayout.ALIGN_RIGHT, R.id.edit_layout);
|
||||
urlBarEntryShrunkenLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.edit_layout);
|
||||
urlBarEntryShrunkenLayoutParams.leftMargin = 0;
|
||||
}
|
||||
|
||||
// This will clip the translating edge's image at 60% of its width
|
||||
urlBarTranslatingEdge = (ImageView) findViewById(R.id.url_bar_translating_edge);
|
||||
|
@ -240,6 +250,50 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
}
|
||||
|
||||
setUIMode(UIMode.DISPLAY);
|
||||
|
||||
// Create these listeners here, once, to avoid constructing new listeners
|
||||
// each time they are set on an animator (i.e. each time the url bar is clicked).
|
||||
showEditingPhoneAnimationListener = new PropertyAnimator.PropertyAnimationListener() {
|
||||
@Override
|
||||
public void onPropertyAnimationStart() { /* Do nothing */ }
|
||||
|
||||
@Override
|
||||
public void onPropertyAnimationEnd() {
|
||||
isAnimatingEntry = false;
|
||||
}
|
||||
};
|
||||
|
||||
stopEditingPhoneAnimationListener = new PropertyAnimator.PropertyAnimationListener() {
|
||||
@Override
|
||||
public void onPropertyAnimationStart() { /* Do nothing */ }
|
||||
|
||||
@Override
|
||||
public void onPropertyAnimationEnd() {
|
||||
urlBarTranslatingEdge.setVisibility(View.INVISIBLE);
|
||||
if (shouldShrinkURLBar) {
|
||||
urlBarEntry.setLayoutParams(urlBarEntryDefaultLayoutParams);
|
||||
}
|
||||
|
||||
PropertyAnimator buttonsAnimator = new PropertyAnimator(300);
|
||||
urlDisplayLayout.prepareStopEditingAnimation(buttonsAnimator);
|
||||
buttonsAnimator.start();
|
||||
|
||||
isAnimatingEntry = false;
|
||||
|
||||
// Trigger animation to update the tabs counter once the
|
||||
// tabs button is back on screen.
|
||||
updateTabCountAndAnimate(Tabs.getInstance().getDisplayCount());
|
||||
}
|
||||
};
|
||||
|
||||
tabletDisplayModeViews = new View[] {
|
||||
actionItemBar,
|
||||
backButton,
|
||||
menuButton,
|
||||
menuIcon,
|
||||
tabsButton,
|
||||
tabsCounter,
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -373,21 +427,19 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
}
|
||||
});
|
||||
|
||||
if (editCancel != null) {
|
||||
editCancel.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// If we exit editing mode during the animation,
|
||||
// we're put into an inconsistent state (bug 1017276).
|
||||
if (!isAnimatingEntry) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL,
|
||||
TelemetryContract.Method.ACTIONBAR,
|
||||
getResources().getResourceEntryName(editCancel.getId()));
|
||||
cancelEdit();
|
||||
}
|
||||
editCancel.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// If we exit editing mode during the animation,
|
||||
// we're put into an inconsistent state (bug 1017276).
|
||||
if (!isAnimatingEntry) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL,
|
||||
TelemetryContract.Method.ACTIONBAR,
|
||||
getResources().getResourceEntryName(editCancel.getId()));
|
||||
cancelEdit();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (hasSoftMenuButton) {
|
||||
menuButton.setVisibility(View.VISIBLE);
|
||||
|
@ -583,12 +635,12 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
menuButton.setNextFocusDownId(nextId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of pixels the url bar translating edge
|
||||
* needs to translate to the right to enter its editing mode state.
|
||||
* A negative value means the edge must translate to the left.
|
||||
*/
|
||||
private int getUrlBarEntryTranslation() {
|
||||
if (editCancel == null) {
|
||||
// We are on tablet, and there is no animation so return a translation of 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find the distance from the right-edge of the url bar (where we're translating from) to
|
||||
// the left-edge of the cancel button (where we're translating to; note that the cancel
|
||||
// button must be laid out, i.e. not View.GONE).
|
||||
|
@ -874,42 +926,28 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
}
|
||||
|
||||
private void setCancelVisibility(final int visibility) {
|
||||
if (editCancel != null) {
|
||||
editCancel.setVisibility(visibility);
|
||||
}
|
||||
editCancel.setVisibility(visibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables and dims all toolbar elements which are not
|
||||
* Disables all toolbar elements which are not
|
||||
* related to editing mode.
|
||||
*/
|
||||
private void updateChildrenForEditing() {
|
||||
// This is for the tablet UI only
|
||||
if (!HardwareUtils.isTablet()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable toolbar elemens while in editing mode
|
||||
private void updateChildrenEnabledStateForEditing() {
|
||||
// Disable toolbar elements while in editing mode
|
||||
final boolean enabled = !isEditing();
|
||||
|
||||
// This alpha value has to be in sync with the one used
|
||||
// in setButtonEnabled().
|
||||
final float alpha = (enabled ? 1.0f : 0.24f);
|
||||
|
||||
if (!enabled) {
|
||||
tabsCounter.onEnterEditingMode();
|
||||
}
|
||||
|
||||
tabsButton.setEnabled(enabled);
|
||||
ViewHelper.setAlpha(tabsCounter, alpha);
|
||||
menuButton.setEnabled(enabled);
|
||||
ViewHelper.setAlpha(menuIcon, alpha);
|
||||
|
||||
final int actionItemsCount = actionItemBar.getChildCount();
|
||||
for (int i = 0; i < actionItemsCount; i++) {
|
||||
actionItemBar.getChildAt(i).setEnabled(enabled);
|
||||
}
|
||||
ViewHelper.setAlpha(actionItemBar, alpha);
|
||||
|
||||
final Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
if (tab != null) {
|
||||
|
@ -952,7 +990,6 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
urlEditLayout.setText(url != null ? url : "");
|
||||
|
||||
setUIMode(UIMode.EDIT);
|
||||
updateChildrenForEditing();
|
||||
|
||||
updateProgressVisibility();
|
||||
|
||||
|
@ -960,38 +997,34 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
startEditingListener.onStartEditing();
|
||||
}
|
||||
|
||||
final int curveTranslation = getUrlBarCurveTranslation();
|
||||
final int entryTranslation = getUrlBarEntryTranslation();
|
||||
shouldShrinkURLBar = (entryTranslation < 0);
|
||||
|
||||
if (urlBarTranslatingEdge != null) {
|
||||
if (HardwareUtils.isTablet()) {
|
||||
showEditingOnTablet();
|
||||
} else {
|
||||
urlBarTranslatingEdge.setVisibility(View.VISIBLE);
|
||||
|
||||
final int curveTranslation = getUrlBarCurveTranslation();
|
||||
final int entryTranslation = getUrlBarEntryTranslation();
|
||||
shouldShrinkURLBar = (entryTranslation < 0);
|
||||
if (shouldShrinkURLBar) {
|
||||
urlBarEntry.setLayoutParams(urlBarEntryShrunkenLayoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < 11) {
|
||||
showEditingWithoutAnimation(entryTranslation, curveTranslation);
|
||||
} else if (HardwareUtils.isTablet()) {
|
||||
// No animation.
|
||||
showUrlEditLayout();
|
||||
} else {
|
||||
showEditingWithPhoneAnimation(animator, entryTranslation, curveTranslation);
|
||||
if (Build.VERSION.SDK_INT < 11) {
|
||||
showEditingOnPreHoneycomb(entryTranslation, curveTranslation);
|
||||
} else {
|
||||
showEditingWithPhoneAnimation(animator, entryTranslation, curveTranslation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showEditingWithoutAnimation(final int entryTranslation,
|
||||
private void showEditingOnPreHoneycomb(final int entryTranslation,
|
||||
final int curveTranslation) {
|
||||
showUrlEditLayout();
|
||||
|
||||
if (urlBarTranslatingEdge != null) {
|
||||
ViewHelper.setTranslationX(urlBarTranslatingEdge, entryTranslation);
|
||||
}
|
||||
|
||||
// Prevent taps through the editing mode cancel button (bug 1001243).
|
||||
tabsButton.setEnabled(false);
|
||||
|
||||
ViewHelper.setTranslationX(urlBarTranslatingEdge, entryTranslation);
|
||||
ViewHelper.setTranslationX(tabsButton, curveTranslation);
|
||||
ViewHelper.setTranslationX(tabsCounter, curveTranslation);
|
||||
ViewHelper.setTranslationX(actionItemBar, curveTranslation);
|
||||
|
@ -1005,6 +1038,27 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
}
|
||||
}
|
||||
|
||||
private void showEditingOnTablet() {
|
||||
urlBarEntry.setLayoutParams(urlBarEntryShrunkenLayoutParams);
|
||||
|
||||
// Hide display elements.
|
||||
updateChildrenEnabledStateForEditing();
|
||||
for (final View v : tabletDisplayModeViews) {
|
||||
v.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
final Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
||||
if (selectedTab != null && selectedTab.canDoForward()) {
|
||||
hidForwardButtonOnStartEditing = true;
|
||||
forwardButton.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
hidForwardButtonOnStartEditing = false;
|
||||
}
|
||||
|
||||
// Show editing elements.
|
||||
showUrlEditLayout();
|
||||
}
|
||||
|
||||
private void showEditingWithPhoneAnimation(final PropertyAnimator animator,
|
||||
final int entryTranslation, final int curveTranslation) {
|
||||
if (isAnimatingEntry)
|
||||
|
@ -1013,12 +1067,9 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
urlDisplayLayout.prepareStartEditingAnimation();
|
||||
|
||||
// Slide toolbar elements.
|
||||
if (urlBarTranslatingEdge != null) {
|
||||
animator.attach(urlBarTranslatingEdge,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
entryTranslation);
|
||||
}
|
||||
|
||||
animator.attach(urlBarTranslatingEdge,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
entryTranslation);
|
||||
animator.attach(tabsButton,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
curveTranslation);
|
||||
|
@ -1041,18 +1092,8 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
|
||||
showUrlEditLayout(animator);
|
||||
|
||||
animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() {
|
||||
@Override
|
||||
public void onPropertyAnimationStart() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPropertyAnimationEnd() {
|
||||
isAnimatingEntry = false;
|
||||
}
|
||||
});
|
||||
|
||||
isAnimatingEntry = true;
|
||||
animator.addPropertyAnimationListener(showEditingPhoneAnimationListener);
|
||||
isAnimatingEntry = true; // To be correct, this should be called last.
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1085,7 +1126,7 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
}
|
||||
setUIMode(UIMode.DISPLAY);
|
||||
|
||||
updateChildrenForEditing();
|
||||
updateChildrenEnabledStateForEditing();
|
||||
|
||||
if (stopEditingListener != null) {
|
||||
stopEditingListener.onStopEditing();
|
||||
|
@ -1098,10 +1139,9 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
urlEditLayout.clearFocus();
|
||||
|
||||
if (Build.VERSION.SDK_INT < 11) {
|
||||
stopEditingWithoutAnimation();
|
||||
stopEditingOnPreHoneycomb();
|
||||
} else if (HardwareUtils.isTablet()) {
|
||||
// No animation.
|
||||
hideUrlEditLayout();
|
||||
stopEditingOnTablet();
|
||||
} else {
|
||||
stopEditingWithPhoneAnimation();
|
||||
}
|
||||
|
@ -1109,21 +1149,19 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
return url;
|
||||
}
|
||||
|
||||
private void stopEditingWithoutAnimation() {
|
||||
private void stopEditingOnPreHoneycomb() {
|
||||
hideUrlEditLayout();
|
||||
|
||||
updateTabCountAndAnimate(Tabs.getInstance().getDisplayCount());
|
||||
|
||||
if (urlBarTranslatingEdge != null) {
|
||||
urlBarTranslatingEdge.setVisibility(View.INVISIBLE);
|
||||
ViewHelper.setTranslationX(urlBarTranslatingEdge, 0);
|
||||
if (shouldShrinkURLBar) {
|
||||
urlBarEntry.setLayoutParams(urlBarEntryDefaultLayoutParams);
|
||||
}
|
||||
if (shouldShrinkURLBar) {
|
||||
urlBarEntry.setLayoutParams(urlBarEntryDefaultLayoutParams);
|
||||
}
|
||||
|
||||
tabsButton.setEnabled(true);
|
||||
|
||||
urlBarTranslatingEdge.setVisibility(View.INVISIBLE);
|
||||
ViewHelper.setTranslationX(urlBarTranslatingEdge, 0);
|
||||
ViewHelper.setTranslationX(tabsButton, 0);
|
||||
ViewHelper.setTranslationX(tabsCounter, 0);
|
||||
ViewHelper.setTranslationX(actionItemBar, 0);
|
||||
|
@ -1136,17 +1174,31 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
}
|
||||
}
|
||||
|
||||
private void stopEditingOnTablet() {
|
||||
urlBarEntry.setLayoutParams(urlBarEntryDefaultLayoutParams);
|
||||
|
||||
// Show display elements.
|
||||
updateChildrenEnabledStateForEditing();
|
||||
for (final View v : tabletDisplayModeViews) {
|
||||
v.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (hidForwardButtonOnStartEditing) {
|
||||
forwardButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
// Hide editing elements.
|
||||
hideUrlEditLayout();
|
||||
}
|
||||
|
||||
private void stopEditingWithPhoneAnimation() {
|
||||
final PropertyAnimator contentAnimator = new PropertyAnimator(250);
|
||||
contentAnimator.setUseHardwareLayer(false);
|
||||
|
||||
// Slide the toolbar back to its original size.
|
||||
if (urlBarTranslatingEdge != null) {
|
||||
contentAnimator.attach(urlBarTranslatingEdge,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
0);
|
||||
}
|
||||
|
||||
contentAnimator.attach(urlBarTranslatingEdge,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
0);
|
||||
contentAnimator.attach(tabsButton,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
0);
|
||||
|
@ -1169,31 +1221,7 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
|
||||
hideUrlEditLayout(contentAnimator);
|
||||
|
||||
contentAnimator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() {
|
||||
@Override
|
||||
public void onPropertyAnimationStart() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPropertyAnimationEnd() {
|
||||
if (urlBarTranslatingEdge != null) {
|
||||
urlBarTranslatingEdge.setVisibility(View.INVISIBLE);
|
||||
if (shouldShrinkURLBar) {
|
||||
urlBarEntry.setLayoutParams(urlBarEntryDefaultLayoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
PropertyAnimator buttonsAnimator = new PropertyAnimator(300);
|
||||
urlDisplayLayout.prepareStopEditingAnimation(buttonsAnimator);
|
||||
buttonsAnimator.start();
|
||||
|
||||
isAnimatingEntry = false;
|
||||
|
||||
// Trigger animation to update the tabs counter once the
|
||||
// tabs button is back on screen.
|
||||
updateTabCountAndAnimate(Tabs.getInstance().getDisplayCount());
|
||||
}
|
||||
});
|
||||
contentAnimator.addPropertyAnimationListener(stopEditingPhoneAnimationListener);
|
||||
|
||||
isAnimatingEntry = true;
|
||||
contentAnimator.start();
|
||||
|
@ -1202,8 +1230,6 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
|||
private void setButtonEnabled(ImageButton button, boolean enabled) {
|
||||
final Drawable drawable = button.getDrawable();
|
||||
if (drawable != null) {
|
||||
// This alpha value has to be in sync with the one used
|
||||
// in updateChildrenForEditing().
|
||||
drawable.setAlpha(enabled ? 255 : 61);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ skip-if = e10s # Bug ?????? - intermittent crash of child process reported when
|
|||
[browser_bug982298.js]
|
||||
[browser_default_image_filename.js]
|
||||
skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly
|
||||
[browser_f7_caret_browsing.js]
|
||||
[browser_findbar.js]
|
||||
skip-if = e10s # Disabled for e10s: Bug ?????? - seems to be a timing issue with RemoteFinder.jsm messages coming later than the tests expect.
|
||||
[browser_input_file_tooltips.js]
|
||||
|
|
|
@ -1,242 +0,0 @@
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
let gTab = null;
|
||||
let gListener = null;
|
||||
const kURL = "data:text/html;charset=utf-8,Caret browsing is fun.<input id='in'>";
|
||||
|
||||
const kPrefShortcutEnabled = "accessibility.browsewithcaret_shortcut.enabled";
|
||||
const kPrefWarnOnEnable = "accessibility.warn_on_browsewithcaret";
|
||||
const kPrefCaretBrowsingOn = "accessibility.browsewithcaret";
|
||||
|
||||
let oldPrefs = {};
|
||||
for (let pref of [kPrefShortcutEnabled, kPrefWarnOnEnable, kPrefCaretBrowsingOn]) {
|
||||
oldPrefs[pref] = Services.prefs.getBoolPref(pref);
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
||||
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
||||
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
if (gTab)
|
||||
gBrowser.removeTab(gTab);
|
||||
if (gListener)
|
||||
Services.wm.removeListener(gListener);
|
||||
|
||||
for (let pref of [kPrefShortcutEnabled, kPrefWarnOnEnable, kPrefCaretBrowsingOn]) {
|
||||
Services.prefs.setBoolPref(pref, oldPrefs[pref]);
|
||||
}
|
||||
});
|
||||
|
||||
function promiseWaitForFocusEvent(el) {
|
||||
let deferred = Promise.defer();
|
||||
el.addEventListener("focus", function listener() {
|
||||
el.removeEventListener("focus", listener, false);
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promiseTestPageLoad() {
|
||||
let deferred = Promise.defer();
|
||||
info("Waiting for test page to load.");
|
||||
|
||||
gTab = gBrowser.selectedTab = gBrowser.addTab(kURL);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
browser.addEventListener("load", function listener() {
|
||||
if (browser.currentURI.spec == "about:blank")
|
||||
return;
|
||||
info("Page loaded: " + browser.currentURI.spec);
|
||||
browser.removeEventListener("load", listener, true);
|
||||
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promiseCaretPromptOpened() {
|
||||
let deferred = Promise.defer();
|
||||
if (gListener) {
|
||||
console.trace();
|
||||
ok(false, "Should not be waiting for another prompt right now.");
|
||||
return false;
|
||||
}
|
||||
info("Waiting for caret prompt to open");
|
||||
gListener = {
|
||||
onOpenWindow: function(win) {
|
||||
let window = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
window.addEventListener("load", function listener() {
|
||||
window.removeEventListener("load", listener);
|
||||
if (window.location.href == "chrome://global/content/commonDialog.xul") {
|
||||
info("Caret prompt opened, removing listener and focusing");
|
||||
Services.wm.removeListener(gListener);
|
||||
gListener = null;
|
||||
deferred.resolve(window);
|
||||
}
|
||||
});
|
||||
},
|
||||
onCloseWindow: function() {},
|
||||
};
|
||||
Services.wm.addListener(gListener);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function hitF7(async = true) {
|
||||
let f7 = () => EventUtils.sendKey("F7", window.content);
|
||||
// Need to not stop execution inside this task:
|
||||
if (async) {
|
||||
executeSoon(f7);
|
||||
} else {
|
||||
f7();
|
||||
}
|
||||
}
|
||||
|
||||
function syncToggleCaretNoDialog(expected) {
|
||||
let openedDialog = false;
|
||||
promiseCaretPromptOpened().then(function(win) {
|
||||
openedDialog = true;
|
||||
win.close(); // This will eventually return focus here and allow the test to continue...
|
||||
});
|
||||
// Cause the dialog to appear sync, if it still does.
|
||||
hitF7(false);
|
||||
if (gListener) {
|
||||
Services.wm.removeListener(gListener);
|
||||
gListener = null;
|
||||
}
|
||||
let expectedStr = expected ? "on." : "off.";
|
||||
ok(!openedDialog, "Shouldn't open a dialog to turn caret browsing " + expectedStr);
|
||||
let prefVal = Services.prefs.getBoolPref(kPrefCaretBrowsingOn);
|
||||
is(prefVal, expected, "Caret browsing should now be " + expectedStr);
|
||||
}
|
||||
|
||||
add_task(function* checkTogglingCaretBrowsing() {
|
||||
yield promiseTestPageLoad();
|
||||
let textEl = window.content.document.getElementById("in");
|
||||
textEl.focus();
|
||||
|
||||
let promiseGotKey = promiseCaretPromptOpened();
|
||||
hitF7();
|
||||
let prompt = yield promiseGotKey;
|
||||
let doc = prompt.document;
|
||||
is(doc.documentElement.defaultButton, "cancel", "'No' button should be the default");
|
||||
ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default.");
|
||||
let promiseInputFocused = promiseWaitForFocusEvent(textEl);
|
||||
doc.documentElement.cancelDialog();
|
||||
yield promiseInputFocused;
|
||||
ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off after cancelling the dialog.");
|
||||
|
||||
promiseGotKey = promiseCaretPromptOpened();
|
||||
hitF7();
|
||||
prompt = yield promiseGotKey;
|
||||
|
||||
doc = prompt.document;
|
||||
is(doc.documentElement.defaultButton, "cancel", "'No' button should be the default");
|
||||
ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default.");
|
||||
promiseInputFocused = promiseWaitForFocusEvent(textEl);
|
||||
doc.documentElement.acceptDialog();
|
||||
yield promiseInputFocused;
|
||||
ok(Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should be on after accepting the dialog.");
|
||||
|
||||
syncToggleCaretNoDialog(false);
|
||||
|
||||
promiseGotKey = promiseCaretPromptOpened();
|
||||
hitF7();
|
||||
prompt = yield promiseGotKey;
|
||||
doc = prompt.document;
|
||||
|
||||
is(doc.documentElement.defaultButton, "cancel", "'No' button should be the default");
|
||||
ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default.");
|
||||
|
||||
promiseInputFocused = promiseWaitForFocusEvent(textEl);
|
||||
doc.documentElement.cancelDialog();
|
||||
yield promiseInputFocused;
|
||||
|
||||
ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off after cancelling the dialog.");
|
||||
|
||||
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
||||
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
||||
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
||||
|
||||
gBrowser.removeTab(gTab);
|
||||
gTab = null;
|
||||
});
|
||||
|
||||
add_task(function* toggleCheckboxNoCaretBrowsing() {
|
||||
yield promiseTestPageLoad();
|
||||
let textEl = window.content.document.getElementById("in");
|
||||
textEl.focus();
|
||||
|
||||
let promiseGotKey = promiseCaretPromptOpened();
|
||||
hitF7();
|
||||
let prompt = yield promiseGotKey;
|
||||
let doc = prompt.document;
|
||||
is(doc.documentElement.defaultButton, "cancel", "'No' button should be the default");
|
||||
let checkbox = doc.getElementById("checkbox");
|
||||
ok(!checkbox.checked, "Checkbox shouldn't be checked by default.");
|
||||
|
||||
// Check the box:
|
||||
checkbox.click();
|
||||
let promiseInputFocused = promiseWaitForFocusEvent(textEl);
|
||||
// Say no:
|
||||
doc.documentElement.getButton("cancel").click();
|
||||
yield promiseInputFocused;
|
||||
ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off.");
|
||||
|
||||
ok(!Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should now be disabled.");
|
||||
|
||||
syncToggleCaretNoDialog(false);
|
||||
ok(!Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should still be disabled.");
|
||||
|
||||
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
||||
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
||||
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
||||
|
||||
gBrowser.removeTab(gTab);
|
||||
gTab = null;
|
||||
});
|
||||
|
||||
|
||||
add_task(function* toggleCheckboxNoCaretBrowsing() {
|
||||
yield promiseTestPageLoad();
|
||||
let textEl = window.content.document.getElementById("in");
|
||||
textEl.focus();
|
||||
|
||||
let promiseGotKey = promiseCaretPromptOpened();
|
||||
hitF7();
|
||||
let prompt = yield promiseGotKey;
|
||||
let doc = prompt.document;
|
||||
is(doc.documentElement.defaultButton, "cancel", "'No' button should be the default");
|
||||
let checkbox = doc.getElementById("checkbox");
|
||||
ok(!checkbox.checked, "Checkbox shouldn't be checked by default.");
|
||||
|
||||
// Check the box:
|
||||
checkbox.click();
|
||||
let promiseInputFocused = promiseWaitForFocusEvent(textEl);
|
||||
// Say yes:
|
||||
doc.documentElement.acceptDialog();
|
||||
yield promiseInputFocused;
|
||||
ok(Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should now be on.");
|
||||
ok(Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should still be enabled.");
|
||||
ok(!Services.prefs.getBoolPref(kPrefWarnOnEnable), "Should no longer warn when enabling.");
|
||||
|
||||
|
||||
syncToggleCaretNoDialog(false);
|
||||
syncToggleCaretNoDialog(true);
|
||||
syncToggleCaretNoDialog(false);
|
||||
|
||||
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
||||
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
||||
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
||||
|
||||
gBrowser.removeTab(gTab);
|
||||
gTab = null;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
|
@ -1100,11 +1100,7 @@
|
|||
if (event.defaultPrevented || !event.isTrusted)
|
||||
return;
|
||||
|
||||
const kPrefShortcutEnabled = "accessibility.browsewithcaret_shortcut.enabled";
|
||||
const kPrefWarnOnEnable = "accessibility.warn_on_browsewithcaret";
|
||||
const kPrefCaretBrowsingOn = "accessibility.browsewithcaret";
|
||||
|
||||
var isEnabled = this.mPrefs.getBoolPref(kPrefShortcutEnabled);
|
||||
var isEnabled = this.mPrefs.getBoolPref("accessibility.browsewithcaret_shortcut.enabled");
|
||||
if (!isEnabled)
|
||||
return;
|
||||
|
||||
|
@ -1113,12 +1109,12 @@
|
|||
var warn = true;
|
||||
|
||||
try {
|
||||
warn = this.mPrefs.getBoolPref(kPrefWarnOnEnable);
|
||||
warn = this.mPrefs.getBoolPref("accessibility.warn_on_browsewithcaret");
|
||||
} catch (ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
browseWithCaretOn = this.mPrefs.getBoolPref(kPrefCaretBrowsingOn);
|
||||
browseWithCaretOn = this.mPrefs.getBoolPref("accessibility.browsewithcaret");
|
||||
} catch (ex) {
|
||||
}
|
||||
if (warn && !browseWithCaretOn) {
|
||||
|
@ -1129,22 +1125,14 @@
|
|||
var buttonPressed = promptService.confirmEx(window,
|
||||
this.mStrBundle.GetStringFromName('browsewithcaret.checkWindowTitle'),
|
||||
this.mStrBundle.GetStringFromName('browsewithcaret.checkLabel'),
|
||||
// Make "No" the default:
|
||||
promptService.STD_YES_NO_BUTTONS | promptService.BUTTON_POS_1_DEFAULT,
|
||||
promptService.STD_YES_NO_BUTTONS,
|
||||
null, null, null, this.mStrBundle.GetStringFromName('browsewithcaret.checkMsg'),
|
||||
checkValue);
|
||||
if (buttonPressed != 0) {
|
||||
if (checkValue.value) {
|
||||
try {
|
||||
this.mPrefs.setBoolPref(kPrefShortcutEnabled, false);
|
||||
} catch (ex) {
|
||||
}
|
||||
}
|
||||
if (buttonPressed != 0)
|
||||
return;
|
||||
}
|
||||
if (checkValue.value) {
|
||||
try {
|
||||
this.mPrefs.setBoolPref(kPrefWarnOnEnable, false);
|
||||
this.mPrefs.setBoolPref("accessibility.warn_on_browsewithcaret", false);
|
||||
}
|
||||
catch (ex) {
|
||||
}
|
||||
|
@ -1153,7 +1141,7 @@
|
|||
|
||||
// Toggle the pref
|
||||
try {
|
||||
this.mPrefs.setBoolPref(kPrefCaretBrowsingOn, !browseWithCaretOn);
|
||||
this.mPrefs.setBoolPref("accessibility.browsewithcaret",!browseWithCaretOn);
|
||||
} catch (ex) {
|
||||
}
|
||||
]]>
|
||||
|
|
|
@ -107,15 +107,15 @@ function err(msg, error = null) {
|
|||
// of a blocker.
|
||||
// We are a little paranoid here to ensure that in case of evaluation
|
||||
// error we do not block the AsyncShutdown.
|
||||
function safeGetState(state) {
|
||||
if (!state) {
|
||||
function safeGetState(fetchState) {
|
||||
if (!fetchState) {
|
||||
return "(none)";
|
||||
}
|
||||
let data, string;
|
||||
try {
|
||||
// Evaluate state(), normalize the result into something that we can
|
||||
// Evaluate fetchState(), normalize the result into something that we can
|
||||
// safely stringify or upload.
|
||||
string = JSON.stringify(state());
|
||||
string = JSON.stringify(fetchState());
|
||||
data = JSON.parse(string);
|
||||
// Simplify the rest of the code by ensuring that we can simply
|
||||
// concatenate the result to a message.
|
||||
|
@ -215,7 +215,7 @@ function getPhase(topic) {
|
|||
* resulting promise is either resolved or rejected. If
|
||||
* |condition| is not a function but another value |v|, it behaves
|
||||
* as if it were a function returning |v|.
|
||||
* @param {function*} state Optionally, a function returning
|
||||
* @param {function*} fetchState Optionally, a function returning
|
||||
* information about the current state of the blocker as an
|
||||
* object. Used for providing more details when logging errors or
|
||||
* crashing.
|
||||
|
@ -241,8 +241,8 @@ function getPhase(topic) {
|
|||
* // No specific guarantee about completion of profileBeforeChange
|
||||
* });
|
||||
*/
|
||||
addBlocker: function(name, condition, state = null) {
|
||||
spinner.addBlocker(name, condition, state);
|
||||
addBlocker: function(name, condition, fetchState = null) {
|
||||
spinner.addBlocker(name, condition, fetchState);
|
||||
},
|
||||
/**
|
||||
* Remove the blocker for a condition.
|
||||
|
@ -306,8 +306,8 @@ Spinner.prototype = {
|
|||
* we wait until the promise is resolved/rejected before proceeding
|
||||
* to the next runstate.
|
||||
*/
|
||||
addBlocker: function(name, condition, state) {
|
||||
this._barrier.client.addBlocker(name, condition, state);
|
||||
addBlocker: function(name, condition, fetchState) {
|
||||
this._barrier.client.addBlocker(name, condition, fetchState);
|
||||
},
|
||||
/**
|
||||
* Remove the blocker for a condition.
|
||||
|
@ -364,7 +364,7 @@ function Barrier(name) {
|
|||
* The set of conditions registered by clients, as a map.
|
||||
*
|
||||
* Key: condition (function)
|
||||
* Value: Array of {name: string, state: function}
|
||||
* Value: Array of {name: string, fetchState: function}
|
||||
*/
|
||||
this._conditions = new Map();
|
||||
|
||||
|
@ -411,16 +411,16 @@ function Barrier(name) {
|
|||
* resulting promise is either resolved or rejected. If
|
||||
* |condition| is not a function but another value |v|, it behaves
|
||||
* as if it were a function returning |v|.
|
||||
* @param {function*} state Optionally, a function returning
|
||||
* @param {function*} fetchState Optionally, a function returning
|
||||
* information about the current state of the blocker as an
|
||||
* object. Used for providing more details when logging errors or
|
||||
* crashing.
|
||||
*/
|
||||
addBlocker: function(name, condition, state) {
|
||||
addBlocker: function(name, condition, fetchState) {
|
||||
if (typeof name != "string") {
|
||||
throw new TypeError("Expected a human-readable name as first argument");
|
||||
}
|
||||
if (state && typeof state != "function") {
|
||||
if (fetchState && typeof fetchState != "function") {
|
||||
throw new TypeError("Expected nothing or a function as third argument");
|
||||
}
|
||||
if (!this._conditions) {
|
||||
|
@ -433,7 +433,7 @@ function Barrier(name) {
|
|||
set = [];
|
||||
this._conditions.set(condition, set);
|
||||
}
|
||||
set.push({name: name, state: state});
|
||||
set.push({name: name, fetchState: fetchState});
|
||||
}.bind(this),
|
||||
|
||||
/**
|
||||
|
@ -480,9 +480,9 @@ Barrier.prototype = Object.freeze({
|
|||
return "Complete";
|
||||
}
|
||||
let frozen = [];
|
||||
for (let {name, isComplete, state} of this._monitors) {
|
||||
for (let {name, isComplete, fetchState} of this._monitors) {
|
||||
if (!isComplete) {
|
||||
frozen.push({name: name, state: safeGetState(state)});
|
||||
frozen.push({name: name, state: safeGetState(fetchState)});
|
||||
}
|
||||
}
|
||||
return frozen;
|
||||
|
@ -536,7 +536,7 @@ Barrier.prototype = Object.freeze({
|
|||
for (let _condition of conditions.keys()) {
|
||||
for (let current of conditions.get(_condition)) {
|
||||
let condition = _condition; // Avoid capturing the wrong variable
|
||||
let {name, state} = current;
|
||||
let {name, fetchState} = current;
|
||||
|
||||
// An indirection on top of condition, used to let clients
|
||||
// cancel a blocker through removeBlocker.
|
||||
|
@ -565,7 +565,7 @@ Barrier.prototype = Object.freeze({
|
|||
let monitor = {
|
||||
isComplete: false,
|
||||
name: name,
|
||||
state: state
|
||||
fetchState: fetchState
|
||||
};
|
||||
|
||||
condition = condition.then(null, function onError(error) {
|
||||
|
@ -573,7 +573,7 @@ Barrier.prototype = Object.freeze({
|
|||
" while we were spinning the event loop." +
|
||||
" Condition: " + name +
|
||||
" Phase: " + topic +
|
||||
" State: " + safeGetState(state);
|
||||
" State: " + safeGetState(fetchState);
|
||||
warn(msg, error);
|
||||
});
|
||||
condition.then(() => indirection.resolve());
|
||||
|
@ -587,7 +587,7 @@ Barrier.prototype = Object.freeze({
|
|||
" while we were initializing the phase." +
|
||||
" Condition: " + name +
|
||||
" Phase: " + topic +
|
||||
" State: " + safeGetState(state);
|
||||
" State: " + safeGetState(fetchState);
|
||||
warn(msg, error);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,10 @@ let DirectoryLinksProvider = {
|
|||
|
||||
try {
|
||||
xmlHttp.open('POST', uri);
|
||||
xmlHttp.send(JSON.stringify({ locale: this.locale }));
|
||||
xmlHttp.send(JSON.stringify({
|
||||
locale: this.locale,
|
||||
directoryCount: this._directoryCount,
|
||||
}));
|
||||
} catch (e) {
|
||||
deferred.reject("Error fetching " + uri);
|
||||
Cu.reportError(e);
|
||||
|
@ -247,6 +250,8 @@ let DirectoryLinksProvider = {
|
|||
* @return download promise
|
||||
*/
|
||||
reportShownCount: function DirectoryLinksProvider_reportShownCount(directoryCount) {
|
||||
// make a deep copy of directoryCount to avoid a leak
|
||||
this._directoryCount = Cu.cloneInto(directoryCount, {});
|
||||
if (directoryCount.sponsored > 0
|
||||
|| directoryCount.affiliate > 0
|
||||
|| directoryCount.organic > 0) {
|
||||
|
@ -292,6 +297,7 @@ let DirectoryLinksProvider = {
|
|||
*/
|
||||
reset: function DirectoryLinksProvider_reset() {
|
||||
delete this.__linksURL;
|
||||
delete this._directoryCount;
|
||||
this._removePrefsObserver();
|
||||
this._removeObservers();
|
||||
},
|
||||
|
|
|
@ -54,6 +54,8 @@ PageMenu.prototype = {
|
|||
if (pos == "start") {
|
||||
insertionPoint.insertBefore(fragment,
|
||||
insertionPoint.firstChild);
|
||||
} else if (pos.startsWith("#")) {
|
||||
insertionPoint.insertBefore(fragment, insertionPoint.querySelector(pos));
|
||||
} else {
|
||||
insertionPoint.appendChild(fragment);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ const kFailURL = kBaseUrl + kFailPath;
|
|||
const kHttpHandlerData = {};
|
||||
kHttpHandlerData[kExamplePath] = {"en-US": [{"url":"http://example.com","title":"RemoteSource"}]};
|
||||
|
||||
const bodyData = JSON.stringify({ locale: DirectoryLinksProvider.locale });
|
||||
const expectedBodyObject = {locale: DirectoryLinksProvider.locale};
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
"setInputStream");
|
||||
|
@ -60,7 +60,8 @@ function getHttpHandler(path) {
|
|||
}
|
||||
return function(aRequest, aResponse) {
|
||||
let bodyStream = new BinaryInputStream(aRequest.bodyInputStream);
|
||||
do_check_eq(NetUtil.readInputStreamToString(bodyStream, bodyStream.available()), bodyData);
|
||||
let bodyObject = JSON.parse(NetUtil.readInputStreamToString(bodyStream, bodyStream.available()));
|
||||
isIdentical(bodyObject, expectedBodyObject);
|
||||
|
||||
aResponse.setStatusLine(null, code);
|
||||
aResponse.setHeader("Content-Type", "application/json");
|
||||
|
@ -401,6 +402,14 @@ add_task(function test_DirectoryLinksProvider_fetchDirectoryOnShowCount() {
|
|||
yield DirectoryLinksProvider.reportShownCount(directoryCount);
|
||||
do_check_true(DirectoryLinksProvider._lastDownloadMS != 0);
|
||||
|
||||
// test that directoryCount object reaches the backend server
|
||||
expectedBodyObject.directoryCount = directoryCount;
|
||||
// set kSourceUrlPref to kExampleURL, causing request to test http server
|
||||
// server handler validates that expectedBodyObject has correct directoryCount
|
||||
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kExampleURL);
|
||||
// reset expectedBodyObject to its original state
|
||||
delete expectedBodyObject.directoryCount;
|
||||
|
||||
yield promiseCleanDirectoryLinksProvider();
|
||||
});
|
||||
|
||||
|
|
|
@ -489,10 +489,6 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
|
|||
}
|
||||
break;
|
||||
|
||||
case DRAW:
|
||||
ReadRectField(jenv);
|
||||
break;
|
||||
|
||||
case SENSOR_EVENT:
|
||||
mX = jenv->GetDoubleField(jobj, jXField);
|
||||
mY = jenv->GetDoubleField(jobj, jYField);
|
||||
|
|
|
@ -453,13 +453,6 @@ public:
|
|||
return event;
|
||||
}
|
||||
|
||||
static AndroidGeckoEvent* MakeDrawEvent(const nsIntRect& aRect) {
|
||||
AndroidGeckoEvent *event = new AndroidGeckoEvent();
|
||||
event->Init(DRAW);
|
||||
event->mRect = aRect;
|
||||
return event;
|
||||
}
|
||||
|
||||
static AndroidGeckoEvent* MakeFromJavaObject(JNIEnv *jenv, jobject jobj) {
|
||||
AndroidGeckoEvent *event = new AndroidGeckoEvent();
|
||||
event->Init(jenv, jobj);
|
||||
|
@ -682,7 +675,6 @@ public:
|
|||
SENSOR_EVENT = 3,
|
||||
LOCATION_EVENT = 5,
|
||||
IME_EVENT = 6,
|
||||
DRAW = 7,
|
||||
SIZE_CHANGED = 8,
|
||||
APP_BACKGROUNDING = 9,
|
||||
APP_FOREGROUNDING = 10,
|
||||
|
|
|
@ -127,9 +127,7 @@ nsAppShell::nsAppShell()
|
|||
: mQueueLock("nsAppShell.mQueueLock"),
|
||||
mCondLock("nsAppShell.mCondLock"),
|
||||
mQueueCond(mCondLock, "nsAppShell.mQueueCond"),
|
||||
mQueuedDrawEvent(nullptr),
|
||||
mQueuedViewportEvent(nullptr),
|
||||
mAllowCoalescingNextDraw(false)
|
||||
mQueuedViewportEvent(nullptr)
|
||||
{
|
||||
gAppShell = this;
|
||||
|
||||
|
@ -673,9 +671,7 @@ nsAppShell::PopNextEvent()
|
|||
if (mEventQueue.Length()) {
|
||||
ae = mEventQueue[0];
|
||||
mEventQueue.RemoveElementAt(0);
|
||||
if (mQueuedDrawEvent == ae) {
|
||||
mQueuedDrawEvent = nullptr;
|
||||
} else if (mQueuedViewportEvent == ae) {
|
||||
if (mQueuedViewportEvent == ae) {
|
||||
mQueuedViewportEvent = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -724,50 +720,6 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae)
|
|||
}
|
||||
break;
|
||||
|
||||
case AndroidGeckoEvent::DRAW:
|
||||
if (mQueuedDrawEvent) {
|
||||
#if defined(DEBUG) || defined(FORCE_ALOG)
|
||||
// coalesce this new draw event with the one already in the queue
|
||||
const nsIntRect& oldRect = mQueuedDrawEvent->Rect();
|
||||
const nsIntRect& newRect = ae->Rect();
|
||||
nsIntRect combinedRect = oldRect.Union(newRect);
|
||||
|
||||
// XXX We may want to consider using regions instead of rectangles.
|
||||
// Print an error if we're upload a lot more than we would
|
||||
// if we handled this as two separate events.
|
||||
int combinedArea = (oldRect.width * oldRect.height) +
|
||||
(newRect.width * newRect.height);
|
||||
int boundsArea = combinedRect.width * combinedRect.height;
|
||||
if (boundsArea > combinedArea * 8)
|
||||
ALOG("nsAppShell: Area of bounds greatly exceeds combined area: %d > %d",
|
||||
boundsArea, combinedArea);
|
||||
#endif
|
||||
|
||||
// coalesce into the new draw event rather than the queued one because
|
||||
// it is not always safe to move draws earlier in the queue; there may
|
||||
// be events between the two draws that affect scroll position or something.
|
||||
ae->UnionRect(mQueuedDrawEvent->Rect());
|
||||
|
||||
EVLOG("nsAppShell: Coalescing previous DRAW event at %p into new DRAW event %p", mQueuedDrawEvent, ae);
|
||||
mEventQueue.RemoveElement(mQueuedDrawEvent);
|
||||
delete mQueuedDrawEvent;
|
||||
}
|
||||
|
||||
if (!mAllowCoalescingNextDraw) {
|
||||
// if we're not allowing coalescing of this draw event, then
|
||||
// don't set mQueuedDrawEvent to point to this; that way the
|
||||
// next draw event that comes in won't kill this one.
|
||||
mAllowCoalescingNextDraw = true;
|
||||
mQueuedDrawEvent = nullptr;
|
||||
} else {
|
||||
mQueuedDrawEvent = ae;
|
||||
}
|
||||
|
||||
allowCoalescingNextViewport = true;
|
||||
|
||||
mEventQueue.AppendElement(ae);
|
||||
break;
|
||||
|
||||
case AndroidGeckoEvent::VIEWPORT:
|
||||
if (mQueuedViewportEvent) {
|
||||
// drop the previous viewport event now that we have a new one
|
||||
|
@ -776,9 +728,6 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae)
|
|||
delete mQueuedViewportEvent;
|
||||
}
|
||||
mQueuedViewportEvent = ae;
|
||||
// temporarily turn off draw-coalescing, so that we process a draw
|
||||
// event as soon as possible after a viewport change
|
||||
mAllowCoalescingNextDraw = false;
|
||||
allowCoalescingNextViewport = true;
|
||||
|
||||
mEventQueue.AppendElement(ae);
|
||||
|
|
|
@ -64,9 +64,7 @@ protected:
|
|||
Mutex mQueueLock;
|
||||
Mutex mCondLock;
|
||||
CondVar mQueueCond;
|
||||
mozilla::AndroidGeckoEvent *mQueuedDrawEvent;
|
||||
mozilla::AndroidGeckoEvent *mQueuedViewportEvent;
|
||||
bool mAllowCoalescingNextDraw;
|
||||
bool mAllowCoalescingTouches;
|
||||
nsTArray<mozilla::AndroidGeckoEvent *> mEventQueue;
|
||||
nsInterfaceHashtable<nsStringHashKey, nsIObserver> mObserversHash;
|
||||
|
|
|
@ -539,8 +539,6 @@ nsWindow::IsEnabled() const
|
|||
NS_IMETHODIMP
|
||||
nsWindow::Invalidate(const nsIntRect &aRect)
|
||||
{
|
||||
AndroidGeckoEvent *event = AndroidGeckoEvent::MakeDrawEvent(aRect);
|
||||
nsAppShell::gAppShell->PostEvent(event);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -882,12 +880,6 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
|
|||
win->mFocus->OnKeyEvent(ae);
|
||||
break;
|
||||
|
||||
case AndroidGeckoEvent::DRAW:
|
||||
layers::renderTraceEventStart("Global draw start", "414141");
|
||||
win->OnDraw(ae);
|
||||
layers::renderTraceEventEnd("414141");
|
||||
break;
|
||||
|
||||
case AndroidGeckoEvent::IME_EVENT:
|
||||
win->UserActivity();
|
||||
if (win->mFocus) {
|
||||
|
@ -937,20 +929,6 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::OnAndroidEvent(AndroidGeckoEvent *ae)
|
||||
{
|
||||
switch (ae->Type()) {
|
||||
case AndroidGeckoEvent::DRAW:
|
||||
OnDraw(ae);
|
||||
break;
|
||||
|
||||
default:
|
||||
ALOG("Window got targetted android event type %d, but didn't handle!", ae->Type());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
{
|
||||
|
@ -1044,52 +1022,6 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
{
|
||||
if (!IsTopLevel()) {
|
||||
ALOG("##### redraw for window %p, which is not a toplevel window -- sending to toplevel!", (void*) this);
|
||||
DumpWindows();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mIsVisible) {
|
||||
ALOG("##### redraw for window %p, which is not visible -- ignoring!", (void*) this);
|
||||
DumpWindows();
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
|
||||
AutoLocalJNIFrame jniFrame;
|
||||
|
||||
// We're paused, or we haven't been given a window-size yet, so do nothing
|
||||
if (sCompositorPaused || gAndroidBounds.width <= 0 || gAndroidBounds.height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int bytesPerPixel = 2;
|
||||
gfxImageFormat format = gfxImageFormat::RGB16_565;
|
||||
if (AndroidBridge::Bridge()->GetScreenDepth() == 24) {
|
||||
bytesPerPixel = 4;
|
||||
format = gfxImageFormat::RGB24;
|
||||
}
|
||||
|
||||
layers::renderTraceEventStart("Get surface", "424545");
|
||||
static unsigned char bits2[32 * 32 * 4];
|
||||
nsRefPtr<gfxImageSurface> targetSurface =
|
||||
new gfxImageSurface(bits2, gfxIntSize(32, 32), 32 * bytesPerPixel, format);
|
||||
layers::renderTraceEventEnd("Get surface", "424545");
|
||||
|
||||
layers::renderTraceEventStart("Widget draw to", "434646");
|
||||
if (targetSurface->CairoStatus()) {
|
||||
ALOG("### Failed to create a valid surface from the bitmap");
|
||||
} else {
|
||||
DrawTo(targetSurface, ae->Rect());
|
||||
}
|
||||
layers::renderTraceEventEnd("Widget draw to", "434646");
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::OnSizeChanged(const gfxIntSize& aSize)
|
||||
{
|
||||
|
|
|
@ -48,8 +48,6 @@ public:
|
|||
|
||||
nsWindow* FindWindowForPoint(const nsIntPoint& pt);
|
||||
|
||||
void OnAndroidEvent(mozilla::AndroidGeckoEvent *ae);
|
||||
void OnDraw(mozilla::AndroidGeckoEvent *ae);
|
||||
bool OnMultitouchEvent(mozilla::AndroidGeckoEvent *ae);
|
||||
void OnNativeGestureEvent(mozilla::AndroidGeckoEvent *ae);
|
||||
void OnMouseEvent(mozilla::AndroidGeckoEvent *ae);
|
||||
|
|
Загрузка…
Ссылка в новой задаче