This commit is contained in:
Ryan VanderMeulen 2014-06-02 17:21:11 -04:00
Родитель 6c7ed782e9 2190bd2057
Коммит 31441571eb
72 изменённых файлов: 911 добавлений и 1061 удалений

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

@ -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);