зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team, a=merge
This commit is contained in:
Коммит
218c9bb81a
|
@ -537,6 +537,48 @@ SettingsListener.observe("theme.selected",
|
|||
setPAC();
|
||||
})();
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AppsUtils",
|
||||
"resource://gre/modules/AppsUtils.jsm");
|
||||
|
||||
// ======================= Dogfooders FOTA ==========================
|
||||
SettingsListener.observe('debug.performance_data.dogfooding', false,
|
||||
isDogfooder => {
|
||||
if (!isDogfooder) {
|
||||
dump('AUS:Settings: Not a dogfooder!\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!('mozTelephony' in navigator)) {
|
||||
dump('AUS:Settings: There is no mozTelephony!\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!('mozMobileConnections' in navigator)) {
|
||||
dump('AUS:Settings: There is no mozMobileConnections!\n');
|
||||
return;
|
||||
}
|
||||
|
||||
let conn = navigator.mozMobileConnections[0];
|
||||
conn.addEventListener('radiostatechange', function onradiostatechange() {
|
||||
if (conn.radioState !== 'enabled') {
|
||||
return;
|
||||
}
|
||||
|
||||
conn.removeEventListener('radiostatechange', onradiostatechange);
|
||||
navigator.mozTelephony.dial('*#06#').then(call => {
|
||||
return call.result.then(res => {
|
||||
if (res.success && res.statusMessage
|
||||
&& (res.serviceCode === 'scImei')) {
|
||||
Services.prefs.setCharPref("app.update.imei_hash",
|
||||
AppsUtils.computeHash(res.statusMessage, "SHA512"));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
#endif
|
||||
|
||||
// =================== Various simple mapping ======================
|
||||
var settingsToObserve = {
|
||||
'accessibility.screenreader_quicknav_modes': {
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -19,12 +19,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="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="067c08fb3e5744b42b68d1f861245f7d507109bc"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1f9532e4157df2dc8d3e9c8100120f80117dcd4"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -19,12 +19,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="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="067c08fb3e5744b42b68d1f861245f7d507109bc"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "aede8622d780ec71f766a3ecccbff74c04aaba4e",
|
||||
"git_revision": "2082894c8e974b0c371e4dec298e0ad0f3ac56b1",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "dbd3a4ea9042cae987147f2d05f41d2a7ebaccbc",
|
||||
"revision": "0e712c8d330e10908f99194a9638e62a07c5c483",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1f9532e4157df2dc8d3e9c8100120f80117dcd4"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="aede8622d780ec71f766a3ecccbff74c04aaba4e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
|
|
|
@ -163,7 +163,7 @@
|
|||
<menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
|
||||
<menupopup rolluponmousewheel="true"
|
||||
#ifdef XP_WIN
|
||||
consumeoutsideclicks="false"
|
||||
consumeoutsideclicks="false" ignorekeys="handled"
|
||||
#endif
|
||||
/>
|
||||
</menulist>
|
||||
|
|
|
@ -23,7 +23,7 @@ const PAGECONTENT =
|
|||
" <optgroup label='Third Group'>" +
|
||||
" <option value='Seven'> Seven </option>" +
|
||||
" <option value='Eight'> Eight </option>" +
|
||||
" </optgroup></select><input />" +
|
||||
" </optgroup></select><input />Text" +
|
||||
"</body></html>";
|
||||
|
||||
function openSelectPopup(selectPopup, withMouse)
|
||||
|
@ -108,6 +108,12 @@ function doSelectTests(contentType, dtd)
|
|||
|
||||
is((yield getChangeEvents()), 0, "Before closed - number of change events");
|
||||
|
||||
EventUtils.synthesizeKey("a", { accelKey: true });
|
||||
let selection = yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
|
||||
return String(content.getSelection());
|
||||
});
|
||||
is(selection, isWindows ? "Text" : "", "Select all while popup is open");
|
||||
|
||||
yield hideSelectPopup(selectPopup);
|
||||
|
||||
is(menulist.selectedIndex, 3, "Item 3 still selected");
|
||||
|
|
|
@ -75,8 +75,8 @@ def main():
|
|||
# Run |nm|. Options:
|
||||
# -u: show only undefined symbols
|
||||
# -C: demangle symbol names
|
||||
# -l: show a filename and line number for each undefined symbol
|
||||
cmd = ['nm', '-u', '-C', '-l', args.file]
|
||||
# -A: show an object filename for each undefined symbol
|
||||
cmd = ['nm', '-u', '-C', '-A', args.file]
|
||||
lines = subprocess.check_output(cmd, universal_newlines=True,
|
||||
stderr=subprocess.PIPE).split('\n')
|
||||
|
||||
|
@ -112,26 +112,30 @@ def main():
|
|||
# This regexp matches the relevant lines in the output of |nm|, which look
|
||||
# like the following.
|
||||
#
|
||||
# U malloc /path/to/objdir/dist/include/js/Utility.h:142
|
||||
# js/src/libjs_static.a:jsutil.o: U malloc
|
||||
#
|
||||
alloc_fns_re = r'U (' + r'|'.join(alloc_fns) + r').*\/([\w\.]+):(\d+)$'
|
||||
alloc_fns_re = r'([^:/ ]+):\s+U (' + r'|'.join(alloc_fns) + r')'
|
||||
|
||||
# This tracks which allocation/free functions have been seen in jsutil.cpp.
|
||||
jsutil_cpp = set([])
|
||||
|
||||
# Would it be helpful to emit detailed line number information after a failure?
|
||||
emit_line_info = False
|
||||
|
||||
for line in lines:
|
||||
m = re.search(alloc_fns_re, line)
|
||||
if m is None:
|
||||
continue
|
||||
|
||||
fn = m.group(1)
|
||||
filename = m.group(2)
|
||||
linenum = m.group(3)
|
||||
if filename == 'jsutil.cpp':
|
||||
filename = m.group(1)
|
||||
fn = m.group(2)
|
||||
if filename == 'jsutil.o':
|
||||
jsutil_cpp.add(fn)
|
||||
else:
|
||||
# An allocation is present in a non-special file. Fail!
|
||||
fail("'" + fn + "' present at " + filename + ':' + linenum)
|
||||
fail("'" + fn + "' present in " + filename)
|
||||
# Try to give more precise information about the offending code.
|
||||
emit_line_info = True
|
||||
|
||||
|
||||
# Check that all functions we expect are used in jsutil.cpp. (This will
|
||||
|
@ -147,6 +151,34 @@ def main():
|
|||
fail('unexpected allocation fns used in jsutil.cpp: ' +
|
||||
', '.join(jsutil_cpp))
|
||||
|
||||
# If we found any improper references to allocation functions, try to use
|
||||
# DWARF debug info to get more accurate line number information about the
|
||||
# bad calls. This is a lot slower than 'nm -A', and it is not always
|
||||
# precise when building with --enable-optimized.
|
||||
if emit_line_info:
|
||||
print('check_vanilla_allocations.py: Source lines with allocation calls:')
|
||||
print('check_vanilla_allocations.py: Accurate in unoptimized builds; jsutil.cpp expected.')
|
||||
|
||||
# Run |nm|. Options:
|
||||
# -u: show only undefined symbols
|
||||
# -C: demangle symbol names
|
||||
# -l: show line number information for each undefined symbol
|
||||
cmd = ['nm', '-u', '-C', '-l', args.file]
|
||||
lines = subprocess.check_output(cmd, universal_newlines=True,
|
||||
stderr=subprocess.PIPE).split('\n')
|
||||
|
||||
# This regexp matches the relevant lines in the output of |nm -l|,
|
||||
# which look like the following.
|
||||
#
|
||||
# U malloc jsutil.cpp:117
|
||||
#
|
||||
alloc_lines_re = r'U ((' + r'|'.join(alloc_fns) + r').*)\s+(\S+:\d+)$'
|
||||
|
||||
for line in lines:
|
||||
m = re.search(alloc_lines_re, line)
|
||||
if m:
|
||||
print('check_vanilla_allocations.py:', m.group(1), 'called at', m.group(3))
|
||||
|
||||
if has_failed:
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -7251,9 +7251,6 @@ if test -z "$MOZ_MEMORY"; then
|
|||
esac
|
||||
else
|
||||
AC_DEFINE(MOZ_MEMORY)
|
||||
if test -n "$NIGHTLY_BUILD"; then
|
||||
MOZ_JEMALLOC4=1
|
||||
fi
|
||||
if test -n "$MOZ_JEMALLOC4"; then
|
||||
AC_DEFINE(MOZ_JEMALLOC4)
|
||||
fi
|
||||
|
|
|
@ -10871,10 +10871,7 @@ nsDocShell::DoChannelLoad(nsIChannel* aChannel,
|
|||
|
||||
// If the user pressed shift-reload, then do not allow ServiceWorker
|
||||
// interception to occur. See step 12.1 of the SW HandleFetch algorithm.
|
||||
if (mLoadType == LOAD_RELOAD_BYPASS_CACHE ||
|
||||
mLoadType == LOAD_RELOAD_BYPASS_PROXY ||
|
||||
mLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
|
||||
mLoadType == LOAD_RELOAD_ALLOW_MIXED_CONTENT) {
|
||||
if (IsForceReloadType(mLoadType)) {
|
||||
nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(aChannel);
|
||||
if (internal) {
|
||||
internal->ForceNoIntercept();
|
||||
|
@ -11163,11 +11160,7 @@ nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, nsISupports* aOwner,
|
|||
* for the page. Save the new cacheKey in Session History.
|
||||
* see bug 90098
|
||||
*/
|
||||
if (aChannel &&
|
||||
(aLoadType == LOAD_RELOAD_BYPASS_CACHE ||
|
||||
aLoadType == LOAD_RELOAD_BYPASS_PROXY ||
|
||||
aLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
|
||||
aLoadType == LOAD_RELOAD_ALLOW_MIXED_CONTENT)) {
|
||||
if (aChannel && IsForceReloadType(aLoadType)) {
|
||||
NS_ASSERTION(!updateSHistory,
|
||||
"We shouldn't be updating session history for forced"
|
||||
" reloads!");
|
||||
|
|
|
@ -101,5 +101,17 @@ IsValidLoadType(uint32_t aLoadType)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsForceReloadType(uint32_t aLoadType) {
|
||||
switch (aLoadType) {
|
||||
case LOAD_RELOAD_BYPASS_CACHE:
|
||||
case LOAD_RELOAD_BYPASS_PROXY:
|
||||
case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
|
||||
case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
#endif
|
||||
|
|
|
@ -560,7 +560,7 @@ Animation::CanThrottle() const
|
|||
return true;
|
||||
}
|
||||
|
||||
return mIsRunningOnCompositor;
|
||||
return IsRunningOnCompositor();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -763,11 +763,6 @@ Animation::DoPause(ErrorResult& aRv)
|
|||
reuseReadyPromise = true;
|
||||
}
|
||||
|
||||
// Mark this as no longer running on the compositor so that next time
|
||||
// we update animations we won't throttle them and will have a chance
|
||||
// to remove the animation from any layer it might be on.
|
||||
mIsRunningOnCompositor = false;
|
||||
|
||||
if (!reuseReadyPromise) {
|
||||
// Clear ready promise. We'll create a new one lazily.
|
||||
mReady = nullptr;
|
||||
|
@ -1202,5 +1197,11 @@ Animation::DispatchPlaybackEvent(const nsAString& aName)
|
|||
asyncDispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
bool
|
||||
Animation::IsRunningOnCompositor() const
|
||||
{
|
||||
return mEffect && mEffect->IsRunningOnCompositor();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -58,7 +58,6 @@ public:
|
|||
, mPlaybackRate(1.0)
|
||||
, mPendingState(PendingState::NotPending)
|
||||
, mAnimationIndex(sNextAnimationIndex++)
|
||||
, mIsRunningOnCompositor(false)
|
||||
, mFinishedAtLastComposeStyle(false)
|
||||
, mIsRelevant(false)
|
||||
, mFinishedIsResolved(false)
|
||||
|
@ -109,7 +108,7 @@ public:
|
|||
virtual void Play(ErrorResult& aRv, LimitBehavior aLimitBehavior);
|
||||
virtual void Pause(ErrorResult& aRv);
|
||||
virtual void Reverse(ErrorResult& aRv);
|
||||
bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; }
|
||||
bool IsRunningOnCompositor() const;
|
||||
IMPL_EVENT_HANDLER(finish);
|
||||
IMPL_EVENT_HANDLER(cancel);
|
||||
|
||||
|
@ -269,8 +268,6 @@ public:
|
|||
*/
|
||||
virtual bool HasLowerCompositeOrderThan(const Animation& aOther) const;
|
||||
|
||||
void SetIsRunningOnCompositor() { mIsRunningOnCompositor = true; }
|
||||
void ClearIsRunningOnCompositor() { mIsRunningOnCompositor = false; }
|
||||
/**
|
||||
* Returns true if this animation does not currently need to update
|
||||
* style on the main thread (e.g. because it is empty, or is
|
||||
|
@ -409,7 +406,6 @@ protected:
|
|||
// possible for two different objects to have the same index.
|
||||
uint64_t mAnimationIndex;
|
||||
|
||||
bool mIsRunningOnCompositor;
|
||||
bool mFinishedAtLastComposeStyle;
|
||||
// Indicates that the animation should be exposed in an element's
|
||||
// getAnimations() list.
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/FloatingPoint.h"
|
||||
#include "AnimationCommon.h"
|
||||
#include "nsCSSPropertySet.h"
|
||||
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -74,6 +75,20 @@ NS_INTERFACE_MAP_END_INHERITING(AnimationEffectReadOnly)
|
|||
NS_IMPL_ADDREF_INHERITED(KeyframeEffectReadOnly, AnimationEffectReadOnly)
|
||||
NS_IMPL_RELEASE_INHERITED(KeyframeEffectReadOnly, AnimationEffectReadOnly)
|
||||
|
||||
KeyframeEffectReadOnly::KeyframeEffectReadOnly(
|
||||
nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
const AnimationTiming& aTiming)
|
||||
: AnimationEffectReadOnly(aDocument)
|
||||
, mTarget(aTarget)
|
||||
, mTiming(aTiming)
|
||||
, mPseudoType(aPseudoType)
|
||||
{
|
||||
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
|
||||
ResetIsRunningOnCompositor();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
KeyframeEffectReadOnly::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
|
@ -396,5 +411,50 @@ KeyframeEffectReadOnly::ComposeStyle(nsRefPtr<AnimValuesStyleRule>& aStyleRule,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
KeyframeEffectReadOnly::IsRunningOnCompositor() const
|
||||
{
|
||||
// We consider animation is running on compositor if there is at least
|
||||
// one property running on compositor.
|
||||
// Animation.IsRunningOnCompotitor will return more fine grained
|
||||
// information in bug 1196114.
|
||||
for (bool isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) {
|
||||
if (isPropertyRunningOnCompositor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::SetIsRunningOnCompositor(nsCSSProperty aProperty,
|
||||
bool aIsRunning)
|
||||
{
|
||||
static_assert(
|
||||
MOZ_ARRAY_LENGTH(LayerAnimationInfo::sRecords) ==
|
||||
MOZ_ARRAY_LENGTH(mIsPropertyRunningOnCompositor),
|
||||
"The length of mIsPropertyRunningOnCompositor should equal to"
|
||||
"the length of LayserAnimationInfo::sRecords");
|
||||
MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty,
|
||||
CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR),
|
||||
"Property being animated on compositor is a recognized "
|
||||
"compositor-animatable property");
|
||||
const auto& info = LayerAnimationInfo::sRecords;
|
||||
for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) {
|
||||
if (info[i].mProperty == aProperty) {
|
||||
mIsPropertyRunningOnCompositor[i] = aIsRunning;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
|
||||
{
|
||||
for (bool& isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) {
|
||||
isPropertyRunningOnCompositor = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords
|
||||
#include "mozilla/StickyTimeDuration.h"
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
@ -199,14 +200,7 @@ public:
|
|||
KeyframeEffectReadOnly(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
const AnimationTiming &aTiming)
|
||||
: AnimationEffectReadOnly(aDocument)
|
||||
, mTarget(aTarget)
|
||||
, mTiming(aTiming)
|
||||
, mPseudoType(aPseudoType)
|
||||
{
|
||||
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
|
||||
}
|
||||
const AnimationTiming& aTiming);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffectReadOnly,
|
||||
|
@ -308,9 +302,12 @@ public:
|
|||
// Any updated properties are added to |aSetProperties|.
|
||||
void ComposeStyle(nsRefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties);
|
||||
bool IsRunningOnCompositor() const;
|
||||
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
|
||||
|
||||
protected:
|
||||
virtual ~KeyframeEffectReadOnly() { }
|
||||
void ResetIsRunningOnCompositor();
|
||||
|
||||
nsCOMPtr<Element> mTarget;
|
||||
Nullable<TimeDuration> mParentTime;
|
||||
|
@ -319,6 +316,17 @@ protected:
|
|||
nsCSSPseudoElements::Type mPseudoType;
|
||||
|
||||
InfallibleTArray<AnimationProperty> mProperties;
|
||||
|
||||
// Parallel array corresponding to CommonAnimationManager::sLayerAnimationInfo
|
||||
// such that mIsPropertyRunningOnCompositor[x] is true only if this effect has
|
||||
// an animation of CommonAnimationManager::sLayerAnimationInfo[x].mProperty
|
||||
// that is currently running on the compositor.
|
||||
//
|
||||
// Note that when the owning Animation requests a non-throttled restyle, in
|
||||
// between calling RequestRestyle on its AnimationCollection and when the
|
||||
// restyle is performed, this member may temporarily become false even if
|
||||
// the animation remains on the layer after the restyle.
|
||||
bool mIsPropertyRunningOnCompositor[LayerAnimationInfo::kRecords];
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
testcommon.js
|
||||
../../imptests/testharness.js
|
||||
../../imptests/testharnessreport.js
|
||||
[chrome/test_animation_observers.html]
|
||||
[chrome/test_running_on_compositor.html]
|
||||
skip-if = buildapp == 'b2g'
|
||||
skip-if = buildapp == 'b2g'
|
||||
|
|
|
@ -3,18 +3,23 @@
|
|||
<meta charset=utf-8>
|
||||
<title>Bug 1045994 - Add a chrome-only property to inspect if an animation is
|
||||
running on the compositor or not</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="../testharness.js"></script>
|
||||
<script type="application/javascript" src="../testharnessreport.js"></script>
|
||||
<script type="application/javascript" src="../testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
to { transform: translate(100px) }
|
||||
}
|
||||
@keyframes background_and_translate {
|
||||
to { background-color: red; transform: translate(100px); }
|
||||
}
|
||||
@keyframes background {
|
||||
to { background-color: red; }
|
||||
}
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
div {
|
||||
/* Element needs geometry to be eligible for layerization */
|
||||
width: 100px;
|
||||
|
@ -26,47 +31,241 @@ div {
|
|||
<body>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1045994"
|
||||
target="_blank">Mozilla Bug 1045994</a>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
/** Test for bug 1045994 - Add a chrome-only property to inspect if an
|
||||
animation is running on the compositor or not **/
|
||||
|
||||
function addDiv(attrs) {
|
||||
var div = document.createElement('div');
|
||||
if (attrs) {
|
||||
for (var attrName in attrs) {
|
||||
div.setAttribute(attrName, attrs[attrName]);
|
||||
}
|
||||
}
|
||||
document.body.appendChild(div);
|
||||
return div;
|
||||
}
|
||||
|
||||
const OMTAPrefKey = 'layers.offmainthreadcomposition.async-animations';
|
||||
var omtaEnabled = SpecialPowers.DOMWindowUtils.layerManagerRemote &&
|
||||
SpecialPowers.getBoolPref(OMTAPrefKey);
|
||||
|
||||
add_task(function* play_and_pause_from_style() {
|
||||
promise_test(function(t) {
|
||||
// FIXME: When we implement Element.animate, use that here instead of CSS
|
||||
// so that we remove any dependency on the CSS mapping.
|
||||
var div = addDiv({ style: 'animation: anim 100s' });
|
||||
var div = addDiv(t, { style: 'animation: anim 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor'
|
||||
+ ' during playback');
|
||||
|
||||
is(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor'
|
||||
+ ' during playback');
|
||||
div.style.animationPlayState = 'paused';
|
||||
|
||||
div.style.animationPlayState = 'paused';
|
||||
return animation.ready;
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when paused');
|
||||
}));
|
||||
}, '');
|
||||
|
||||
yield animation.ready;
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: background 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' for animation of "background"');
|
||||
}));
|
||||
}, 'isRunningOnCompositor is false for animation of "background"');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: background_and_translate 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor'
|
||||
+ ' when the animation has two properties, where one can run'
|
||||
+ ' on the compositor, the other cannot');
|
||||
}));
|
||||
}, 'isRunningOnCompositor is true if the animation has at least one ' +
|
||||
'property can run on compositor');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: anim 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
animation.pause();
|
||||
return animation.ready;
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when animation.pause() is called');
|
||||
}));
|
||||
}, 'isRunningOnCompositor is false when the animation.pause() is called');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: anim 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
animation.finish();
|
||||
// We need to wait for two frames here to ensure isRunningOnCompositor
|
||||
// flag is cleared. The first frame is for waking root refresh driver up,
|
||||
// the second one is for clearing the flag.
|
||||
// In most cases root refresh driver has been dormant because there is
|
||||
// nothing to do for the root refresh driver (e.g. nothing change on
|
||||
// chrome window). In the first frame document's refresh driver wakes the
|
||||
// root refresh driver up as a result of animation's style changes.
|
||||
// In the second frame the root refresh driver clears the flag as a
|
||||
// result of a paint.
|
||||
return waitForAnimationFrames(2);
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when animation.finish() is called');
|
||||
}));
|
||||
}, 'isRunningOnCompositor is false when the animation.finish() is called');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: anim 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
animation.currentTime = 100000; // 100s
|
||||
// We need to wait for up to two frames here to ensure the "is running on
|
||||
// compositor" flag is cleared.
|
||||
// See the description in the 'isRunningOnCompositor is false when the
|
||||
// animation.finish() is called' test for the rationale.
|
||||
return waitForAnimationFrames(2);
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when manually seeking the animation to the end');
|
||||
}));
|
||||
}, 'isRunningOnCompositor is false when manually seeking the animation to ' +
|
||||
'the end');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: anim 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
animation.cancel();
|
||||
// We need to wait for up to two frames here to ensure the "is running on
|
||||
// compositor" flag is cleared.
|
||||
// See the description in the 'isRunningOnCompositor is false when the
|
||||
// animation.finish() is called' test for the rationale.
|
||||
return waitForAnimationFrames(2);
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when animation.cancel() is called');
|
||||
}));
|
||||
}, 'isRunningOnCompositor is false when animation.cancel() is called');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: anim 100s 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' while in the delay phase');
|
||||
}));
|
||||
}, 'isRunningOnCompositor is false while in the delay phase');
|
||||
|
||||
// This is to test that we don't simply clobber the flag when ticking
|
||||
// animations and then set it again during painting.
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: anim 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
return new Promise(t.step_func(function(resolve) {
|
||||
window.requestAnimationFrame(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor'
|
||||
+ ' in requestAnimationFrame callback');
|
||||
resolve();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}, 'isRunningOnCompositor is true in requestAnimationFrame callback');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: anim 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
return new Promise(t.step_func(function(resolve) {
|
||||
var observer = new MutationObserver(t.step_func(function(records) {
|
||||
var changedAnimation;
|
||||
records.forEach(function(record) {
|
||||
changedAnimation =
|
||||
record.changedAnimations.find(function(changedAnim) {
|
||||
return changedAnim == animation;
|
||||
});
|
||||
});
|
||||
assert_true(!!changedAnimation, 'The animation should be recorded '
|
||||
+ 'as one of the changedAnimations');
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor'
|
||||
+ ' in MutationObserver callback');
|
||||
resolve();
|
||||
}));
|
||||
observer.observe(div, { animations: true, subtree: false });
|
||||
div.style.animationDuration = "200s";
|
||||
}));
|
||||
}));
|
||||
}, 'isRunningOnCompositor is true in MutationObserver callback');
|
||||
|
||||
// This is to test that we don't temporarily clear the flag when forcing
|
||||
// an unthrottled sample.
|
||||
promise_test(function(t) {
|
||||
return new Promise(function(resolve) {
|
||||
// Needs scrollbars to cause overflow.
|
||||
SpecialPowers.pushPrefEnv({ set: [["ui.showHideScrollbars", 1]] },
|
||||
resolve);
|
||||
}).then(t.step_func(function() {
|
||||
var div = addDiv(t, { style: 'animation: rotate 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
return new Promise(t.step_func(function(resolve) {
|
||||
var timeAtStart = window.performance.now();
|
||||
function handleFrame() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor'
|
||||
+ ' in requestAnimationFrame callback');
|
||||
|
||||
// we have to wait at least 200ms because this animation is
|
||||
// unthrottled on every 200ms.
|
||||
// See http://hg.mozilla.org/mozilla-central/file/cafb1c90f794/layout/style/AnimationCommon.cpp#l863
|
||||
if (window.performance.now() - timeAtStart > 200) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
window.requestAnimationFrame(handleFrame);
|
||||
}
|
||||
window.requestAnimationFrame(handleFrame);
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}, 'isRunningOnCompositor remains true in requestAnimationFrameCallback for ' +
|
||||
'overflow animation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t, { style: 'transition: opacity 100s; opacity: 1' });
|
||||
|
||||
getComputedStyle(div).opacity;
|
||||
|
||||
div.style.opacity = 0;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Transition reports that it is running on the compositor'
|
||||
+ ' during playback for opacity transition');
|
||||
}));
|
||||
}, 'isRunningOnCompositor for transitions');
|
||||
|
||||
is(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when paused');
|
||||
div.parentNode.removeChild(div);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -89,20 +89,22 @@ function flushComputedStyle(elem) {
|
|||
cs.marginLeft;
|
||||
}
|
||||
|
||||
for (var funcName of ["async_test", "assert_not_equals", "assert_equals",
|
||||
"assert_approx_equals", "assert_less_than",
|
||||
"assert_less_than_equal", "assert_between_inclusive",
|
||||
"assert_true", "assert_false",
|
||||
"assert_class_string", "assert_throws",
|
||||
"assert_unreached", "test"]) {
|
||||
window[funcName] = opener[funcName].bind(opener);
|
||||
}
|
||||
if (opener) {
|
||||
for (var funcName of ["async_test", "assert_not_equals", "assert_equals",
|
||||
"assert_approx_equals", "assert_less_than",
|
||||
"assert_less_than_equal", "assert_between_inclusive",
|
||||
"assert_true", "assert_false",
|
||||
"assert_class_string", "assert_throws",
|
||||
"assert_unreached", "test"]) {
|
||||
window[funcName] = opener[funcName].bind(opener);
|
||||
}
|
||||
|
||||
window.EventWatcher = opener.EventWatcher;
|
||||
window.EventWatcher = opener.EventWatcher;
|
||||
|
||||
function done() {
|
||||
opener.add_completion_callback(function() {
|
||||
self.close();
|
||||
});
|
||||
opener.done();
|
||||
function done() {
|
||||
opener.add_completion_callback(function() {
|
||||
self.close();
|
||||
});
|
||||
opener.done();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -757,8 +757,8 @@ this.AppsUtils = {
|
|||
return deferred.promise;
|
||||
},
|
||||
|
||||
// Returns the MD5 hash of a string.
|
||||
computeHash: function(aString) {
|
||||
// Returns the hash of a string, with MD5 as a default hashing function.
|
||||
computeHash: function(aString, aAlgorithm = "MD5") {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
@ -768,7 +768,7 @@ this.AppsUtils = {
|
|||
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"]
|
||||
.createInstance(Ci.nsICryptoHash);
|
||||
hasher.init(hasher.MD5);
|
||||
hasher.initWithString(aAlgorithm);
|
||||
hasher.update(data, data.length);
|
||||
// We're passing false to get the binary hash and not base64.
|
||||
let hash = hasher.finish(false);
|
||||
|
|
|
@ -135,8 +135,8 @@ class DestinationInsertionPointList;
|
|||
|
||||
// IID for the dom::Element interface
|
||||
#define NS_ELEMENT_IID \
|
||||
{ 0x31d3f3fb, 0xcdf8, 0x4e40, \
|
||||
{ 0xb7, 0x09, 0x1a, 0x11, 0x43, 0x93, 0x61, 0x71 } }
|
||||
{ 0xc67ed254, 0xfd3b, 0x4b10, \
|
||||
{ 0x96, 0xa2, 0xc5, 0x8b, 0x7b, 0x64, 0x97, 0xd1 } }
|
||||
|
||||
class Element : public FragmentOrElement
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "mozilla/css/Loader.h"
|
||||
#include "mozilla/css/ImageLoader.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsDocShellLoadTypes.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
@ -4730,15 +4731,13 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
|||
mTemplateContentsOwner->SetScriptGlobalObject(aScriptGlobalObject);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = GetChannel();
|
||||
if (!mMaybeServiceWorkerControlled && channel) {
|
||||
nsLoadFlags loadFlags = 0;
|
||||
channel->GetLoadFlags(&loadFlags);
|
||||
if (!mMaybeServiceWorkerControlled && mDocumentContainer && mScriptGlobalObject && GetChannel()) {
|
||||
nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
|
||||
uint32_t loadType;
|
||||
docShell->GetLoadType(&loadType);
|
||||
|
||||
// If we are shift-reloaded, don't associate with a ServiceWorker.
|
||||
// TODO: This should check the nsDocShell definition of shift-reload instead
|
||||
// of trying to infer it from LOAD_BYPASS_CACHE. The current code
|
||||
// will probably cause problems once bug 1120715 lands.
|
||||
if (loadFlags & nsIRequest::LOAD_BYPASS_CACHE) {
|
||||
if (IsForceReloadType(loadType)) {
|
||||
NS_WARNING("Page was shift reloaded, skipping ServiceWorker control");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
class nsDOMAttributeMap;
|
||||
|
||||
#define NS_IATTRIBUTE_IID \
|
||||
{ 0x233a9c4d, 0xb27f, 0x4662, \
|
||||
{ 0xbd, 0x90, 0xba, 0xd6, 0x2e, 0x76, 0xc8, 0xe1 } }
|
||||
{ 0x84d43da7, 0xb45d, 0x47ae, \
|
||||
{ 0x8f, 0xbf, 0x95, 0x26, 0x78, 0x4d, 0x5e, 0x47 } }
|
||||
|
||||
class nsIAttribute : public nsINode
|
||||
{
|
||||
|
|
|
@ -40,8 +40,8 @@ enum nsLinkState {
|
|||
|
||||
// IID for the nsIContent interface
|
||||
#define NS_ICONTENT_IID \
|
||||
{ 0x70f7e9ea, 0xa9bf, 0x48cc, \
|
||||
{ 0xad, 0x9d, 0x8a, 0xca, 0xee, 0xd2, 0x9b, 0x68 } }
|
||||
{ 0x52cebfc8, 0x79ba, 0x4e38, \
|
||||
{ 0x8a, 0x4c, 0x7f, 0x9d, 0xb1, 0xa2, 0xb6, 0x1d } }
|
||||
|
||||
/**
|
||||
* A node of content in a document's content model. This interface
|
||||
|
|
|
@ -155,8 +155,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
|
|||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x292450a1, 0x285e, 0x4a09, \
|
||||
{ 0x9a, 0xf9, 0x61, 0xf9, 0xb1, 0xbd, 0x27, 0xcc } }
|
||||
{ 0x72391609, 0x673d, 0x4bec, \
|
||||
{ 0xbd, 0x75, 0x64, 0xbf, 0x1f, 0x6a, 0x6b, 0x5e } }
|
||||
|
||||
// Enum for requesting a particular type of document when creating a doc
|
||||
enum DocumentFlavor {
|
||||
|
|
|
@ -2833,3 +2833,12 @@ nsINode::AddAnimationObserverUnlessExists(
|
|||
AddMutationObserverUnlessExists(aAnimationObserver);
|
||||
OwnerDoc()->SetMayHaveAnimationObservers();
|
||||
}
|
||||
|
||||
bool
|
||||
nsINode::HasApzAwareListeners() const
|
||||
{
|
||||
if (NodeMayHaveApzAwareListeners()) {
|
||||
return EventTarget::HasApzAwareListeners();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -250,8 +250,8 @@ private:
|
|||
|
||||
// IID for the nsINode interface
|
||||
#define NS_INODE_IID \
|
||||
{ 0xe8fdd227, 0x27da, 0x46ee, \
|
||||
{ 0xbe, 0xf3, 0x1a, 0xef, 0x5a, 0x8f, 0xc5, 0xb4 } }
|
||||
{ 0x70ba4547, 0x7699, 0x44fc, \
|
||||
{ 0xb3, 0x20, 0x52, 0xdb, 0xe3, 0xd1, 0xf9, 0x0a } }
|
||||
|
||||
/**
|
||||
* An internal interface that abstracts some DOMNode-related parts that both
|
||||
|
@ -949,6 +949,9 @@ public:
|
|||
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
|
||||
mozilla::ErrorResult& aRv) override;
|
||||
using nsIDOMEventTarget::AddSystemEventListener;
|
||||
|
||||
virtual bool HasApzAwareListeners() const override;
|
||||
|
||||
virtual nsIDOMWindow* GetOwnerGlobalForBindings() override;
|
||||
virtual nsIGlobalObject* GetOwnerGlobal() const override;
|
||||
|
||||
|
@ -1495,6 +1498,8 @@ private:
|
|||
ElementHasWeirdParserInsertionMode,
|
||||
// Parser sets this flag if it has notified about the node.
|
||||
ParserHasNotified,
|
||||
// EventListenerManager sets this flag in case we have apz aware listeners.
|
||||
MayHaveApzAwareListeners,
|
||||
// Guard value
|
||||
BooleanFlagCount
|
||||
};
|
||||
|
@ -1637,6 +1642,12 @@ public:
|
|||
void SetHasRelevantHoverRules() { SetBoolFlag(NodeHasRelevantHoverRules); }
|
||||
void SetParserHasNotified() { SetBoolFlag(ParserHasNotified); };
|
||||
bool HasParserNotified() { return GetBoolFlag(ParserHasNotified); }
|
||||
|
||||
void SetMayHaveApzAwareListeners() { SetBoolFlag(MayHaveApzAwareListeners); }
|
||||
bool NodeMayHaveApzAwareListeners() const
|
||||
{
|
||||
return GetBoolFlag(MayHaveApzAwareListeners);
|
||||
}
|
||||
protected:
|
||||
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
|
||||
void SetInDocument() { SetBoolFlag(IsInDocument); }
|
||||
|
|
|
@ -22,8 +22,8 @@ class TabParent;
|
|||
} // namespace mozilla
|
||||
|
||||
#define NS_IWINDOWROOT_IID \
|
||||
{ 0x238edca0, 0xb30d, 0x46d3, \
|
||||
{ 0xb2, 0x6a, 0x17, 0xb6, 0x21, 0x28, 0x89, 0x7e } }
|
||||
{ 0xb8724c49, 0xc398, 0x4f9b, \
|
||||
{ 0x82, 0x59, 0x87, 0x27, 0xa6, 0x47, 0xdd, 0x0f } }
|
||||
|
||||
class nsPIWindowRoot : public mozilla::dom::EventTarget
|
||||
{
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,346 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_BluetoothDaemonCoreInterface_h
|
||||
#define mozilla_dom_bluetooth_bluedroid_BluetoothDaemonCoreInterface_h
|
||||
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "mozilla/ipc/DaemonRunnables.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
using mozilla::ipc::DaemonSocketResultHandler;
|
||||
|
||||
class BluetoothDaemonCoreModule
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
SERVICE_ID = 0x01
|
||||
};
|
||||
|
||||
enum {
|
||||
OPCODE_ERROR = 0x00,
|
||||
OPCODE_ENABLE = 0x01,
|
||||
OPCODE_DISABLE = 0x02,
|
||||
OPCODE_GET_ADAPTER_PROPERTIES = 0x03,
|
||||
OPCODE_GET_ADAPTER_PROPERTY = 0x04,
|
||||
OPCODE_SET_ADAPTER_PROPERTY = 0x05,
|
||||
OPCODE_GET_REMOTE_DEVICE_PROPERTIES = 0x06,
|
||||
OPCODE_GET_REMOTE_DEVICE_PROPERTY = 0x07,
|
||||
OPCODE_SET_REMOTE_DEVICE_PROPERTY = 0x08,
|
||||
OPCODE_GET_REMOTE_SERVICE_RECORD = 0x09,
|
||||
OPCODE_GET_REMOTE_SERVICES = 0x0a,
|
||||
OPCODE_START_DISCOVERY = 0x0b,
|
||||
OPCODE_CANCEL_DISCOVERY = 0x0c,
|
||||
OPCODE_CREATE_BOND = 0x0d,
|
||||
OPCODE_REMOVE_BOND = 0x0e,
|
||||
OPCODE_CANCEL_BOND = 0x0f,
|
||||
OPCODE_PIN_REPLY = 0x10,
|
||||
OPCODE_SSP_REPLY = 0x11,
|
||||
OPCODE_DUT_MODE_CONFIGURE = 0x12,
|
||||
OPCODE_DUT_MODE_SEND = 0x13,
|
||||
OPCODE_LE_TEST_MODE = 0x14,
|
||||
OPCODE_ADAPTER_STATE_CHANGED_NTF = 0x81,
|
||||
OPCODE_ADAPTER_PROPERTIES_NTF = 0x82,
|
||||
OPCODE_REMOTE_DEVICE_PROPERTIES_NTF = 0x83,
|
||||
OPCODE_DEVICE_FOUND_NTF = 0x84,
|
||||
OPCODE_DISCOVERY_STATE_CHANGED_NTF = 0x85,
|
||||
OPCODE_PIN_REQUEST_NTF = 0x86,
|
||||
OPCODE_SSP_REQUEST_NTF = 0x87,
|
||||
OPCODE_BOND_STATE_CHANGED_NTF = 0x88,
|
||||
OPCODE_ACL_STATE_CHANGED_NTF = 0x89,
|
||||
OPCODE_DUT_MODE_RECV_NTF = 0x8a,
|
||||
OPCODE_LE_TEST_MODE_NTF = 0x8b
|
||||
};
|
||||
|
||||
static const int MAX_NUM_CLIENTS;
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
void SetNotificationHandler(
|
||||
BluetoothNotificationHandler* aNotificationHandler);
|
||||
|
||||
BluetoothNotificationHandler* GetNotificationHandler();
|
||||
|
||||
//
|
||||
// Commands
|
||||
//
|
||||
|
||||
nsresult EnableCmd(BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult DisableCmd(BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetAdapterPropertiesCmd(BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetAdapterPropertyCmd(const nsAString& aName,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult SetAdapterPropertyCmd(const BluetoothNamedValue& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetRemoteDevicePropertiesCmd(const nsAString& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr,
|
||||
const nsAString& aName,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult SetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr,
|
||||
const BluetoothNamedValue& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetRemoteServiceRecordCmd(const nsAString& aRemoteAddr,
|
||||
const uint8_t aUuid[16],
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetRemoteServicesCmd(const nsAString& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult StartDiscoveryCmd(BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult CancelDiscoveryCmd(BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult CreateBondCmd(const nsAString& aBdAddr,
|
||||
BluetoothTransport aTransport,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult RemoveBondCmd(const nsAString& aBdAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult CancelBondCmd(const nsAString& aBdAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult PinReplyCmd(const nsAString& aBdAddr, bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult SspReplyCmd(const nsAString& aBdAddr, BluetoothSspVariant aVariant,
|
||||
bool aAccept, uint32_t aPasskey,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult DutModeConfigureCmd(bool aEnable, BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult DutModeSendCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult LeTestModeCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Responses
|
||||
//
|
||||
|
||||
typedef mozilla::ipc::DaemonResultRunnable0<
|
||||
BluetoothResultHandler, void>
|
||||
ResultRunnable;
|
||||
|
||||
typedef mozilla::ipc::DaemonResultRunnable1<
|
||||
BluetoothResultHandler, void, BluetoothStatus, BluetoothStatus>
|
||||
ErrorRunnable;
|
||||
|
||||
void ErrorRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void EnableRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void DisableRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void GetAdapterPropertiesRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void GetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void SetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void GetRemoteDevicePropertiesRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void
|
||||
GetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void SetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
void GetRemoteServiceRecordRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
void GetRemoteServicesRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void StartDiscoveryRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
void CancelDiscoveryRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void CreateBondRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
void RemoveBondRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
void CancelBondRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void PinReplyRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
void SspReplyRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void DutModeConfigureRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void DutModeSendRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void LeTestModeRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void HandleRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
|
||||
class NotificationHandlerWrapper;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable1<
|
||||
NotificationHandlerWrapper, void, bool>
|
||||
AdapterStateChangedNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
NotificationHandlerWrapper, void, BluetoothStatus, int,
|
||||
nsAutoArrayPtr<BluetoothProperty>, BluetoothStatus, int,
|
||||
const BluetoothProperty*>
|
||||
AdapterPropertiesNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable4<
|
||||
NotificationHandlerWrapper, void, BluetoothStatus, nsString, int,
|
||||
nsAutoArrayPtr<BluetoothProperty>, BluetoothStatus, const nsAString&,
|
||||
int, const BluetoothProperty*>
|
||||
RemoteDevicePropertiesNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable2<
|
||||
NotificationHandlerWrapper, void, int, nsAutoArrayPtr<BluetoothProperty>,
|
||||
int, const BluetoothProperty*>
|
||||
DeviceFoundNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable1<
|
||||
NotificationHandlerWrapper, void, bool>
|
||||
DiscoveryStateChangedNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
NotificationHandlerWrapper, void, nsString, nsString, uint32_t,
|
||||
const nsAString&, const nsAString&>
|
||||
PinRequestNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable5<
|
||||
NotificationHandlerWrapper, void, nsString, nsString, uint32_t,
|
||||
BluetoothSspVariant, uint32_t, const nsAString&, const nsAString&>
|
||||
SspRequestNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
NotificationHandlerWrapper, void, BluetoothStatus, nsString,
|
||||
BluetoothBondState, BluetoothStatus, const nsAString&>
|
||||
BondStateChangedNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
NotificationHandlerWrapper, void, BluetoothStatus, nsString, bool,
|
||||
BluetoothStatus, const nsAString&>
|
||||
AclStateChangedNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
NotificationHandlerWrapper, void, uint16_t, nsAutoArrayPtr<uint8_t>,
|
||||
uint8_t, uint16_t, const uint8_t*>
|
||||
DutModeRecvNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable2<
|
||||
NotificationHandlerWrapper, void, BluetoothStatus, uint16_t>
|
||||
LeTestModeNotification;
|
||||
|
||||
class AclStateChangedInitOp;
|
||||
class AdapterPropertiesInitOp;
|
||||
class BondStateChangedInitOp;
|
||||
class DeviceFoundInitOp;
|
||||
class DutModeRecvInitOp;
|
||||
class PinRequestInitOp;
|
||||
class RemoteDevicePropertiesInitOp;
|
||||
class SspRequestInitOp;
|
||||
|
||||
void AdapterStateChangedNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void AdapterPropertiesNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void RemoteDevicePropertiesNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void DeviceFoundNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void DiscoveryStateChangedNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void PinRequestNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void SspRequestNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void BondStateChangedNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void AclStateChangedNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void DutModeRecvNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void LeTestModeNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU);
|
||||
|
||||
void HandleNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
|
||||
|
||||
static BluetoothNotificationHandler* sNotificationHandler;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_bluetooth_bluedroid_BluetoothDaemonCoreInterface_h
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -32,7 +32,9 @@ BluetoothDaemonSocketModule::ListenCmd(BluetoothSocketType aType,
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoPtr<DaemonSocketPDU> pdu(new DaemonSocketPDU(0x02, 0x01, 0));
|
||||
nsAutoPtr<DaemonSocketPDU> pdu(
|
||||
new DaemonSocketPDU(SERVICE_ID, OPCODE_LISTEN,
|
||||
0));
|
||||
|
||||
nsresult rv = PackPDU(
|
||||
aType,
|
||||
|
@ -61,7 +63,9 @@ BluetoothDaemonSocketModule::ConnectCmd(const nsAString& aBdAddr,
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoPtr<DaemonSocketPDU> pdu(new DaemonSocketPDU(0x02, 0x02, 0));
|
||||
nsAutoPtr<DaemonSocketPDU> pdu(
|
||||
new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT,
|
||||
0));
|
||||
|
||||
nsresult rv = PackPDU(
|
||||
PackConversion<nsAString, BluetoothAddress>(aBdAddr),
|
||||
|
@ -166,9 +170,9 @@ BluetoothDaemonSocketModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
|||
const DaemonSocketPDUHeader&,
|
||||
DaemonSocketPDU&,
|
||||
BluetoothSocketResultHandler*) = {
|
||||
[0x00] = &BluetoothDaemonSocketModule::ErrorRsp,
|
||||
[0x01] = &BluetoothDaemonSocketModule::ListenRsp,
|
||||
[0x02] = &BluetoothDaemonSocketModule::ConnectRsp
|
||||
[OPCODE_ERROR] = &BluetoothDaemonSocketModule::ErrorRsp,
|
||||
[OPCODE_LISTEN] = &BluetoothDaemonSocketModule::ListenRsp,
|
||||
[OPCODE_CONNECT] = &BluetoothDaemonSocketModule::ConnectRsp
|
||||
};
|
||||
|
||||
if (NS_WARN_IF(MOZ_ARRAY_LENGTH(HandleRsp) <= aHeader.mOpcode) ||
|
||||
|
|
|
@ -20,6 +20,16 @@ using mozilla::ipc::DaemonSocketResultHandler;
|
|||
class BluetoothDaemonSocketModule
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
SERVICE_ID = 0x02
|
||||
};
|
||||
|
||||
enum {
|
||||
OPCODE_ERROR = 0x00,
|
||||
OPCODE_LISTEN = 0x01,
|
||||
OPCODE_CONNECT = 0x02
|
||||
};
|
||||
|
||||
static const int MAX_NUM_CLIENTS;
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
|
|
|
@ -74,6 +74,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
'bluedroid/BluetoothAvrcpManager.cpp',
|
||||
'bluedroid/BluetoothDaemonA2dpInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonAvrcpInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonCoreInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonGattInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonHandsfreeInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonHelpers.cpp',
|
||||
|
|
|
@ -72,7 +72,8 @@ var CopyPasteAssistent = {
|
|||
collapsed: e.collapsed,
|
||||
caretVisible: e.caretVisible,
|
||||
selectionVisible: e.selectionVisible,
|
||||
selectionEditable: e.selectionEditable
|
||||
selectionEditable: e.selectionEditable,
|
||||
selectedTextContent: e.selectedTextContent
|
||||
};
|
||||
|
||||
// Get correct geometry information if we have nested iframe.
|
||||
|
|
|
@ -459,6 +459,8 @@ BrowserElementParent.prototype = {
|
|||
// - caretVisible: Indicate the caret visiibility.
|
||||
// - selectionVisible: Indicate current selection is visible or not.
|
||||
// - selectionEditable: Indicate current selection is editable or not.
|
||||
// - selectedTextContent: Contains current selected text content, which is
|
||||
// equivalent to the string returned by Selection.toString().
|
||||
_handleCaretStateChanged: function(data) {
|
||||
let evt = this._createEvent('caretstatechanged', data.json,
|
||||
/* cancelable = */ false);
|
||||
|
|
|
@ -405,6 +405,13 @@ EventListenerManager::AddEventListenerInternal(
|
|||
}
|
||||
}
|
||||
|
||||
if (IsApzAwareEvent(aTypeAtom)) {
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
|
||||
if (node) {
|
||||
node->SetMayHaveApzAwareListeners();
|
||||
}
|
||||
}
|
||||
|
||||
if (aTypeAtom && mTarget) {
|
||||
mTarget->EventListenerAdded(aTypeAtom);
|
||||
}
|
||||
|
@ -1490,6 +1497,30 @@ EventListenerManager::TraceListeners(JSTracer* aTrc)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
EventListenerManager::HasApzAwareListeners()
|
||||
{
|
||||
uint32_t count = mListeners.Length();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
Listener* listener = &mListeners.ElementAt(i);
|
||||
if (IsApzAwareEvent(listener->mTypeAtom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EventListenerManager::IsApzAwareEvent(nsIAtom* aEvent)
|
||||
{
|
||||
return aEvent == nsGkAtoms::ontouchstart ||
|
||||
aEvent == nsGkAtoms::ontouchmove ||
|
||||
aEvent == nsGkAtoms::onwheel ||
|
||||
aEvent == nsGkAtoms::onDOMMouseScroll ||
|
||||
aEvent == nsHtml5Atoms::onmousewheel ||
|
||||
aEvent == nsGkAtoms::onMozMousePixelScroll;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIScriptGlobalObject>
|
||||
EventListenerManager::GetScriptGlobalAndDocument(nsIDocument** aDoc)
|
||||
{
|
||||
|
|
|
@ -443,6 +443,10 @@ public:
|
|||
|
||||
dom::EventTarget* GetTarget() { return mTarget; }
|
||||
|
||||
bool HasApzAwareListeners();
|
||||
|
||||
bool IsApzAwareEvent(nsIAtom* aEvent);
|
||||
|
||||
protected:
|
||||
void HandleEventInternal(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
|
|
|
@ -56,5 +56,12 @@ EventTarget::SetEventHandler(nsIAtom* aType, const nsAString& aTypeString,
|
|||
GetOrCreateListenerManager()->SetEventHandler(aType, aTypeString, aHandler);
|
||||
}
|
||||
|
||||
bool
|
||||
EventTarget::HasApzAwareListeners() const
|
||||
{
|
||||
EventListenerManager* elm = GetExistingListenerManager();
|
||||
return elm && elm->HasApzAwareListeners();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -28,8 +28,8 @@ template <class T> struct Nullable;
|
|||
|
||||
// IID for the dom::EventTarget interface
|
||||
#define NS_EVENTTARGET_IID \
|
||||
{ 0x605158a9, 0xe229, 0x45b1, \
|
||||
{ 0xbc, 0x12, 0x02, 0x9f, 0xa3, 0xa9, 0x3f, 0xcb } }
|
||||
{ 0xde651c36, 0x0053, 0x4c67, \
|
||||
{ 0xb1, 0x3d, 0x67, 0xb9, 0x40, 0xfc, 0x82, 0xe4 } }
|
||||
|
||||
class EventTarget : public nsIDOMEventTarget,
|
||||
public nsWrapperCache
|
||||
|
@ -88,6 +88,8 @@ public:
|
|||
*/
|
||||
virtual EventListenerManager* GetExistingListenerManager() const = 0;
|
||||
|
||||
virtual bool HasApzAwareListeners() const;
|
||||
|
||||
protected:
|
||||
EventHandlerNonNull* GetEventHandler(nsIAtom* aType,
|
||||
const nsAString& aTypeString);
|
||||
|
|
|
@ -232,7 +232,7 @@ HTMLVideoElement::GetVideoPlaybackQuality()
|
|||
}
|
||||
|
||||
if (mDecoder) {
|
||||
MediaDecoder::FrameStatistics& stats = mDecoder->GetFrameStatistics();
|
||||
FrameStatistics& stats = mDecoder->GetFrameStatistics();
|
||||
totalFrames = stats.GetParsedFrames();
|
||||
droppedFrames = stats.GetDroppedFrames();
|
||||
corruptedFrames = 0;
|
||||
|
|
|
@ -45,10 +45,12 @@ this.Keyboard = {
|
|||
_keyboardMM: null, // The keyboard app message manager.
|
||||
_keyboardID: -1, // The keyboard app's ID number. -1 = invalid
|
||||
_nextKeyboardID: 0, // The ID number counter.
|
||||
_systemMMs: [], // The message managers registered to handle system async
|
||||
// messages.
|
||||
_supportsSwitchingTypes: [],
|
||||
_systemMessageNames: [
|
||||
'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions',
|
||||
'SetSupportsSwitchingTypes'
|
||||
'SetSupportsSwitchingTypes', 'RegisterSync', 'Unregister'
|
||||
],
|
||||
|
||||
_messageNames: [
|
||||
|
@ -57,7 +59,7 @@ this.Keyboard = {
|
|||
'SwitchToNextInputMethod', 'HideInputMethod',
|
||||
'GetText', 'SendKey', 'GetContext',
|
||||
'SetComposition', 'EndComposition',
|
||||
'Register', 'Unregister'
|
||||
'RegisterSync', 'Unregister'
|
||||
],
|
||||
|
||||
get formMM() {
|
||||
|
@ -89,6 +91,20 @@ this.Keyboard = {
|
|||
} catch(e) { }
|
||||
},
|
||||
|
||||
sendToSystem: function(name, data) {
|
||||
if (!this._systemMMs.length) {
|
||||
dump("Keyboard.jsm: Attempt to send message " + name +
|
||||
" to system but no message manager registered.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._systemMMs.forEach((mm, i) => {
|
||||
data.inputManageId = i;
|
||||
mm.sendAsyncMessage(name, data);
|
||||
});
|
||||
},
|
||||
|
||||
init: function keyboardInit() {
|
||||
Services.obs.addObserver(this, 'inprocess-browser-shown', false);
|
||||
Services.obs.addObserver(this, 'remote-browser-shown', false);
|
||||
|
@ -124,10 +140,14 @@ this.Keyboard = {
|
|||
// keyboard app that the focus has been lost.
|
||||
this.sendToKeyboard('Keyboard:Blur', {});
|
||||
// Notify system app to hide keyboard.
|
||||
this.sendToSystem('System:Blur', {});
|
||||
// XXX: To be removed when content migrate away from mozChromeEvents.
|
||||
SystemAppProxy.dispatchEvent({
|
||||
type: 'inputmethod-contextchange',
|
||||
inputType: 'blur'
|
||||
});
|
||||
|
||||
this.formMM = null;
|
||||
}
|
||||
} else {
|
||||
// Ignore notifications that aren't from a BrowserOrApp
|
||||
|
@ -193,7 +213,7 @@ this.Keyboard = {
|
|||
}
|
||||
|
||||
if (0 === msg.name.indexOf('Keyboard:') &&
|
||||
('Keyboard:Register' !== msg.name && this._keyboardID !== kbID)
|
||||
('Keyboard:RegisterSync' !== msg.name && this._keyboardID !== kbID)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -228,6 +248,24 @@ this.Keyboard = {
|
|||
case 'Keyboard:RemoveFocus':
|
||||
case 'System:RemoveFocus':
|
||||
this.removeFocus();
|
||||
break;
|
||||
case 'System:RegisterSync': {
|
||||
if (this._systemMMs.length !== 0) {
|
||||
dump('Keyboard.jsm Warning: There are more than one content page ' +
|
||||
'with input-manage permission. There will be undeterministic ' +
|
||||
'responses to addInput()/removeInput() if both content pages are ' +
|
||||
'trying to respond to the same request event.\n');
|
||||
}
|
||||
|
||||
let id = this._systemMMs.length;
|
||||
this._systemMMs.push(mm);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
case 'System:Unregister':
|
||||
this._systemMMs.splice(msg.data.id, 1);
|
||||
|
||||
break;
|
||||
case 'System:SetSelectedOption':
|
||||
this.setSelectedOption(msg);
|
||||
|
@ -265,7 +303,7 @@ this.Keyboard = {
|
|||
case 'Keyboard:EndComposition':
|
||||
this.endComposition(msg);
|
||||
break;
|
||||
case 'Keyboard:Register':
|
||||
case 'Keyboard:RegisterSync':
|
||||
this._keyboardMM = mm;
|
||||
if (kbID) {
|
||||
// keyboard identifies itself, use its kbID
|
||||
|
@ -293,10 +331,14 @@ this.Keyboard = {
|
|||
.frameLoader.messageManager;
|
||||
this.formMM = mm;
|
||||
|
||||
// Notify the current active input app to gain focus.
|
||||
this.forwardEvent('Keyboard:Focus', msg);
|
||||
|
||||
// Chrome event, used also to render value selectors; that's why we need
|
||||
// the info about choices / min / max here as well...
|
||||
// Notify System app, used also to render value selectors for now;
|
||||
// that's why we need the info about choices / min / max here as well...
|
||||
this.sendToSystem('System:Focus', msg.data);
|
||||
|
||||
// XXX: To be removed when content migrate away from mozChromeEvents.
|
||||
SystemAppProxy.dispatchEvent({
|
||||
type: 'inputmethod-contextchange',
|
||||
inputType: msg.data.inputType,
|
||||
|
@ -322,7 +364,9 @@ this.Keyboard = {
|
|||
this.formMM = null;
|
||||
|
||||
this.forwardEvent('Keyboard:Blur', msg);
|
||||
this.sendToSystem('System:Blur', {});
|
||||
|
||||
// XXX: To be removed when content migrate away from mozChromeEvents.
|
||||
SystemAppProxy.dispatchEvent({
|
||||
type: 'inputmethod-contextchange',
|
||||
inputType: 'blur'
|
||||
|
@ -362,12 +406,18 @@ this.Keyboard = {
|
|||
},
|
||||
|
||||
showInputMethodPicker: function keyboardShowInputMethodPicker() {
|
||||
this.sendToSystem('System:ShowAll', {});
|
||||
|
||||
// XXX: To be removed with mozContentEvent support from shell.js
|
||||
SystemAppProxy.dispatchEvent({
|
||||
type: "inputmethod-showall"
|
||||
});
|
||||
},
|
||||
|
||||
switchToNextInputMethod: function keyboardSwitchToNextInputMethod() {
|
||||
this.sendToSystem('System:Next', {});
|
||||
|
||||
// XXX: To be removed with mozContentEvent support from shell.js
|
||||
SystemAppProxy.dispatchEvent({
|
||||
type: "inputmethod-next"
|
||||
});
|
||||
|
@ -432,14 +482,17 @@ function InputRegistryGlue() {
|
|||
|
||||
ppmm.addMessageListener('InputRegistry:Add', this);
|
||||
ppmm.addMessageListener('InputRegistry:Remove', this);
|
||||
ppmm.addMessageListener('System:InputRegistry:Add:Done', this);
|
||||
ppmm.addMessageListener('System:InputRegistry:Remove:Done', this);
|
||||
};
|
||||
|
||||
InputRegistryGlue.prototype.receiveMessage = function(msg) {
|
||||
let mm = Utils.getMMFromMessage(msg);
|
||||
|
||||
if (!Utils.checkPermissionForMM(mm, 'input')) {
|
||||
let permName = msg.name.startsWith("System:") ? "input-mgmt" : "input";
|
||||
if (!Utils.checkPermissionForMM(mm, permName)) {
|
||||
dump("InputRegistryGlue message " + msg.name +
|
||||
" from a content process with no 'input' privileges.");
|
||||
" from a content process with no " + permName + " privileges.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -452,6 +505,12 @@ InputRegistryGlue.prototype.receiveMessage = function(msg) {
|
|||
case 'InputRegistry:Remove':
|
||||
this.removeInput(msg, mm);
|
||||
|
||||
break;
|
||||
|
||||
case 'System:InputRegistry:Add:Done':
|
||||
case 'System:InputRegistry:Remove:Done':
|
||||
this.returnMessage(msg.data);
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
@ -465,6 +524,14 @@ InputRegistryGlue.prototype.addInput = function(msg, mm) {
|
|||
|
||||
let manifestURL = appsService.getManifestURLByLocalId(msg.data.appId);
|
||||
|
||||
Keyboard.sendToSystem('System:InputRegistry:Add', {
|
||||
id: msgId,
|
||||
manifestURL: manifestURL,
|
||||
inputId: msg.data.inputId,
|
||||
inputManifest: msg.data.inputManifest
|
||||
});
|
||||
|
||||
// XXX: To be removed when content migrate away from mozChromeEvents.
|
||||
SystemAppProxy.dispatchEvent({
|
||||
type: 'inputregistry-add',
|
||||
id: msgId,
|
||||
|
@ -483,6 +550,13 @@ InputRegistryGlue.prototype.removeInput = function(msg, mm) {
|
|||
|
||||
let manifestURL = appsService.getManifestURLByLocalId(msg.data.appId);
|
||||
|
||||
Keyboard.sendToSystem('System:InputRegistry:Remove', {
|
||||
id: msgId,
|
||||
manifestURL: manifestURL,
|
||||
inputId: msg.data.inputId
|
||||
});
|
||||
|
||||
// XXX: To be removed when content migrate away from mozChromeEvents.
|
||||
SystemAppProxy.dispatchEvent({
|
||||
type: 'inputregistry-remove',
|
||||
id: msgId,
|
||||
|
@ -493,6 +567,8 @@ InputRegistryGlue.prototype.removeInput = function(msg, mm) {
|
|||
|
||||
InputRegistryGlue.prototype.returnMessage = function(detail) {
|
||||
if (!this._msgMap.has(detail.id)) {
|
||||
dump('InputRegistryGlue: Ignoring already handled message response. ' +
|
||||
'id=' + detail.id + '\n');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -500,6 +576,7 @@ InputRegistryGlue.prototype.returnMessage = function(detail) {
|
|||
this._msgMap.delete(detail.id);
|
||||
|
||||
if (Cu.isDeadWrapper(mm)) {
|
||||
dump('InputRegistryGlue: Message manager has already died.\n');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -143,6 +144,54 @@ MozInputMethodManager.prototype = {
|
|||
|
||||
QueryInterface: XPCOMUtils.generateQI([]),
|
||||
|
||||
set oninputcontextfocus(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("oninputcontextfocus", handler);
|
||||
},
|
||||
|
||||
get oninputcontextfocus() {
|
||||
return this.__DOM_IMPL__.getEventHandler("oninputcontextfocus");
|
||||
},
|
||||
|
||||
set oninputcontextblur(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("oninputcontextblur", handler);
|
||||
},
|
||||
|
||||
get oninputcontextblur() {
|
||||
return this.__DOM_IMPL__.getEventHandler("oninputcontextblur");
|
||||
},
|
||||
|
||||
set onshowallrequest(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("onshowallrequest", handler);
|
||||
},
|
||||
|
||||
get onshowallrequest() {
|
||||
return this.__DOM_IMPL__.getEventHandler("onshowallrequest");
|
||||
},
|
||||
|
||||
set onnextrequest(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("onnextrequest", handler);
|
||||
},
|
||||
|
||||
get onnextrequest() {
|
||||
return this.__DOM_IMPL__.getEventHandler("onnextrequest");
|
||||
},
|
||||
|
||||
set onaddinputrequest(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("onaddinputrequest", handler);
|
||||
},
|
||||
|
||||
get onaddinputrequest() {
|
||||
return this.__DOM_IMPL__.getEventHandler("onaddinputrequest");
|
||||
},
|
||||
|
||||
set onremoveinputrequest(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("onremoveinputrequest", handler);
|
||||
},
|
||||
|
||||
get onremoveinputrequest() {
|
||||
return this.__DOM_IMPL__.getEventHandler("onremoveinputrequest");
|
||||
},
|
||||
|
||||
showAll: function() {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return;
|
||||
|
@ -175,6 +224,169 @@ MozInputMethodManager.prototype = {
|
|||
cpmm.sendAsyncMessage('System:SetSupportsSwitchingTypes', {
|
||||
types: types
|
||||
});
|
||||
},
|
||||
|
||||
handleFocus: function(data) {
|
||||
let detail = new MozInputContextFocusEventDetail(this._window, data);
|
||||
let wrappedDetail =
|
||||
this._window.MozInputContextFocusEventDetail._create(this._window, detail);
|
||||
let event = new this._window.CustomEvent('inputcontextfocus',
|
||||
{ cancelable: true, detail: wrappedDetail });
|
||||
|
||||
let handled = !this.__DOM_IMPL__.dispatchEvent(event);
|
||||
|
||||
// A gentle warning if the event is not preventDefault() by the content.
|
||||
if (!handled) {
|
||||
dump('MozKeyboard.js: A frame with input-manage permission did not' +
|
||||
' handle the inputcontextfocus event dispatched.\n');
|
||||
}
|
||||
},
|
||||
|
||||
handleBlur: function(data) {
|
||||
let event =
|
||||
new this._window.Event('inputcontextblur', { cancelable: true });
|
||||
|
||||
let handled = !this.__DOM_IMPL__.dispatchEvent(event);
|
||||
|
||||
// A gentle warning if the event is not preventDefault() by the content.
|
||||
if (!handled) {
|
||||
dump('MozKeyboard.js: A frame with input-manage permission did not' +
|
||||
' handle the inputcontextblur event dispatched.\n');
|
||||
}
|
||||
},
|
||||
|
||||
dispatchShowAllRequestEvent: function() {
|
||||
this._fireSimpleEvent('showallrequest');
|
||||
},
|
||||
|
||||
dispatchNextRequestEvent: function() {
|
||||
this._fireSimpleEvent('nextrequest');
|
||||
},
|
||||
|
||||
_fireSimpleEvent: function(eventType) {
|
||||
let event = new this._window.Event(eventType);
|
||||
let handled = !this.__DOM_IMPL__.dispatchEvent(event, { cancelable: true });
|
||||
|
||||
// A gentle warning if the event is not preventDefault() by the content.
|
||||
if (!handled) {
|
||||
dump('MozKeyboard.js: A frame with input-manage permission did not' +
|
||||
' handle the ' + eventType + ' event dispatched.\n');
|
||||
}
|
||||
},
|
||||
|
||||
handleAddInput: function(data) {
|
||||
let p = this._fireInputRegistryEvent('addinputrequest', data);
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.then(() => {
|
||||
cpmm.sendAsyncMessage('System:InputRegistry:Add:Done', {
|
||||
id: data.id
|
||||
});
|
||||
}, (error) => {
|
||||
cpmm.sendAsyncMessage('System:InputRegistry:Add:Done', {
|
||||
id: data.id,
|
||||
error: error || 'Unknown Error'
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
handleRemoveInput: function(data) {
|
||||
let p = this._fireInputRegistryEvent('removeinputrequest', data);
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.then(() => {
|
||||
cpmm.sendAsyncMessage('System:InputRegistry:Remove:Done', {
|
||||
id: data.id
|
||||
});
|
||||
}, (error) => {
|
||||
cpmm.sendAsyncMessage('System:InputRegistry:Remove:Done', {
|
||||
id: data.id,
|
||||
error: error || 'Unknown Error'
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_fireInputRegistryEvent: function(eventType, data) {
|
||||
let detail = new MozInputRegistryEventDetail(this._window, data);
|
||||
let wrappedDetail =
|
||||
this._window.MozInputRegistryEventDetail._create(this._window, detail);
|
||||
let event = new this._window.CustomEvent(eventType,
|
||||
{ cancelable: true, detail: wrappedDetail });
|
||||
let handled = !this.__DOM_IMPL__.dispatchEvent(event);
|
||||
|
||||
// A gentle warning if the event is not preventDefault() by the content.
|
||||
if (!handled) {
|
||||
dump('MozKeyboard.js: A frame with input-manage permission did not' +
|
||||
' handle the ' + eventType + ' event dispatched.\n');
|
||||
|
||||
return null;
|
||||
}
|
||||
return detail.takeChainedPromise();
|
||||
}
|
||||
};
|
||||
|
||||
function MozInputContextFocusEventDetail(win, data) {
|
||||
this.type = data.type;
|
||||
this.inputType = data.inputType;
|
||||
this.value = data.value;
|
||||
// Exposed as MozInputContextChoicesInfo dictionary defined in WebIDL
|
||||
this.choices = data.choices;
|
||||
this.min = data.min;
|
||||
this.max = data.max;
|
||||
}
|
||||
MozInputContextFocusEventDetail.prototype = {
|
||||
classID: Components.ID("{e0794208-ac50-40e8-b22e-6ee0b4c4e6e8}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([]),
|
||||
|
||||
type: undefined,
|
||||
inputType: undefined,
|
||||
value: '',
|
||||
choices: null,
|
||||
min: undefined,
|
||||
max: undefined
|
||||
};
|
||||
|
||||
function MozInputRegistryEventDetail(win, data) {
|
||||
this._window = win;
|
||||
|
||||
this.manifestURL = data.manifestURL;
|
||||
this.inputId = data.inputId;
|
||||
// Exposed as MozInputMethodInputManifest dictionary defined in WebIDL
|
||||
this.inputManifest = data.inputManifest;
|
||||
|
||||
this._chainedPromise = Promise.resolve();
|
||||
}
|
||||
MozInputRegistryEventDetail.prototype = {
|
||||
classID: Components.ID("{02130070-9b3e-4f38-bbd9-f0013aa36717}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([]),
|
||||
|
||||
_window: null,
|
||||
|
||||
manifestURL: undefined,
|
||||
inputId: undefined,
|
||||
inputManifest: null,
|
||||
|
||||
waitUntil: function(p) {
|
||||
// Need an extra protection here since waitUntil will be an no-op
|
||||
// when chainedPromise is already returned.
|
||||
if (!this._chainedPromise) {
|
||||
throw new this._window.DOMException(
|
||||
'Must call waitUntil() within the event handling loop.',
|
||||
'InvalidStateError');
|
||||
}
|
||||
|
||||
this._chainedPromise = this._chainedPromise
|
||||
.then(function() { return p; });
|
||||
},
|
||||
|
||||
takeChainedPromise: function() {
|
||||
var p = this._chainedPromise;
|
||||
this._chainedPromise = null;
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -188,10 +400,13 @@ function MozInputMethod() { }
|
|||
MozInputMethod.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
_window: null,
|
||||
_inputcontext: null,
|
||||
_wrappedInputContext: null,
|
||||
_mgmt: null,
|
||||
_wrappedMgmt: null,
|
||||
_supportsSwitchingTypes: [],
|
||||
_window: null,
|
||||
_inputManageId: undefined,
|
||||
|
||||
classID: Components.ID("{4607330d-e7d2-40a4-9eb8-43967eae0142}"),
|
||||
|
||||
|
@ -204,6 +419,7 @@ MozInputMethod.prototype = {
|
|||
init: function mozInputMethodInit(win) {
|
||||
this._window = win;
|
||||
this._mgmt = new MozInputMethodManager(win);
|
||||
this._wrappedMgmt = win.MozInputMethodManager._create(win, this._mgmt);
|
||||
this.innerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
|
@ -217,11 +433,22 @@ MozInputMethod.prototype = {
|
|||
cpmm.addWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this);
|
||||
cpmm.addWeakMessageListener('InputRegistry:Result:OK', this);
|
||||
cpmm.addWeakMessageListener('InputRegistry:Result:Error', this);
|
||||
|
||||
if (this._hasInputManagePerm(win)) {
|
||||
this._inputManageId = cpmm.sendSyncMessage('System:RegisterSync', {})[0];
|
||||
cpmm.addWeakMessageListener('System:Focus', this);
|
||||
cpmm.addWeakMessageListener('System:Blur', this);
|
||||
cpmm.addWeakMessageListener('System:ShowAll', this);
|
||||
cpmm.addWeakMessageListener('System:Next', this);
|
||||
cpmm.addWeakMessageListener('System:InputRegistry:Add', this);
|
||||
cpmm.addWeakMessageListener('System:InputRegistry:Remove', this);
|
||||
}
|
||||
},
|
||||
|
||||
uninit: function mozInputMethodUninit() {
|
||||
this._window = null;
|
||||
this._mgmt = null;
|
||||
this._wrappedMgmt = null;
|
||||
|
||||
cpmm.removeWeakMessageListener('Keyboard:Focus', this);
|
||||
cpmm.removeWeakMessageListener('Keyboard:Blur', this);
|
||||
|
@ -231,15 +458,34 @@ MozInputMethod.prototype = {
|
|||
cpmm.removeWeakMessageListener('InputRegistry:Result:OK', this);
|
||||
cpmm.removeWeakMessageListener('InputRegistry:Result:Error', this);
|
||||
this.setActive(false);
|
||||
|
||||
if (typeof this._inputManageId === 'number') {
|
||||
cpmm.sendAsyncMessage('System:Unregister', {
|
||||
'id': this._inputManageId
|
||||
});
|
||||
cpmm.removeWeakMessageListener('System:Focus', this);
|
||||
cpmm.removeWeakMessageListener('System:Blur', this);
|
||||
cpmm.removeWeakMessageListener('System:ShowAll', this);
|
||||
cpmm.removeWeakMessageListener('System:Next', this);
|
||||
cpmm.removeWeakMessageListener('System:InputRegistry:Add', this);
|
||||
cpmm.removeWeakMessageListener('System:InputRegistry:Remove', this);
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function mozInputMethodReceiveMsg(msg) {
|
||||
if (!msg.name.startsWith('InputRegistry') &&
|
||||
if (msg.name.startsWith('Keyboard') &&
|
||||
!WindowMap.isActive(this._window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let data = msg.data;
|
||||
|
||||
if (msg.name.startsWith('System') &&
|
||||
this._inputManageId !== data.inputManageId) {
|
||||
return;
|
||||
}
|
||||
delete data.inputManageId;
|
||||
|
||||
let resolver = ('requestId' in data) ?
|
||||
this.takePromiseResolver(data.requestId) : null;
|
||||
|
||||
|
@ -272,6 +518,30 @@ MozInputMethod.prototype = {
|
|||
resolver.reject(data.error);
|
||||
|
||||
break;
|
||||
|
||||
case 'System:Focus':
|
||||
this._mgmt.handleFocus(data);
|
||||
break;
|
||||
|
||||
case 'System:Blur':
|
||||
this._mgmt.handleBlur(data);
|
||||
break;
|
||||
|
||||
case 'System:ShowAll':
|
||||
this._mgmt.dispatchShowAllRequestEvent();
|
||||
break;
|
||||
|
||||
case 'System:Next':
|
||||
this._mgmt.dispatchNextRequestEvent();
|
||||
break;
|
||||
|
||||
case 'System:InputRegistry:Add':
|
||||
this._mgmt.handleAddInput(data);
|
||||
break;
|
||||
|
||||
case 'System:InputRegistry:Remove':
|
||||
this._mgmt.handleRemoveInput(data);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -282,7 +552,7 @@ MozInputMethod.prototype = {
|
|||
},
|
||||
|
||||
get mgmt() {
|
||||
return this._mgmt;
|
||||
return this._wrappedMgmt;
|
||||
},
|
||||
|
||||
get inputcontext() {
|
||||
|
@ -320,8 +590,7 @@ MozInputMethod.prototype = {
|
|||
this._window.MozInputContext._create(this._window, this._inputcontext);
|
||||
}
|
||||
|
||||
let event = new this._window.Event("inputcontextchange",
|
||||
Cu.cloneInto({}, this._window));
|
||||
let event = new this._window.Event("inputcontextchange");
|
||||
this.__DOM_IMPL__.dispatchEvent(event);
|
||||
},
|
||||
|
||||
|
@ -344,9 +613,9 @@ MozInputMethod.prototype = {
|
|||
// we have to use a synchronous message
|
||||
var kbID = WindowMap.getKbID(this._window);
|
||||
if (kbID) {
|
||||
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:Register', {});
|
||||
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:RegisterSync', {});
|
||||
} else {
|
||||
let res = cpmm.sendSyncMessage('Keyboard:Register', {});
|
||||
let res = cpmm.sendSyncMessage('Keyboard:RegisterSync', {});
|
||||
WindowMap.setKbID(this._window, res[0]);
|
||||
}
|
||||
|
||||
|
@ -405,6 +674,13 @@ MozInputMethod.prototype = {
|
|||
|
||||
removeFocus: function() {
|
||||
cpmm.sendAsyncMessage('System:RemoveFocus', {});
|
||||
},
|
||||
|
||||
_hasInputManagePerm: function(win) {
|
||||
let principal = win.document.nodePrincipal;
|
||||
let perm = Services.perms.testExactPermissionFromPrincipal(principal,
|
||||
"input-manage");
|
||||
return (perm === Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1135,6 +1135,8 @@ function getJSON(element, focusCounter) {
|
|||
switch (inputTypeLowerCase) {
|
||||
case "datetime":
|
||||
case "datetime-local":
|
||||
case "month":
|
||||
case "week":
|
||||
case "range":
|
||||
inputType = inputTypeLowerCase;
|
||||
break;
|
||||
|
|
|
@ -4,7 +4,7 @@ skip-if = (toolkit == 'android' || toolkit == 'gonk') || e10s
|
|||
support-files =
|
||||
inputmethod_common.js
|
||||
file_inputmethod.html
|
||||
file_inputmethod_1043828.html
|
||||
file_blank.html
|
||||
file_test_app.html
|
||||
file_test_sendkey_cancel.html
|
||||
file_test_sms_app.html
|
||||
|
@ -22,8 +22,11 @@ support-files =
|
|||
[test_bug1066515.html]
|
||||
[test_bug1175399.html]
|
||||
[test_bug1137557.html]
|
||||
[test_focus_blur_manage_events.html]
|
||||
[test_input_registry_events.html]
|
||||
[test_sendkey_cancel.html]
|
||||
[test_setSupportsSwitching.html]
|
||||
[test_simple_manage_events.html]
|
||||
[test_sync_edit.html]
|
||||
[test_two_inputs.html]
|
||||
[test_two_selects.html]
|
||||
|
|
|
@ -84,7 +84,7 @@ function runTest() {
|
|||
document.body.appendChild(keyboardB);
|
||||
|
||||
// simulate two different keyboard apps
|
||||
let imeUrl = basePath + '/file_inputmethod_1043828.html';
|
||||
let imeUrl = basePath + '/file_blank.html';
|
||||
|
||||
SpecialPowers.pushPermissions([{
|
||||
type: 'input',
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1201407
|
||||
-->
|
||||
<head>
|
||||
<title>Test inputcontextfocus and inputcontextblur event</title>
|
||||
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1201407">Mozilla Bug 1201407</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
let contentFrameMM;
|
||||
|
||||
function setupTestRunner() {
|
||||
info('setupTestRunner');
|
||||
let im = navigator.mozInputMethod;
|
||||
|
||||
let expectedEventDetails = [
|
||||
{ type: 'input', inputType: 'text' },
|
||||
{ type: 'input', inputType: 'search' },
|
||||
{ type: 'textarea', inputType: 'textarea' },
|
||||
{ type: 'contenteditable', inputType: 'textarea' },
|
||||
{ type: 'input', inputType: 'number' },
|
||||
{ type: 'input', inputType: 'tel' },
|
||||
{ type: 'input', inputType: 'url' },
|
||||
{ type: 'input', inputType: 'email' },
|
||||
{ type: 'input', inputType: 'password' },
|
||||
{ type: 'input', inputType: 'datetime' },
|
||||
{ type: 'input', inputType: 'date',
|
||||
value: '2015-08-03', min: '1990-01-01', max: '2020-01-01' },
|
||||
{ type: 'input', inputType: 'month' },
|
||||
{ type: 'input', inputType: 'week' },
|
||||
{ type: 'input', inputType: 'time' },
|
||||
{ type: 'input', inputType: 'datetime-local' },
|
||||
{ type: 'input', inputType: 'color' },
|
||||
{ type: 'select', inputType: 'select-one',
|
||||
choices: {
|
||||
multiple: false,
|
||||
choices: [
|
||||
{ group: false, inGroup: false, text: 'foo',
|
||||
disabled: false, selected: true, optionIndex: 0 },
|
||||
{ group: false, inGroup: false, text: 'bar',
|
||||
disabled: true, selected: false, optionIndex: 1 },
|
||||
{ group: true, text: 'group', disabled: false },
|
||||
{ group: false, inGroup: true, text: 'baz',
|
||||
disabled: false, selected: false, optionIndex: 2 } ] }
|
||||
},
|
||||
{ type: 'select', inputType: 'select-multiple',
|
||||
choices: {
|
||||
multiple: true,
|
||||
choices: [
|
||||
{ group: false, inGroup: false, text: 'foo',
|
||||
disabled: false, selected: true, optionIndex: 0 },
|
||||
{ group: false, inGroup: false, text: 'bar',
|
||||
disabled: true, selected: false, optionIndex: 1 },
|
||||
{ group: true, text: 'group', disabled: false },
|
||||
{ group: false, inGroup: true, text: 'baz',
|
||||
disabled: false, selected: false, optionIndex: 2 } ] }
|
||||
}
|
||||
];
|
||||
|
||||
let expectBlur = false;
|
||||
|
||||
function deepAssertObject(obj, expectedObj, desc) {
|
||||
for (let prop in expectedObj) {
|
||||
if (typeof expectedObj[prop] === 'object') {
|
||||
deepAssertObject(obj[prop], expectedObj[prop], desc + '.' + prop);
|
||||
} else {
|
||||
is(obj[prop], expectedObj[prop], desc + '.' + prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
im.mgmt.oninputcontextfocus =
|
||||
im.mgmt.oninputcontextblur = function(evt) {
|
||||
if (expectBlur) {
|
||||
is(evt.type, 'inputcontextblur', 'evt.type');
|
||||
evt.preventDefault();
|
||||
expectBlur = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let expectedEventDetail = expectedEventDetails.shift();
|
||||
|
||||
if (!expectedEventDetail) {
|
||||
ok(false, 'Receving extra events');
|
||||
inputmethod_cleanup();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
is(evt.type, 'inputcontextfocus', 'evt.type');
|
||||
evt.preventDefault();
|
||||
expectBlur = true;
|
||||
|
||||
let detail = evt.detail;
|
||||
deepAssertObject(detail, expectedEventDetail, 'detail');
|
||||
|
||||
if (expectedEventDetails.length) {
|
||||
contentFrameMM.sendAsyncMessage('test:next');
|
||||
} else {
|
||||
im.mgmt.oninputcontextfocus = im.mgmt.oninputcontextblur = null;
|
||||
inputmethod_cleanup();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function setupInputAppFrame() {
|
||||
info('setupInputAppFrame');
|
||||
return new Promise((resolve, reject) => {
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let im = content.navigator.mozInputMethod;
|
||||
|
||||
im.mgmt.oninputcontextfocus =
|
||||
im.mgmt.oninputcontextblur = function(evt) {
|
||||
sendAsyncMessage('text:appEvent', { type: evt.type });
|
||||
};
|
||||
|
||||
content.document.body.textContent = 'I am a input app';
|
||||
};
|
||||
|
||||
let path = location.pathname;
|
||||
let basePath = location.protocol + '//' + location.host +
|
||||
path.substring(0, path.lastIndexOf('/'));
|
||||
let imeUrl = basePath + '/file_blank.html';
|
||||
|
||||
let inputAppFrame = document.createElement('iframe');
|
||||
inputAppFrame.setAttribute('mozbrowser', true);
|
||||
inputAppFrame.src = imeUrl;
|
||||
document.body.appendChild(inputAppFrame);
|
||||
|
||||
SpecialPowers.pushPermissions([{
|
||||
type: 'input',
|
||||
allow: true,
|
||||
context: {
|
||||
url: imeUrl,
|
||||
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||
isInBrowserElement: true
|
||||
}
|
||||
}], function() {
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(inputAppFrame);
|
||||
inputAppFrame.addEventListener('mozbrowserloadend', function() {
|
||||
mm.addMessageListener('text:appEvent', function(msg) {
|
||||
ok(false, 'Input app should not receive ' + msg.data.type + ' event.');
|
||||
});
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
|
||||
// Set the input app frame to be active
|
||||
let req = inputAppFrame.setInputMethodActive(true);
|
||||
resolve(req);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setupContentFrame() {
|
||||
info('setupContentFrame');
|
||||
return new Promise((resolve, reject) => {
|
||||
let contentFrameScript = function contentFrameScript() {
|
||||
let input = content.document.body.firstElementChild;
|
||||
|
||||
let i = 0;
|
||||
|
||||
input.focus();
|
||||
|
||||
addMessageListener('test:next', function() {
|
||||
content.document.body.children[++i].focus();
|
||||
});
|
||||
};
|
||||
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.src = 'data:text/html,<html><body>' +
|
||||
'<input type="text">' +
|
||||
'<input type="search">' +
|
||||
'<textarea></textarea>' +
|
||||
'<p contenteditable></p>' +
|
||||
'<input type="number">' +
|
||||
'<input type="tel">' +
|
||||
'<input type="url">' +
|
||||
'<input type="email">' +
|
||||
'<input type="password">' +
|
||||
'<input type="datetime">' +
|
||||
'<input type="date" value="2015-08-03" min="1990-01-01" max="2020-01-01">' +
|
||||
'<input type="month">' +
|
||||
'<input type="week">' +
|
||||
'<input type="time">' +
|
||||
'<input type="datetime-local">' +
|
||||
'<input type="color">' +
|
||||
'<select><option selected>foo</option><option disabled>bar</option>' +
|
||||
'<optgroup label="group"><option>baz</option></optgroup></select>' +
|
||||
'<select multiple><option selected>foo</option><option disabled>bar</option>' +
|
||||
'<optgroup label="group"><option>baz</option></optgroup></select>' +
|
||||
'</body></html>';
|
||||
iframe.setAttribute('mozbrowser', true);
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
let mm = contentFrameMM =
|
||||
SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', function() {
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(contentFrameScript.toString()) + ')();', false);
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
inputmethod_setup(function() {
|
||||
Promise.resolve()
|
||||
.then(() => setupTestRunner())
|
||||
.then(() => setupContentFrame())
|
||||
.then(() => setupInputAppFrame())
|
||||
.catch((e) => {
|
||||
ok(false, 'Error' + e.toString());
|
||||
console.error(e);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1201407
|
||||
-->
|
||||
<head>
|
||||
<title>Test addinputrequest and removeinputrequest event</title>
|
||||
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1201407">Mozilla Bug 1201407</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
let appFrameMM;
|
||||
let nextStep;
|
||||
|
||||
function setupInputAppFrame() {
|
||||
info('setupInputAppFrame');
|
||||
return new Promise((resolve, reject) => {
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let im = content.navigator.mozInputMethod;
|
||||
|
||||
addMessageListener('test:callAddInput', function() {
|
||||
im.addInput('foo', {
|
||||
launch_path: 'bar.html',
|
||||
name: 'Foo',
|
||||
description: 'foobar',
|
||||
types: ['text', 'password']
|
||||
})
|
||||
.then((r) => {
|
||||
sendAsyncMessage('test:resolved', { resolved: true, result: r });
|
||||
}, (e) => {
|
||||
sendAsyncMessage('test:rejected', { rejected: true, error: e });
|
||||
});
|
||||
});
|
||||
|
||||
addMessageListener('test:callRemoveInput', function() {
|
||||
im.removeInput('foo')
|
||||
.then((r) => {
|
||||
sendAsyncMessage('test:resolved', { resolved: true, result: r });
|
||||
}, (e) => {
|
||||
sendAsyncMessage('test:rejected', { rejected: true, error: e });
|
||||
});
|
||||
});
|
||||
|
||||
im.mgmt.onaddinputrequest =
|
||||
im.mgmt.onremoveinputrequest = function(evt) {
|
||||
sendAsyncMessage('test:appEvent', { type: evt.type });
|
||||
};
|
||||
|
||||
content.document.body.textContent = 'I am a input app';
|
||||
};
|
||||
|
||||
let path = location.pathname;
|
||||
let basePath = location.protocol + '//' + location.host +
|
||||
path.substring(0, path.lastIndexOf('/'));
|
||||
let imeUrl = basePath + '/file_blank.html';
|
||||
|
||||
let inputAppFrame = document.createElement('iframe');
|
||||
inputAppFrame.setAttribute('mozbrowser', true);
|
||||
inputAppFrame.src = imeUrl;
|
||||
document.body.appendChild(inputAppFrame);
|
||||
|
||||
SpecialPowers.pushPermissions([{
|
||||
type: 'input',
|
||||
allow: true,
|
||||
context: {
|
||||
url: imeUrl,
|
||||
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||
isInBrowserElement: true
|
||||
}
|
||||
}], function() {
|
||||
let mm = appFrameMM =
|
||||
SpecialPowers.getBrowserFrameMessageManager(inputAppFrame);
|
||||
|
||||
inputAppFrame.addEventListener('mozbrowserloadend', function() {
|
||||
mm.addMessageListener('test:appEvent', function(msg) {
|
||||
ok(false, 'Input app should not receive ' + msg.data.type + ' event.');
|
||||
});
|
||||
mm.addMessageListener('test:resolved', function(msg) {
|
||||
nextStep && nextStep(msg.data);
|
||||
});
|
||||
mm.addMessageListener('test:rejected', function(msg) {
|
||||
nextStep && nextStep(msg.data);
|
||||
});
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function Deferred() {
|
||||
this.promise = new Promise((res, rej) => {
|
||||
this.resolve = res;
|
||||
this.reject = rej;
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
function deepAssertObject(obj, expectedObj, desc) {
|
||||
for (let prop in expectedObj) {
|
||||
if (typeof expectedObj[prop] === 'object') {
|
||||
deepAssertObject(obj[prop], expectedObj[prop], desc + '.' + prop);
|
||||
} else {
|
||||
is(obj[prop], expectedObj[prop], desc + '.' + prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupTestRunner() {
|
||||
let im = navigator.mozInputMethod;
|
||||
let d;
|
||||
|
||||
let i = -1;
|
||||
nextStep = function next(evt) {
|
||||
i++;
|
||||
info('Step ' + i);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
appFrameMM.sendAsyncMessage('test:callAddInput');
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
is(evt.type, 'addinputrequest', 'evt.type');
|
||||
deepAssertObject(evt.detail, {
|
||||
inputId: 'foo',
|
||||
manifestURL: null, // todo
|
||||
inputManifest: {
|
||||
launch_path: 'bar.html',
|
||||
name: 'Foo',
|
||||
description: 'foobar',
|
||||
types: ['text', 'password']
|
||||
}
|
||||
}, 'detail');
|
||||
|
||||
d = new Deferred();
|
||||
evt.detail.waitUntil(d.promise);
|
||||
evt.preventDefault();
|
||||
|
||||
Promise.resolve().then(next);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
d.resolve();
|
||||
d = null;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ok(evt.resolved, 'resolved');
|
||||
appFrameMM.sendAsyncMessage('test:callAddInput');
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
is(evt.type, 'addinputrequest', 'evt.type');
|
||||
|
||||
d = new Deferred();
|
||||
evt.detail.waitUntil(d.promise);
|
||||
evt.preventDefault();
|
||||
|
||||
Promise.resolve().then(next);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
d.reject('Foo Error');
|
||||
d = null;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
ok(evt.rejected, 'rejected');
|
||||
is(evt.error, 'Foo Error', 'rejected');
|
||||
|
||||
|
||||
appFrameMM.sendAsyncMessage('test:callRemoveInput');
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
is(evt.type, 'removeinputrequest', 'evt.type');
|
||||
deepAssertObject(evt.detail, {
|
||||
inputId: 'foo',
|
||||
manifestURL: null // todo
|
||||
}, 'detail');
|
||||
|
||||
d = new Deferred();
|
||||
evt.detail.waitUntil(d.promise);
|
||||
evt.preventDefault();
|
||||
|
||||
Promise.resolve().then(next);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
d.resolve();
|
||||
d = null;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
ok(evt.resolved, 'resolved');
|
||||
appFrameMM.sendAsyncMessage('test:callRemoveInput');
|
||||
|
||||
break;
|
||||
|
||||
case 10:
|
||||
is(evt.type, 'removeinputrequest', 'evt.type');
|
||||
|
||||
d = new Deferred();
|
||||
evt.detail.waitUntil(d.promise);
|
||||
evt.preventDefault();
|
||||
|
||||
Promise.resolve().then(next);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
d.reject('Foo Error');
|
||||
d = null;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
ok(evt.rejected, 'rejected');
|
||||
is(evt.error, 'Foo Error', 'rejected');
|
||||
inputmethod_cleanup();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ok(false, 'received extra call.');
|
||||
inputmethod_cleanup();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
im.mgmt.onaddinputrequest =
|
||||
im.mgmt.onremoveinputrequest = nextStep;
|
||||
}
|
||||
|
||||
inputmethod_setup(function() {
|
||||
Promise.resolve()
|
||||
.then(() => setupTestRunner())
|
||||
.then(() => setupInputAppFrame())
|
||||
.then(() => nextStep())
|
||||
.catch((e) => {
|
||||
ok(false, 'Error' + e.toString());
|
||||
console.error(e);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,164 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1201407
|
||||
-->
|
||||
<head>
|
||||
<title>Test simple manage notification events on MozInputMethodManager</title>
|
||||
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1201407">Mozilla Bug 1201407</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
let appFrameMM;
|
||||
let nextStep;
|
||||
|
||||
function setupTestRunner() {
|
||||
info('setupTestRunner');
|
||||
let im = navigator.mozInputMethod;
|
||||
|
||||
let i = 0;
|
||||
im.mgmt.onshowallrequest =
|
||||
im.mgmt.onnextrequest = nextStep = function(evt) {
|
||||
i++;
|
||||
switch (i) {
|
||||
case 1:
|
||||
is(evt.type, 'inputcontextchange', '1) inputcontextchange event');
|
||||
appFrameMM.sendAsyncMessage('test:callShowAll');
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
is(evt.type, 'showallrequest', '2) showallrequest event');
|
||||
ok(evt.target, im.mgmt, '2) evt.target');
|
||||
evt.preventDefault();
|
||||
|
||||
appFrameMM.sendAsyncMessage('test:callNext');
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
is(evt.type, 'nextrequest', '3) nextrequest event');
|
||||
ok(evt.target, im.mgmt, '3) evt.target');
|
||||
evt.preventDefault();
|
||||
|
||||
im.mgmt.onshowallrequest =
|
||||
im.mgmt.onnextrequest = nextStep = null;
|
||||
|
||||
inputmethod_cleanup();
|
||||
break;
|
||||
|
||||
default:
|
||||
ok(false, 'Receving extra events');
|
||||
inputmethod_cleanup();
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function setupInputAppFrame() {
|
||||
info('setupInputAppFrame');
|
||||
return new Promise((resolve, reject) => {
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let im = content.navigator.mozInputMethod;
|
||||
|
||||
addMessageListener('test:callShowAll', function() {
|
||||
im.mgmt.showAll();
|
||||
});
|
||||
|
||||
addMessageListener('test:callNext', function() {
|
||||
im.mgmt.next();
|
||||
});
|
||||
|
||||
im.mgmt.onshowallrequest =
|
||||
im.mgmt.onnextrequest = function(evt) {
|
||||
sendAsyncMessage('test:appEvent', { type: evt.type });
|
||||
};
|
||||
|
||||
im.oninputcontextchange = function(evt) {
|
||||
sendAsyncMessage('test:inputcontextchange', {});
|
||||
};
|
||||
|
||||
content.document.body.textContent = 'I am a input app';
|
||||
};
|
||||
|
||||
let path = location.pathname;
|
||||
let basePath = location.protocol + '//' + location.host +
|
||||
path.substring(0, path.lastIndexOf('/'));
|
||||
let imeUrl = basePath + '/file_blank.html';
|
||||
|
||||
let inputAppFrame = document.createElement('iframe');
|
||||
inputAppFrame.setAttribute('mozbrowser', true);
|
||||
inputAppFrame.src = imeUrl;
|
||||
document.body.appendChild(inputAppFrame);
|
||||
|
||||
SpecialPowers.pushPermissions([{
|
||||
type: 'input',
|
||||
allow: true,
|
||||
context: {
|
||||
url: imeUrl,
|
||||
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||
isInBrowserElement: true
|
||||
}
|
||||
}], function() {
|
||||
let mm = appFrameMM =
|
||||
SpecialPowers.getBrowserFrameMessageManager(inputAppFrame);
|
||||
|
||||
inputAppFrame.addEventListener('mozbrowserloadend', function() {
|
||||
mm.addMessageListener('test:appEvent', function(msg) {
|
||||
ok(false, 'Input app should not receive ' + msg.data.type + ' event.');
|
||||
});
|
||||
mm.addMessageListener('test:inputcontextchange', function(msg) {
|
||||
nextStep && nextStep({ type: 'inputcontextchange' });
|
||||
});
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
|
||||
// Set the input app frame to be active
|
||||
let req = inputAppFrame.setInputMethodActive(true);
|
||||
resolve(req);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setupContentFrame() {
|
||||
let contentFrameScript = function contentFrameScript() {
|
||||
let input = content.document.body.firstElementChild;
|
||||
|
||||
input.focus();
|
||||
};
|
||||
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.src = 'data:text/html,<html><body><input type="text"></body></html>';
|
||||
iframe.setAttribute('mozbrowser', true);
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', function() {
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(contentFrameScript.toString()) + ')();', false);
|
||||
});
|
||||
}
|
||||
|
||||
inputmethod_setup(function() {
|
||||
Promise.resolve()
|
||||
.then(() => setupTestRunner())
|
||||
.then(() => setupContentFrame())
|
||||
.then(() => setupInputAppFrame())
|
||||
.catch((e) => {
|
||||
ok(false, 'Error' + e.toString());
|
||||
console.error(e);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef FrameStatistics_h_
|
||||
#define FrameStatistics_h_
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Frame decoding/painting related performance counters.
|
||||
// Threadsafe.
|
||||
class FrameStatistics {
|
||||
public:
|
||||
FrameStatistics() :
|
||||
mReentrantMonitor("FrameStats"),
|
||||
mParsedFrames(0),
|
||||
mDecodedFrames(0),
|
||||
mPresentedFrames(0),
|
||||
mDroppedFrames(0),
|
||||
mCorruptFrames(0) {}
|
||||
|
||||
// Returns number of frames which have been parsed from the media.
|
||||
// Can be called on any thread.
|
||||
uint32_t GetParsedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mParsedFrames;
|
||||
}
|
||||
|
||||
// Returns the number of parsed frames which have been decoded.
|
||||
// Can be called on any thread.
|
||||
uint32_t GetDecodedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mDecodedFrames;
|
||||
}
|
||||
|
||||
// Returns the number of decoded frames which have been sent to the rendering
|
||||
// pipeline for painting ("presented").
|
||||
// Can be called on any thread.
|
||||
uint32_t GetPresentedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mPresentedFrames;
|
||||
}
|
||||
|
||||
// Number of frames that have been skipped because they have missed their
|
||||
// compoisition deadline.
|
||||
uint32_t GetDroppedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mDroppedFrames + mCorruptFrames;
|
||||
}
|
||||
|
||||
uint32_t GetCorruptedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mCorruptFrames;
|
||||
}
|
||||
|
||||
// Increments the parsed and decoded frame counters by the passed in counts.
|
||||
// Can be called on any thread.
|
||||
void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded,
|
||||
uint32_t aDropped) {
|
||||
if (aParsed == 0 && aDecoded == 0 && aDropped == 0)
|
||||
return;
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mParsedFrames += aParsed;
|
||||
mDecodedFrames += aDecoded;
|
||||
mDroppedFrames += aDropped;
|
||||
}
|
||||
|
||||
// Increments the presented frame counters.
|
||||
// Can be called on any thread.
|
||||
void NotifyPresentedFrame() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
++mPresentedFrames;
|
||||
}
|
||||
|
||||
void NotifyCorruptFrame() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
++mCorruptFrames;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// ReentrantMonitor to protect access of playback statistics.
|
||||
ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
// Number of frames parsed and demuxed from media.
|
||||
// Access protected by mReentrantMonitor.
|
||||
uint32_t mParsedFrames;
|
||||
|
||||
// Number of parsed frames which were actually decoded.
|
||||
// Access protected by mReentrantMonitor.
|
||||
uint32_t mDecodedFrames;
|
||||
|
||||
// Number of decoded frames which were actually sent down the rendering
|
||||
// pipeline to be painted ("presented"). Access protected by mReentrantMonitor.
|
||||
uint32_t mPresentedFrames;
|
||||
|
||||
uint32_t mDroppedFrames;
|
||||
|
||||
uint32_t mCorruptFrames;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -203,6 +203,7 @@ destroying the MediaDecoder object.
|
|||
#include "nsITimer.h"
|
||||
|
||||
#include "AbstractMediaDecoder.h"
|
||||
#include "FrameStatistics.h"
|
||||
#include "MediaDecoderOwner.h"
|
||||
#include "MediaEventSource.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
|
@ -721,99 +722,6 @@ public:
|
|||
// at any time.
|
||||
MediaStatistics GetStatistics();
|
||||
|
||||
// Frame decoding/painting related performance counters.
|
||||
// Threadsafe.
|
||||
class FrameStatistics {
|
||||
public:
|
||||
|
||||
FrameStatistics() :
|
||||
mReentrantMonitor("MediaDecoder::FrameStats"),
|
||||
mParsedFrames(0),
|
||||
mDecodedFrames(0),
|
||||
mPresentedFrames(0),
|
||||
mDroppedFrames(0),
|
||||
mCorruptFrames(0) {}
|
||||
|
||||
// Returns number of frames which have been parsed from the media.
|
||||
// Can be called on any thread.
|
||||
uint32_t GetParsedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mParsedFrames;
|
||||
}
|
||||
|
||||
// Returns the number of parsed frames which have been decoded.
|
||||
// Can be called on any thread.
|
||||
uint32_t GetDecodedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mDecodedFrames;
|
||||
}
|
||||
|
||||
// Returns the number of decoded frames which have been sent to the rendering
|
||||
// pipeline for painting ("presented").
|
||||
// Can be called on any thread.
|
||||
uint32_t GetPresentedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mPresentedFrames;
|
||||
}
|
||||
|
||||
// Number of frames that have been skipped because they have missed their
|
||||
// compoisition deadline.
|
||||
uint32_t GetDroppedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mDroppedFrames + mCorruptFrames;
|
||||
}
|
||||
|
||||
uint32_t GetCorruptedFrames() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mCorruptFrames;
|
||||
}
|
||||
|
||||
// Increments the parsed and decoded frame counters by the passed in counts.
|
||||
// Can be called on any thread.
|
||||
void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded,
|
||||
uint32_t aDropped) {
|
||||
if (aParsed == 0 && aDecoded == 0 && aDropped == 0)
|
||||
return;
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mParsedFrames += aParsed;
|
||||
mDecodedFrames += aDecoded;
|
||||
mDroppedFrames += aDropped;
|
||||
}
|
||||
|
||||
// Increments the presented frame counters.
|
||||
// Can be called on any thread.
|
||||
void NotifyPresentedFrame() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
++mPresentedFrames;
|
||||
}
|
||||
|
||||
void NotifyCorruptFrame() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
++mCorruptFrames;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// ReentrantMonitor to protect access of playback statistics.
|
||||
ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
// Number of frames parsed and demuxed from media.
|
||||
// Access protected by mReentrantMonitor.
|
||||
uint32_t mParsedFrames;
|
||||
|
||||
// Number of parsed frames which were actually decoded.
|
||||
// Access protected by mReentrantMonitor.
|
||||
uint32_t mDecodedFrames;
|
||||
|
||||
// Number of decoded frames which were actually sent down the rendering
|
||||
// pipeline to be painted ("presented"). Access protected by mReentrantMonitor.
|
||||
uint32_t mPresentedFrames;
|
||||
|
||||
uint32_t mDroppedFrames;
|
||||
|
||||
uint32_t mCorruptFrames;
|
||||
};
|
||||
|
||||
// Return the frame decode/paint related statistics.
|
||||
FrameStatistics& GetFrameStatistics() { return mFrameStats; }
|
||||
|
||||
|
|
|
@ -2498,7 +2498,7 @@ bool MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData)
|
|||
|
||||
// Update corrupt-frames statistics
|
||||
if (aData->mImage && !aData->mImage->IsValid()) {
|
||||
MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
|
||||
FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
|
||||
frameStats.NotifyCorruptFrame();
|
||||
// If more than 10% of the last 30 frames have been corrupted, then try disabling
|
||||
// hardware acceleration. We use 10 as the corrupt value because RollingMean<>
|
||||
|
@ -2635,7 +2635,7 @@ void MediaDecoderStateMachine::UpdateRenderedVideoFrames()
|
|||
VideoQueue().PushFront(currentFrame);
|
||||
if (framesRemoved > 0) {
|
||||
mVideoFrameEndTime = currentFrame->GetEndTime();
|
||||
MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
|
||||
FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
|
||||
frameStats.NotifyPresentedFrame();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/PeerIdentity.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
@ -1579,6 +1580,16 @@ nsresult MediaManager::GenerateUUID(nsAString& aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
enum class GetUserMediaSecurityState {
|
||||
Other = 0,
|
||||
HTTPS = 1,
|
||||
File = 2,
|
||||
App = 3,
|
||||
Localhost = 4,
|
||||
Loop = 5,
|
||||
Privileged = 6
|
||||
};
|
||||
|
||||
/**
|
||||
* The entry point for this file. A call from Navigator::mozGetUserMedia
|
||||
* will end up here. MediaManager is a singleton that is responsible
|
||||
|
@ -1630,9 +1641,47 @@ MediaManager::GetUserMedia(nsPIDOMWindow* aWindow,
|
|||
bool privileged = loop || IsPrivileged();
|
||||
bool isHTTPS = false;
|
||||
docURI->SchemeIs("https", &isHTTPS);
|
||||
nsCString host;
|
||||
nsresult rv = docURI->GetHost(host);
|
||||
// Test for some other schemes that ServiceWorker recognizes
|
||||
bool isFile;
|
||||
docURI->SchemeIs("file", &isFile);
|
||||
bool isApp;
|
||||
docURI->SchemeIs("app", &isApp);
|
||||
// Same localhost check as ServiceWorkers uses
|
||||
// (see IsFromAuthenticatedOriginInternal())
|
||||
bool isLocalhost = NS_SUCCEEDED(rv) &&
|
||||
(host.LowerCaseEqualsLiteral("localhost") ||
|
||||
host.LowerCaseEqualsLiteral("127.0.0.1") ||
|
||||
host.LowerCaseEqualsLiteral("::1"));
|
||||
|
||||
// Record telemetry about whether the source of the call was secure, i.e.,
|
||||
// privileged or HTTPS. We may handle other cases
|
||||
if (loop) {
|
||||
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_SECURE_ORIGIN,
|
||||
(uint32_t) GetUserMediaSecurityState::Loop);
|
||||
} else if (privileged) {
|
||||
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_SECURE_ORIGIN,
|
||||
(uint32_t) GetUserMediaSecurityState::Privileged);
|
||||
} else if (isHTTPS) {
|
||||
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_SECURE_ORIGIN,
|
||||
(uint32_t) GetUserMediaSecurityState::HTTPS);
|
||||
} else if (isFile) {
|
||||
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_SECURE_ORIGIN,
|
||||
(uint32_t) GetUserMediaSecurityState::File);
|
||||
} else if (isApp) {
|
||||
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_SECURE_ORIGIN,
|
||||
(uint32_t) GetUserMediaSecurityState::App);
|
||||
} else if (isLocalhost) {
|
||||
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_SECURE_ORIGIN,
|
||||
(uint32_t) GetUserMediaSecurityState::Localhost);
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_SECURE_ORIGIN,
|
||||
(uint32_t) GetUserMediaSecurityState::Other);
|
||||
}
|
||||
|
||||
nsCString origin;
|
||||
nsresult rv = nsPrincipal::GetOriginForURI(docURI, origin);
|
||||
rv = nsPrincipal::GetOriginForURI(docURI, origin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ EXPORTS += [
|
|||
'EncodedBufferCache.h',
|
||||
'FileBlockCache.h',
|
||||
'FlushableTaskQueue.h',
|
||||
'FrameStatistics.h',
|
||||
'Intervals.h',
|
||||
'Latency.h',
|
||||
'MediaCache.h',
|
||||
|
|
|
@ -472,9 +472,9 @@ nsresult OggReader::ReadMetadata(MediaInfo* aInfo,
|
|||
if (HasAudio() || HasVideo()) {
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
if (mInfo.mMetadataDuration.isNothing() && !mDecoder->IsOggDecoderShutdown() &&
|
||||
mResource.GetLength() >= 0 && mDecoder->IsMediaSeekable())
|
||||
{
|
||||
if (mInfo.mMetadataDuration.isNothing() &&
|
||||
!mDecoder->IsOggDecoderShutdown() &&
|
||||
mResource.GetLength() >= 0) {
|
||||
// We didn't get a duration from the index or a Content-Duration header.
|
||||
// Seek to the end of file to find the end time.
|
||||
int64_t length = mResource.GetLength();
|
||||
|
|
|
@ -545,6 +545,7 @@ DeallocPMediaParent(media::PMediaParent *aActor)
|
|||
{
|
||||
MOZ_ASSERT(sIPCServingParent == static_cast<Parent<PMediaParent>*>(aActor));
|
||||
delete sIPCServingParent;
|
||||
sIPCServingParent = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "1087551",
|
||||
title: "addCandidate behavior in different states"
|
||||
title: "addIceCandidate behavior (local and remote) including invalid data"
|
||||
});
|
||||
|
||||
var test;
|
||||
|
@ -71,6 +71,28 @@
|
|||
sdpMLineIndex: 0});
|
||||
return test.pcRemote._pc.addIceCandidate(candidate)
|
||||
.then(ok(true, "Successfully added valid ICE candidate"));
|
||||
},
|
||||
// bug 1095793
|
||||
function PC_REMOTE_ADD_MISMATCHED_MID_AND_LEVEL_CANDIDATE(test) {
|
||||
var bogus = new mozRTCIceCandidate(
|
||||
{candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
|
||||
sdpMLineIndex: 0,
|
||||
sdpMid: "sdparta_1"});
|
||||
return test.pcRemote._pc.addIceCandidate(bogus)
|
||||
.then(
|
||||
generateErrorCallback("addIceCandidate should have failed."),
|
||||
err => {
|
||||
is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError");
|
||||
}
|
||||
);
|
||||
},
|
||||
function PC_REMOTE_ADD_MATCHING_MID_AND_LEVEL_CANDIDATE(test) {
|
||||
var candidate = new mozRTCIceCandidate(
|
||||
{candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
|
||||
sdpMLineIndex: 0,
|
||||
sdpMid: "sdparta_0"});
|
||||
return test.pcRemote._pc.addIceCandidate(candidate)
|
||||
.then(ok(true, "Successfully added valid ICE candidate with matching mid and level"));
|
||||
}
|
||||
]);
|
||||
test.run();
|
||||
|
|
|
@ -20,6 +20,7 @@ dictionary CaretStateChangedEventInit : EventInit {
|
|||
boolean caretVisible = false;
|
||||
boolean selectionVisible = false;
|
||||
boolean selectionEditable = false;
|
||||
DOMString selectedTextContent = "";
|
||||
};
|
||||
|
||||
[Constructor(DOMString type, optional CaretStateChangedEventInit eventInit),
|
||||
|
@ -31,4 +32,5 @@ interface CaretStateChangedEvent : Event {
|
|||
readonly attribute boolean caretVisible;
|
||||
readonly attribute boolean selectionVisible;
|
||||
readonly attribute boolean selectionEditable;
|
||||
readonly attribute DOMString selectedTextContent;
|
||||
};
|
||||
|
|
|
@ -120,7 +120,7 @@ interface MozInputMethod : EventTarget {
|
|||
[JSImplementation="@mozilla.org/b2g-imm;1",
|
||||
Pref="dom.mozInputMethod.enabled",
|
||||
CheckAnyPermissions="input input-manage"]
|
||||
interface MozInputMethodManager {
|
||||
interface MozInputMethodManager : EventTarget {
|
||||
/**
|
||||
* Ask the OS to show a list of available inputs for users to switch from.
|
||||
* OS should sliently ignore this request if the app is currently not the
|
||||
|
@ -165,6 +165,149 @@ interface MozInputMethodManager {
|
|||
*/
|
||||
[CheckAllPermissions="input-manage"]
|
||||
void setSupportsSwitchingTypes(sequence<MozInputMethodInputContextInputTypes> types);
|
||||
|
||||
/**
|
||||
* CustomEvent dispatches to System when there is an input to handle.
|
||||
* If the API consumer failed to handle and call preventDefault(),
|
||||
* there will be a message printed on the console.
|
||||
*
|
||||
* evt.detail is defined by MozInputContextFocusEventDetail.
|
||||
*/
|
||||
[CheckAnyPermissions="input-manage"]
|
||||
attribute EventHandler oninputcontextfocus;
|
||||
|
||||
/**
|
||||
* Event dispatches to System when there is no longer an input to handle.
|
||||
* If the API consumer failed to handle and call preventDefault(),
|
||||
* there will be a message printed on the console.
|
||||
*/
|
||||
[CheckAnyPermissions="input-manage"]
|
||||
attribute EventHandler oninputcontextblur;
|
||||
|
||||
/**
|
||||
* Event dispatches to System when there is a showAll() call.
|
||||
* If the API consumer failed to handle and call preventDefault(),
|
||||
* there will be a message printed on the console.
|
||||
*/
|
||||
[CheckAnyPermissions="input-manage"]
|
||||
attribute EventHandler onshowallrequest;
|
||||
|
||||
/**
|
||||
* Event dispatches to System when there is a next() call.
|
||||
* If the API consumer failed to handle and call preventDefault(),
|
||||
* there will be a message printed on the console.
|
||||
*/
|
||||
[CheckAnyPermissions="input-manage"]
|
||||
attribute EventHandler onnextrequest;
|
||||
|
||||
/**
|
||||
* Event dispatches to System when there is a addInput() call.
|
||||
* The API consumer must call preventDefault() to indicate the event is
|
||||
* consumed, otherwise the request is not considered handled even if
|
||||
* waitUntil() was called.
|
||||
*
|
||||
* evt.detail is defined by MozInputRegistryEventDetail.
|
||||
*/
|
||||
[CheckAnyPermissions="input-manage"]
|
||||
attribute EventHandler onaddinputrequest;
|
||||
|
||||
/**
|
||||
* Event dispatches to System when there is a removeInput() call.
|
||||
* The API consumer must call preventDefault() to indicate the event is
|
||||
* consumed, otherwise the request is not considered handled even if
|
||||
* waitUntil() was called.
|
||||
*
|
||||
* evt.detail is defined by MozInputRegistryEventDetail.
|
||||
*/
|
||||
[CheckAnyPermissions="input-manage"]
|
||||
attribute EventHandler onremoveinputrequest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Detail of the inputcontextfocus event.
|
||||
*/
|
||||
[JSImplementation="@mozilla.org/b2g-imm-focus;1",
|
||||
Pref="dom.mozInputMethod.enabled",
|
||||
CheckAnyPermissions="input-manage"]
|
||||
interface MozInputContextFocusEventDetail {
|
||||
/**
|
||||
* The type of the focused input.
|
||||
*/
|
||||
readonly attribute MozInputMethodInputContextTypes type;
|
||||
/**
|
||||
* The input type of the focused input.
|
||||
*/
|
||||
readonly attribute MozInputMethodInputContextInputTypes inputType;
|
||||
|
||||
/**
|
||||
* The following is only needed for rendering and handling "option" input types,
|
||||
* in System app.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Current value of the input/select element.
|
||||
*/
|
||||
readonly attribute DOMString? value;
|
||||
/**
|
||||
* An object representing all the <optgroup> and <option> elements
|
||||
* in the <select> element.
|
||||
*/
|
||||
[Pure, Cached, Frozen]
|
||||
readonly attribute MozInputContextChoicesInfo? choices;
|
||||
/**
|
||||
* Max/min value of <input>
|
||||
*/
|
||||
readonly attribute DOMString? min;
|
||||
readonly attribute DOMString? max;
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about the options within the <select> element.
|
||||
*/
|
||||
dictionary MozInputContextChoicesInfo {
|
||||
boolean multiple;
|
||||
sequence<MozInputMethodChoiceDict> choices;
|
||||
};
|
||||
|
||||
/**
|
||||
* Content the header (<optgroup>) or an option (<option>).
|
||||
*/
|
||||
dictionary MozInputMethodChoiceDict {
|
||||
boolean group;
|
||||
DOMString text;
|
||||
boolean disabled;
|
||||
boolean? inGroup;
|
||||
boolean? selected;
|
||||
long? optionIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* detail of addinputrequest or removeinputrequest event.
|
||||
*/
|
||||
[JSImplementation="@mozilla.org/b2g-imm-input-registry;1",
|
||||
Pref="dom.mozInputMethod.enabled",
|
||||
CheckAnyPermissions="input-manage"]
|
||||
interface MozInputRegistryEventDetail {
|
||||
/**
|
||||
* Manifest URL of the requesting app.
|
||||
*/
|
||||
readonly attribute DOMString manifestURL;
|
||||
/**
|
||||
* ID of the input
|
||||
*/
|
||||
readonly attribute DOMString inputId;
|
||||
/**
|
||||
* Input manifest of the input to add.
|
||||
* Null for removeinputrequest event.
|
||||
*/
|
||||
[Pure, Cached, Frozen]
|
||||
readonly attribute MozInputMethodInputManifest? inputManifest;
|
||||
/**
|
||||
* Resolve or Reject the addInput() or removeInput() call when the passed
|
||||
* promises are resolved.
|
||||
*/
|
||||
[Throws]
|
||||
void waitUntil(Promise<any> p);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -397,19 +540,20 @@ dictionary CompositionClauseParameters {
|
|||
* *and* the special keyword "contenteditable" for contenteditable element.
|
||||
*/
|
||||
enum MozInputMethodInputContextTypes {
|
||||
"input", "textarea", "contenteditable"
|
||||
"input", "textarea", "contenteditable",
|
||||
/**
|
||||
* <select> is managed by the API but it's not exposed through InputContext
|
||||
* yet.
|
||||
* <select> is managed by the API but it is handled by the System app only,
|
||||
* so this value is only accessible by System app from inputcontextfocus event.
|
||||
*/
|
||||
// "select"
|
||||
"select"
|
||||
};
|
||||
|
||||
/**
|
||||
* InputTypes of the input that InputContext is representing. The value
|
||||
* is inferred from the type attribute of input element.
|
||||
* is inferred from the type attribute of element.
|
||||
*
|
||||
* See https://html.spec.whatwg.org/multipage/forms.html#states-of-the-type-attribute
|
||||
* for types of HTMLInputElement.
|
||||
*
|
||||
* They are divided into groups -- an layout/input capable of handling one type
|
||||
* in the group is considered as capable of handling all of the types in the
|
||||
|
@ -444,12 +588,15 @@ enum MozInputMethodInputContextInputTypes {
|
|||
* Group "password".
|
||||
* An non-Latin alphabet layout/input should not be able to handle this type.
|
||||
*/
|
||||
"password"
|
||||
"password",
|
||||
/**
|
||||
* Group "option". These types are handled by System app itself currently, and
|
||||
* not exposed and allowed to handled with input context.
|
||||
* Group "option". These types are handled by System app itself currently, so
|
||||
* no input app will be set to active for these input types.
|
||||
* System app access these types from inputcontextfocus event.
|
||||
* ("select-one" and "select-multiple" are valid HTMLSelectElement#type.)
|
||||
*/
|
||||
//"datetime", "date", "month", "week", "time", "datetime-local", "color",
|
||||
"datetime", "date", "month", "week", "time", "datetime-local", "color",
|
||||
"select-one", "select-multiple"
|
||||
/**
|
||||
* These types are ignored by the API even though they are valid
|
||||
* HTMLInputElement#type.
|
||||
|
|
|
@ -162,6 +162,8 @@ support-files =
|
|||
eventsource/*
|
||||
sw_clients/file_blob_upload_frame.html
|
||||
redirect_post.sjs
|
||||
xslt_worker.js
|
||||
xslt/*
|
||||
|
||||
[test_app_protocol.html]
|
||||
skip-if = release_build
|
||||
|
@ -250,6 +252,7 @@ skip-if = toolkit == "android" || toolkit == "gonk"
|
|||
[test_workerupdatefoundevent.html]
|
||||
[test_opaque_intercept.html]
|
||||
[test_fetch_event_client_postmessage.html]
|
||||
[test_xslt.html]
|
||||
[test_escapedSlashes.html]
|
||||
[test_eventsource_intercept.html]
|
||||
[test_not_intercept_plugin.html]
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1182113 - Test service worker XSLT interception</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content"></div>
|
||||
<pre id="test"></pre>
|
||||
<script class="testbody" type="text/javascript">
|
||||
var registration;
|
||||
var worker;
|
||||
|
||||
function start() {
|
||||
return navigator.serviceWorker.register("xslt_worker.js",
|
||||
{ scope: "./" })
|
||||
.then((swr) => registration = swr);
|
||||
}
|
||||
|
||||
function unregister() {
|
||||
return registration.unregister().then(function(result) {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
}
|
||||
|
||||
function getXmlString(xmlObject) {
|
||||
serializer = new XMLSerializer();
|
||||
return serializer.serializeToString(iframe.contentDocument);
|
||||
}
|
||||
|
||||
function synthetic() {
|
||||
content = document.getElementById("content");
|
||||
ok(content, "parent exists.");
|
||||
|
||||
iframe = document.createElement("iframe");
|
||||
content.appendChild(iframe);
|
||||
|
||||
iframe.setAttribute('src', "xslt/test.xml");
|
||||
|
||||
var p = new Promise(function(res, rej) {
|
||||
iframe.onload = function(e) {
|
||||
dump("Set request mode\n");
|
||||
registration.active.postMessage("synthetic");
|
||||
xmlString = getXmlString(iframe.contentDocument);
|
||||
ok(!xmlString.includes("Error"), "Load synthetic cross origin XSLT should be allowed");
|
||||
res();
|
||||
};
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
function cors() {
|
||||
var p = new Promise(function(res, rej) {
|
||||
iframe.onload = function(e) {
|
||||
xmlString = getXmlString(iframe.contentDocument);
|
||||
ok(!xmlString.includes("Error"), "Load CORS cross origin XSLT should be allowed");
|
||||
res();
|
||||
};
|
||||
});
|
||||
|
||||
registration.active.postMessage("cors");
|
||||
iframe.setAttribute('src', "xslt/test.xml");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
function opaque() {
|
||||
var p = new Promise(function(res, rej) {
|
||||
iframe.onload = function(e) {
|
||||
xmlString = getXmlString(iframe.contentDocument);
|
||||
ok(xmlString.includes("Error"), "Load opaque cross origin XSLT should not be allowed");
|
||||
res();
|
||||
};
|
||||
});
|
||||
|
||||
registration.active.postMessage("opaque");
|
||||
iframe.setAttribute('src', "xslt/test.xml");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
start()
|
||||
.then(synthetic)
|
||||
.then(opaque)
|
||||
.then(cors)
|
||||
.then(unregister)
|
||||
.catch(function(e) {
|
||||
ok(false, "Some test failed with error " + e);
|
||||
}).then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.interception.enabled", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
]}, runTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
|
||||
<result>
|
||||
<Title>Example</Title>
|
||||
<Error>Error</Error>
|
||||
</result>
|
|
@ -0,0 +1,12 @@
|
|||
function handleRequest(request, response) {
|
||||
response.setHeader("Content-Type", "application/xslt+xml", false);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
|
||||
var body = request.queryString;
|
||||
if (!body) {
|
||||
response.setStatusLine(null, 500, "Invalid querystring");
|
||||
return;
|
||||
}
|
||||
|
||||
response.write(unescape(body));
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
var testType = 'synthetic';
|
||||
|
||||
var xslt = "<?xml version=\"1.0\"?> " +
|
||||
"<xsl:stylesheet version=\"1.0\"" +
|
||||
" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
|
||||
" <xsl:template match=\"node()|@*\">" +
|
||||
" <xsl:copy>" +
|
||||
" <xsl:apply-templates select=\"node()|@*\"/>" +
|
||||
" </xsl:copy>" +
|
||||
" </xsl:template>" +
|
||||
" <xsl:template match=\"Error\"/>" +
|
||||
"</xsl:stylesheet>";
|
||||
|
||||
onfetch = function(event) {
|
||||
if (event.request.url.includes('test.xsl')) {
|
||||
if (testType == 'synthetic') {
|
||||
if (event.request.mode != 'cors') {
|
||||
event.respondWith(Response.error());
|
||||
return;
|
||||
}
|
||||
|
||||
event.respondWith(Promise.resolve(
|
||||
new Response(xslt, { headers: {'Content-Type': 'application/xslt+xml'}})
|
||||
));
|
||||
}
|
||||
else if (testType == 'cors') {
|
||||
if (event.request.mode != 'cors') {
|
||||
event.respondWith(Response.error());
|
||||
return;
|
||||
}
|
||||
|
||||
var url = "http://example.com/tests/dom/workers/test/serviceworkers/xslt/xslt.sjs?" + escape(xslt);
|
||||
event.respondWith(fetch(url, { mode: 'cors' }));
|
||||
}
|
||||
else if (testType == 'opaque') {
|
||||
if (event.request.mode != 'cors') {
|
||||
event.respondWith(Response.error());
|
||||
return;
|
||||
}
|
||||
|
||||
var url = "http://example.com/tests/dom/workers/test/serviceworkers/xslt/xslt.sjs?" + escape(xslt);
|
||||
event.respondWith(fetch(url, { mode: 'no-cors' }));
|
||||
}
|
||||
else {
|
||||
event.respondWith(Response.error());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onmessage = function(event) {
|
||||
testType = event.data;
|
||||
};
|
|
@ -1688,7 +1688,7 @@ static void
|
|||
DrawPaintedLayer(PaintedLayer* aLayer,
|
||||
gfxContext* aContext,
|
||||
const nsIntRegion& aRegionToDraw,
|
||||
const nsIntRegion* aDirtyRegion,
|
||||
const nsIntRegion& aDirtyRegion,
|
||||
DrawRegionClip aClip,
|
||||
const nsIntRegion& aRegionToInvalidate,
|
||||
void* aCallbackData)
|
||||
|
|
|
@ -316,6 +316,7 @@ GLContext::GLContext(const SurfaceCaps& caps,
|
|||
mMaxTextureImageSize(0),
|
||||
mMaxRenderbufferSize(0),
|
||||
mNeedsTextureSizeChecks(false),
|
||||
mNeedsFlushBeforeDeleteFB(false),
|
||||
mWorkAroundDriverBugs(true),
|
||||
mHeavyGLCallsSinceLastFlush(false)
|
||||
{
|
||||
|
@ -616,6 +617,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
"Adreno (TM) 200",
|
||||
"Adreno (TM) 205",
|
||||
"Adreno (TM) 320",
|
||||
"Adreno (TM) 420",
|
||||
"PowerVR SGX 530",
|
||||
"PowerVR SGX 540",
|
||||
"NVIDIA Tegra",
|
||||
|
@ -1607,6 +1609,12 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
mNeedsTextureSizeChecks = true;
|
||||
}
|
||||
#endif
|
||||
if (mWorkAroundDriverBugs &&
|
||||
Renderer() == GLRenderer::AdrenoTM420) {
|
||||
// see bug 1194923. Calling glFlush before glDeleteFramebuffers
|
||||
// prevents occasional driver crash.
|
||||
mNeedsFlushBeforeDeleteFB = true;
|
||||
}
|
||||
|
||||
mMaxTextureImageSize = mMaxTextureSize;
|
||||
|
||||
|
@ -2851,6 +2859,11 @@ GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names)
|
|||
}
|
||||
}
|
||||
|
||||
// Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
|
||||
if (mNeedsFlushBeforeDeleteFB) {
|
||||
fFlush();
|
||||
}
|
||||
|
||||
if (n == 1 && *names == 0) {
|
||||
// Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
|
||||
} else {
|
||||
|
|
|
@ -169,6 +169,7 @@ enum class GLRenderer {
|
|||
AdrenoTM200,
|
||||
AdrenoTM205,
|
||||
AdrenoTM320,
|
||||
AdrenoTM420,
|
||||
SGX530,
|
||||
SGX540,
|
||||
Tegra,
|
||||
|
@ -3504,6 +3505,7 @@ protected:
|
|||
GLint mMaxViewportDims[2];
|
||||
GLsizei mMaxSamples;
|
||||
bool mNeedsTextureSizeChecks;
|
||||
bool mNeedsFlushBeforeDeleteFB;
|
||||
bool mWorkAroundDriverBugs;
|
||||
|
||||
bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width, GLsizei height) const {
|
||||
|
|
|
@ -259,11 +259,12 @@ public:
|
|||
* The callee must draw all of aRegionToDraw.
|
||||
* This region is relative to 0,0 in the PaintedLayer.
|
||||
*
|
||||
* aDirtyRegion, if non-null, contains the total region that is due to be
|
||||
* painted during the transaction, even though only aRegionToDraw should
|
||||
* be drawn during this call. The sum of every aRegionToDraw over the
|
||||
* course of the transaction must equal aDirtyRegion. aDirtyRegion can be
|
||||
* null if the total dirty region is unknown.
|
||||
* aDirtyRegion should contain the total region that is be due to be painted
|
||||
* during the transaction, even though only aRegionToDraw should be drawn
|
||||
* during this call. aRegionToDraw must be entirely contained within
|
||||
* aDirtyRegion. If the total dirty region is unknown it is okay to pass a
|
||||
* subregion of the total dirty region, e.g. just aRegionToDraw, though it
|
||||
* may not be as efficient.
|
||||
*
|
||||
* aRegionToInvalidate contains a region whose contents have been
|
||||
* changed by the layer manager and which must therefore be invalidated.
|
||||
|
@ -285,7 +286,7 @@ public:
|
|||
typedef void (* DrawPaintedLayerCallback)(PaintedLayer* aLayer,
|
||||
gfxContext* aContext,
|
||||
const nsIntRegion& aRegionToDraw,
|
||||
const nsIntRegion* aDirtyRegion,
|
||||
const nsIntRegion& aDirtyRegion,
|
||||
DrawRegionClip aClip,
|
||||
const nsIntRegion& aRegionToInvalidate,
|
||||
void* aCallbackData);
|
||||
|
|
|
@ -1227,6 +1227,10 @@ TransformDisplacement(APZCTreeManager* aTreeManager,
|
|||
AsyncPanZoomController* aTarget,
|
||||
ParentLayerPoint& aStartPoint,
|
||||
ParentLayerPoint& aEndPoint) {
|
||||
if (aSource == aTarget) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert start and end points to Screen coordinates.
|
||||
Matrix4x4 untransformToApzc = aTreeManager->GetScreenToApzcTransform(aSource).Inverse();
|
||||
ScreenPoint screenStart = TransformTo<ScreenPixel>(untransformToApzc, aStartPoint);
|
||||
|
@ -1246,10 +1250,10 @@ TransformDisplacement(APZCTreeManager* aTreeManager,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev,
|
||||
ParentLayerPoint aStartPoint,
|
||||
ParentLayerPoint aEndPoint,
|
||||
ParentLayerPoint& aStartPoint,
|
||||
ParentLayerPoint& aEndPoint,
|
||||
OverscrollHandoffState& aOverscrollHandoffState)
|
||||
{
|
||||
const OverscrollHandoffChain& overscrollHandoffChain = aOverscrollHandoffState.mChain;
|
||||
|
@ -1259,34 +1263,39 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev,
|
|||
// nothing more to scroll, so we ignore the rest of the pan gesture.
|
||||
if (overscrollHandoffChainIndex >= overscrollHandoffChain.Length()) {
|
||||
// Nothing more to scroll - ignore the rest of the pan gesture.
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
next = overscrollHandoffChain.GetApzcAtIndex(overscrollHandoffChainIndex);
|
||||
|
||||
if (next == nullptr || next->IsDestroyed()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert the start and end points from |aPrev|'s coordinate space to
|
||||
// |next|'s coordinate space. Since |aPrev| may be the same as |next|
|
||||
// (if |aPrev| is the APZC that is initiating the scroll and there is no
|
||||
// scroll grabbing to grab the scroll from it), don't bother doing the
|
||||
// transformations in that case.
|
||||
if (next != aPrev) {
|
||||
if (!TransformDisplacement(this, aPrev, next, aStartPoint, aEndPoint)) {
|
||||
return false;
|
||||
}
|
||||
// |next|'s coordinate space.
|
||||
if (!TransformDisplacement(this, aPrev, next, aStartPoint, aEndPoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll |next|. If this causes overscroll, it will call DispatchScroll()
|
||||
// again with an incremented index.
|
||||
return next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffState);
|
||||
if (!next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffState)) {
|
||||
// Transform |aStartPoint| and |aEndPoint| (which now represent the
|
||||
// portion of the displacement that wasn't consumed by APZCs later
|
||||
// in the handoff chain) back into |aPrev|'s coordinate space. This
|
||||
// allows the caller (which is |aPrev|) to interpret the unconsumed
|
||||
// displacement in its own coordinate space, and make use of it
|
||||
// (e.g. by going into overscroll).
|
||||
if (!TransformDisplacement(this, next, aPrev, aStartPoint, aEndPoint)) {
|
||||
NS_WARNING("Failed to untransform scroll points during dispatch");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
|
||||
ParentLayerPoint aVelocity,
|
||||
ParentLayerPoint& aVelocity,
|
||||
nsRefPtr<const OverscrollHandoffChain> aOverscrollHandoffChain,
|
||||
bool aHandoff)
|
||||
{
|
||||
|
@ -1303,7 +1312,7 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
|
|||
// rather than (0, 0).
|
||||
ParentLayerPoint startPoint; // (0, 0)
|
||||
ParentLayerPoint endPoint;
|
||||
ParentLayerPoint transformedVelocity = aVelocity;
|
||||
ParentLayerPoint usedTransformedVelocity = aVelocity;
|
||||
|
||||
if (aHandoff) {
|
||||
startIndex = aOverscrollHandoffChain->IndexOf(aPrev) + 1;
|
||||
|
@ -1311,7 +1320,7 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
|
|||
// IndexOf will return aOverscrollHandoffChain->Length() if
|
||||
// |aPrev| is not found.
|
||||
if (startIndex >= aOverscrollHandoffChainLength) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
startIndex = 0;
|
||||
|
@ -1322,10 +1331,10 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
|
|||
|
||||
// Make sure the apcz about to be handled can be handled
|
||||
if (current == nullptr || current->IsDestroyed()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
endPoint = startPoint + transformedVelocity;
|
||||
endPoint = startPoint + usedTransformedVelocity;
|
||||
|
||||
// Only transform when current apcz can be transformed with previous
|
||||
if (startIndex > 0) {
|
||||
|
@ -1334,20 +1343,34 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
|
|||
current,
|
||||
startPoint,
|
||||
endPoint)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
transformedVelocity = endPoint - startPoint;
|
||||
ParentLayerPoint transformedVelocity = endPoint - startPoint;
|
||||
usedTransformedVelocity = transformedVelocity;
|
||||
|
||||
if (current->AttemptFling(transformedVelocity,
|
||||
if (current->AttemptFling(usedTransformedVelocity,
|
||||
aOverscrollHandoffChain,
|
||||
aHandoff)) {
|
||||
return true;
|
||||
if (IsZero(usedTransformedVelocity)) {
|
||||
aVelocity = ParentLayerPoint();
|
||||
return;
|
||||
}
|
||||
|
||||
// Subtract the proportion of used velocity from aVelocity
|
||||
if (!FuzzyEqualsAdditive(transformedVelocity.x,
|
||||
usedTransformedVelocity.x, COORDINATE_EPSILON)) {
|
||||
aVelocity.x = aVelocity.x *
|
||||
(usedTransformedVelocity.x / transformedVelocity.x);
|
||||
}
|
||||
if (!FuzzyEqualsAdditive(transformedVelocity.y,
|
||||
usedTransformedVelocity.y, COORDINATE_EPSILON)) {
|
||||
aVelocity.y = aVelocity.y *
|
||||
(usedTransformedVelocity.y / transformedVelocity.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -327,9 +327,10 @@ public:
|
|||
* |aOverscrollHandoffChainIndex| is the next position in the overscroll
|
||||
* handoff chain that should be scrolled.
|
||||
*
|
||||
* Returns true iff. some APZC accepted the scroll and scrolled.
|
||||
* This is to allow the sending APZC to go into an overscrolled state if
|
||||
* no APZC further up in the handoff chain accepted the overscroll.
|
||||
* aStartPoint and aEndPoint will be modified depending on how much of the
|
||||
* scroll each APZC consumes. This is to allow the sending APZC to go into
|
||||
* an overscrolled state if no APZC further up in the handoff chain accepted
|
||||
* the entire scroll.
|
||||
*
|
||||
* The way this method works is best illustrated with an example.
|
||||
* Consider three nested APZCs, A, B, and C, with C being the innermost one.
|
||||
|
@ -352,9 +353,9 @@ public:
|
|||
* Note: this should be used for panning only. For handing off overscroll for
|
||||
* a fling, use DispatchFling().
|
||||
*/
|
||||
bool DispatchScroll(AsyncPanZoomController* aApzc,
|
||||
ParentLayerPoint aStartPoint,
|
||||
ParentLayerPoint aEndPoint,
|
||||
void DispatchScroll(AsyncPanZoomController* aApzc,
|
||||
ParentLayerPoint& aStartPoint,
|
||||
ParentLayerPoint& aEndPoint,
|
||||
OverscrollHandoffState& aOverscrollHandoffState);
|
||||
|
||||
/**
|
||||
|
@ -374,12 +375,13 @@ public:
|
|||
* start a fling (in this case the fling is given to the
|
||||
* first APZC in the chain)
|
||||
*
|
||||
* Returns true iff. an APZC accepted the fling. In the case of fling handoff,
|
||||
* the caller uses this return value to determine whether it should consume
|
||||
* the excess fling itself by going into an overscroll fling.
|
||||
* aVelocity will be modified depending on how much of that velocity has
|
||||
* been consumed by APZCs in the overscroll hand-off chain. The caller can
|
||||
* use this value to determine whether it should consume the excess velocity
|
||||
* by going into an overscroll fling.
|
||||
*/
|
||||
bool DispatchFling(AsyncPanZoomController* aApzc,
|
||||
ParentLayerPoint aVelocity,
|
||||
void DispatchFling(AsyncPanZoomController* aApzc,
|
||||
ParentLayerPoint& aVelocity,
|
||||
nsRefPtr<const OverscrollHandoffChain> aOverscrollHandoffChain,
|
||||
bool aHandoff);
|
||||
|
||||
|
|
|
@ -1578,9 +1578,9 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
|||
*mInputQueue->CurrentWheelBlock()->GetOverscrollHandoffChain(),
|
||||
distance,
|
||||
ScrollSource::Wheel);
|
||||
CallDispatchScroll(aEvent.mLocalOrigin,
|
||||
aEvent.mLocalOrigin - delta,
|
||||
handoffState);
|
||||
ParentLayerPoint startPoint = aEvent.mLocalOrigin;
|
||||
ParentLayerPoint endPoint = aEvent.mLocalOrigin - delta;
|
||||
CallDispatchScroll(startPoint, endPoint, handoffState);
|
||||
|
||||
SetState(NOTHING);
|
||||
RequestContentRepaint();
|
||||
|
@ -1726,9 +1726,9 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
|||
*CurrentPanGestureBlock()->GetOverscrollHandoffChain(),
|
||||
panDistance,
|
||||
ScrollSource::Wheel);
|
||||
CallDispatchScroll(aEvent.mLocalPanStartPoint,
|
||||
aEvent.mLocalPanStartPoint + aEvent.mLocalPanDisplacement,
|
||||
handoffState);
|
||||
ParentLayerPoint startPoint = aEvent.mLocalPanStartPoint;
|
||||
ParentLayerPoint endPoint = aEvent.mLocalPanStartPoint + aEvent.mLocalPanDisplacement;
|
||||
CallDispatchScroll(startPoint, endPoint, handoffState);
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
@ -1983,11 +1983,19 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle) {
|
|||
|
||||
void AsyncPanZoomController::HandlePanning(double aAngle) {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
if (!gfxPrefs::APZCrossSlideEnabled() && (!mX.CanScrollNow() || !mY.CanScrollNow())) {
|
||||
nsRefPtr<const OverscrollHandoffChain> overscrollHandoffChain =
|
||||
GetInputQueue()->CurrentBlock()->GetOverscrollHandoffChain();
|
||||
bool canScrollHorizontal = !mX.IsAxisLocked() &&
|
||||
overscrollHandoffChain->CanScrollInDirection(this, Layer::HORIZONTAL);
|
||||
bool canScrollVertical = !mY.IsAxisLocked() &&
|
||||
overscrollHandoffChain->CanScrollInDirection(this, Layer::VERTICAL);
|
||||
|
||||
if (!gfxPrefs::APZCrossSlideEnabled() &&
|
||||
(!canScrollHorizontal || !canScrollVertical)) {
|
||||
SetState(PANNING);
|
||||
} else if (IsCloseToHorizontal(aAngle, gfxPrefs::APZAxisLockAngle())) {
|
||||
mY.SetAxisLocked(true);
|
||||
if (mX.CanScrollNow()) {
|
||||
if (canScrollHorizontal) {
|
||||
SetState(PANNING_LOCKED_X);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_X);
|
||||
|
@ -1995,7 +2003,7 @@ void AsyncPanZoomController::HandlePanning(double aAngle) {
|
|||
}
|
||||
} else if (IsCloseToVertical(aAngle, gfxPrefs::APZAxisLockAngle())) {
|
||||
mX.SetAxisLocked(true);
|
||||
if (mY.CanScrollNow()) {
|
||||
if (canScrollVertical) {
|
||||
SetState(PANNING_LOCKED_Y);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_Y);
|
||||
|
@ -2067,8 +2075,8 @@ void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput&
|
|||
mY.UpdateWithTouchAtDevicePoint(point.y, 0, aEvent.mTime);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint,
|
||||
const ParentLayerPoint& aEndPoint,
|
||||
bool AsyncPanZoomController::AttemptScroll(ParentLayerPoint& aStartPoint,
|
||||
ParentLayerPoint& aEndPoint,
|
||||
OverscrollHandoffState& aOverscrollHandoffState) {
|
||||
|
||||
// "start - end" rather than "end - start" because e.g. moving your finger
|
||||
|
@ -2099,6 +2107,9 @@ bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint,
|
|||
}
|
||||
}
|
||||
|
||||
// Adjust the start point to reflect the consumed portion of the scroll.
|
||||
aStartPoint = aEndPoint + overscroll;
|
||||
|
||||
// If we consumed the entire displacement as a normal scroll, great.
|
||||
if (IsZero(overscroll)) {
|
||||
return true;
|
||||
|
@ -2111,8 +2122,10 @@ bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint,
|
|||
// Note: "+ overscroll" rather than "- overscroll" because "overscroll"
|
||||
// is what's left of "displacement", and "displacement" is "start - end".
|
||||
++aOverscrollHandoffState.mChainIndex;
|
||||
if (CallDispatchScroll(aEndPoint + overscroll, aEndPoint,
|
||||
aOverscrollHandoffState)) {
|
||||
CallDispatchScroll(aStartPoint, aEndPoint, aOverscrollHandoffState);
|
||||
|
||||
overscroll = aStartPoint - aEndPoint;
|
||||
if (IsZero(overscroll)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2121,10 +2134,13 @@ bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint,
|
|||
// overscroll, try to accept it ourselves. We only accept it if we
|
||||
// are pannable.
|
||||
APZC_LOG("%p taking overscroll during panning\n", this);
|
||||
return OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance);
|
||||
OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance);
|
||||
aStartPoint = aEndPoint + overscroll;
|
||||
|
||||
return IsZero(overscroll);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll,
|
||||
void AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint& aOverscroll,
|
||||
const ScreenPoint& aPanDistance) {
|
||||
// Only allow entering overscroll along an axis if the pan distance along
|
||||
// that axis is greater than the pan distance along the other axis by a
|
||||
|
@ -2138,12 +2154,12 @@ bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll,
|
|||
}
|
||||
}
|
||||
|
||||
return OverscrollBy(aOverscroll);
|
||||
OverscrollBy(aOverscroll);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::OverscrollBy(const ParentLayerPoint& aOverscroll) {
|
||||
void AsyncPanZoomController::OverscrollBy(ParentLayerPoint& aOverscroll) {
|
||||
if (!gfxPrefs::APZOverscrollEnabled()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
@ -2151,19 +2167,24 @@ bool AsyncPanZoomController::OverscrollBy(const ParentLayerPoint& aOverscroll) {
|
|||
// scroll to begin with.
|
||||
bool xCanScroll = mX.CanScroll();
|
||||
bool yCanScroll = mY.CanScroll();
|
||||
if (xCanScroll) {
|
||||
|
||||
bool xConsumed = FuzzyEqualsAdditive(aOverscroll.x, 0.0f, COORDINATE_EPSILON);
|
||||
if (xCanScroll && !xConsumed) {
|
||||
mX.OverscrollBy(aOverscroll.x);
|
||||
aOverscroll.x = 0;
|
||||
xConsumed = true;
|
||||
}
|
||||
if (yCanScroll) {
|
||||
|
||||
bool yConsumed = FuzzyEqualsAdditive(aOverscroll.y, 0.0f, COORDINATE_EPSILON);
|
||||
if (yCanScroll && !yConsumed) {
|
||||
mY.OverscrollBy(aOverscroll.y);
|
||||
aOverscroll.y = 0;
|
||||
yConsumed = true;
|
||||
}
|
||||
if (xCanScroll || yCanScroll) {
|
||||
|
||||
if ((xCanScroll && xConsumed) || (yCanScroll && yConsumed)) {
|
||||
ScheduleComposite();
|
||||
return true;
|
||||
}
|
||||
// TODO(botond): If one of the x- or y-overscroll was not accepted, we
|
||||
// may want to propagate that one to an APZC earlier in the handoff chain.
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<const OverscrollHandoffChain> AsyncPanZoomController::BuildOverscrollHandoffChain() {
|
||||
|
@ -2178,14 +2199,22 @@ nsRefPtr<const OverscrollHandoffChain> AsyncPanZoomController::BuildOverscrollHa
|
|||
return result;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity,
|
||||
void AsyncPanZoomController::AcceptFling(ParentLayerPoint& aVelocity,
|
||||
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
|
||||
bool aHandoff) {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
// We may have a pre-existing velocity for whatever reason (for example,
|
||||
// a previously handed off fling). We don't want to clobber that.
|
||||
APZC_LOG("%p accepting fling with velocity %s\n", this, Stringify(aVelocity).c_str());
|
||||
mX.SetVelocity(mX.GetVelocity() + aVelocity.x);
|
||||
mY.SetVelocity(mY.GetVelocity() + aVelocity.y);
|
||||
if (mX.CanScroll()) {
|
||||
mX.SetVelocity(mX.GetVelocity() + aVelocity.x);
|
||||
aVelocity.x = 0;
|
||||
}
|
||||
if (mY.CanScroll()) {
|
||||
mY.SetVelocity(mY.GetVelocity() + aVelocity.y);
|
||||
aVelocity.y = 0;
|
||||
}
|
||||
SetState(FLING);
|
||||
FlingAnimation *fling = new FlingAnimation(*this,
|
||||
aOverscrollHandoffChain,
|
||||
|
@ -2227,7 +2256,7 @@ void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity,
|
|||
StartAnimation(fling);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity,
|
||||
bool AsyncPanZoomController::AttemptFling(ParentLayerPoint& aVelocity,
|
||||
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
|
||||
bool aHandoff) {
|
||||
// If we are pannable, take over the fling ourselves.
|
||||
|
@ -2244,14 +2273,12 @@ bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity,
|
|||
void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
|
||||
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain) {
|
||||
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
|
||||
if (!(treeManagerLocal && treeManagerLocal->DispatchFling(this,
|
||||
aVelocity,
|
||||
aOverscrollHandoffChain,
|
||||
true /* handoff */))) {
|
||||
// No one wanted the fling, so we "take it" ourselves by entering an
|
||||
// overscroll animation starting with the fling's velocity.
|
||||
if (IsPannable() && gfxPrefs::APZOverscrollEnabled()) {
|
||||
StartOverscrollAnimation(aVelocity);
|
||||
ParentLayerPoint velocity = aVelocity;
|
||||
if (treeManagerLocal) {
|
||||
treeManagerLocal->DispatchFling(this, velocity, aOverscrollHandoffChain,
|
||||
true /* handoff */);
|
||||
if (!IsZero(velocity) && IsPannable() && gfxPrefs::APZOverscrollEnabled()) {
|
||||
StartOverscrollAnimation(velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2284,19 +2311,19 @@ void AsyncPanZoomController::StartOverscrollAnimation(const ParentLayerPoint& aV
|
|||
StartAnimation(new OverscrollAnimation(*this, aVelocity));
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::CallDispatchScroll(const ParentLayerPoint& aStartPoint,
|
||||
const ParentLayerPoint& aEndPoint,
|
||||
void AsyncPanZoomController::CallDispatchScroll(ParentLayerPoint& aStartPoint,
|
||||
ParentLayerPoint& aEndPoint,
|
||||
OverscrollHandoffState& aOverscrollHandoffState) {
|
||||
// Make a local copy of the tree manager pointer and check if it's not
|
||||
// null before calling DispatchScroll(). This is necessary because
|
||||
// Destroy(), which nulls out mTreeManager, could be called concurrently.
|
||||
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
|
||||
if (!treeManagerLocal) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
return treeManagerLocal->DispatchScroll(this,
|
||||
aStartPoint, aEndPoint,
|
||||
aOverscrollHandoffState);
|
||||
treeManagerLocal->DispatchScroll(this,
|
||||
aStartPoint, aEndPoint,
|
||||
aOverscrollHandoffState);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
|
||||
|
@ -3103,13 +3130,16 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
|||
targetZoom = CSSToParentLayerScale(std::min(compositionBounds.width / aRect.width,
|
||||
compositionBounds.height / aRect.height));
|
||||
}
|
||||
// 1. If the rect is empty, request received from browserElementScrolling.js
|
||||
// 1. If the rect is empty, the content-side logic for handling a double-tap
|
||||
// requested that we zoom out.
|
||||
// 2. currentZoom is equal to mZoomConstraints.mMaxZoom and user still double-tapping it
|
||||
// 3. currentZoom is equal to localMinZoom and user still double-tapping it
|
||||
// Treat these three cases as a request to zoom out as much as possible.
|
||||
bool zoomOut = false;
|
||||
if (aRect.IsEmpty() ||
|
||||
(currentZoom == localMaxZoom && targetZoom >= localMaxZoom) ||
|
||||
(currentZoom == localMinZoom && targetZoom <= localMinZoom)) {
|
||||
zoomOut = true;
|
||||
CSSSize compositedSize = mFrameMetrics.CalculateCompositedSizeInCssPixels();
|
||||
float y = scrollOffset.y;
|
||||
float newHeight =
|
||||
|
@ -3143,6 +3173,14 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
|||
aRect.x = aRect.x > 0 ? aRect.x : 0;
|
||||
}
|
||||
|
||||
// Vertically center the zoomed element in the screen.
|
||||
if (!zoomOut && (sizeAfterZoom.height > aRect.height)) {
|
||||
aRect.y -= (sizeAfterZoom.height - aRect.height) * 0.5f;
|
||||
if (aRect.y < 0.0f) {
|
||||
aRect.y = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
endZoomToMetrics.SetScrollOffset(aRect.TopLeft());
|
||||
endZoomToMetrics.SetDisplayPortMargins(
|
||||
CalculatePendingDisplayPort(endZoomToMetrics,
|
||||
|
|
|
@ -855,15 +855,16 @@ private:
|
|||
*/
|
||||
public:
|
||||
/**
|
||||
* Attempt a fling with the given velocity. If we are not pannable, tehe fling
|
||||
* Attempt a fling with the given velocity. If we are not pannable, the fling
|
||||
* is handed off to the next APZC in the handoff chain via
|
||||
* mTreeManager->DspatchFling(). Returns true iff. any APZC (whether this
|
||||
* one or one further in the handoff chain) accepted the fling.
|
||||
* mTreeManager->DispatchFling(). Returns true iff. the entire velocity of
|
||||
* the fling was consumed by this APZC. aVelocity is modified to contain any
|
||||
* unused, residual velocity.
|
||||
* |aHandoff| should be true iff. the fling was handed off from a previous
|
||||
* APZC, and determines whether acceleration is applied to the
|
||||
* fling.
|
||||
*/
|
||||
bool AttemptFling(ParentLayerPoint aVelocity,
|
||||
bool AttemptFling(ParentLayerPoint& aVelocity,
|
||||
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
|
||||
bool aHandoff);
|
||||
|
||||
|
@ -889,7 +890,7 @@ private:
|
|||
void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity);
|
||||
|
||||
// Helper function used by TakeOverFling() and HandleFlingOverscroll().
|
||||
void AcceptFling(const ParentLayerPoint& aVelocity,
|
||||
void AcceptFling(ParentLayerPoint& aVelocity,
|
||||
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
|
||||
bool aHandoff);
|
||||
|
||||
|
@ -967,9 +968,11 @@ public:
|
|||
* handoff chain, accepted the scroll (possibly entering an overscrolled
|
||||
* state). If this returns false, the caller APZC knows that it should enter
|
||||
* an overscrolled state itself if it can.
|
||||
* aStartPoint and aEndPoint are modified depending on how much of the
|
||||
* scroll gesture was consumed by APZCs in the handoff chain.
|
||||
*/
|
||||
bool AttemptScroll(const ParentLayerPoint& aStartPoint,
|
||||
const ParentLayerPoint& aEndPoint,
|
||||
bool AttemptScroll(ParentLayerPoint& aStartPoint,
|
||||
ParentLayerPoint& aEndPoint,
|
||||
OverscrollHandoffState& aOverscrollHandoffState);
|
||||
|
||||
void FlushRepaintForOverscrollHandoff();
|
||||
|
@ -1007,8 +1010,8 @@ private:
|
|||
* Guards against the case where the APZC is being concurrently destroyed
|
||||
* (and thus mTreeManager is being nulled out).
|
||||
*/
|
||||
bool CallDispatchScroll(const ParentLayerPoint& aStartPoint,
|
||||
const ParentLayerPoint& aEndPoint,
|
||||
void CallDispatchScroll(ParentLayerPoint& aStartPoint,
|
||||
ParentLayerPoint& aEndPoint,
|
||||
OverscrollHandoffState& aOverscrollHandoffState);
|
||||
|
||||
/**
|
||||
|
@ -1016,16 +1019,15 @@ private:
|
|||
* around OverscrollBy() that also implements restrictions on entering
|
||||
* overscroll based on the pan angle.
|
||||
*/
|
||||
bool OverscrollForPanning(ParentLayerPoint aOverscroll,
|
||||
void OverscrollForPanning(ParentLayerPoint& aOverscroll,
|
||||
const ScreenPoint& aPanDistance);
|
||||
|
||||
/**
|
||||
* Try to overscroll by 'aOverscroll'.
|
||||
* If we are pannable, 'aOverscroll' is added to any existing overscroll,
|
||||
* and the function returns true.
|
||||
* Otherwise, nothing happens and the function return false.
|
||||
* If we are pannable on a particular axis, that component of 'aOverscroll'
|
||||
* is transferred to any existing overscroll.
|
||||
*/
|
||||
bool OverscrollBy(const ParentLayerPoint& aOverscroll);
|
||||
void OverscrollBy(ParentLayerPoint& aOverscroll);
|
||||
|
||||
|
||||
/* ===================================================================
|
||||
|
|
|
@ -510,6 +510,10 @@ CSSCoord Axis::ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool Axis::IsAxisLocked() const {
|
||||
return mAxisLocked;
|
||||
}
|
||||
|
||||
float Axis::GetVelocity() const {
|
||||
return mAxisLocked ? 0 : mVelocity;
|
||||
}
|
||||
|
|
|
@ -223,6 +223,11 @@ public:
|
|||
*/
|
||||
bool ScaleWillOverscrollBothSides(float aScale) const;
|
||||
|
||||
/**
|
||||
* Returns true if movement on this axis is locked.
|
||||
*/
|
||||
bool IsAxisLocked() const;
|
||||
|
||||
ParentLayerCoord GetOrigin() const;
|
||||
ParentLayerCoord GetCompositionLength() const;
|
||||
ParentLayerCoord GetPageStart() const;
|
||||
|
|
|
@ -105,25 +105,12 @@ void
|
|||
OverscrollHandoffChain::SnapBackOverscrolledApzc(const AsyncPanZoomController* aStart) const
|
||||
{
|
||||
uint32_t i = IndexOf(aStart);
|
||||
for (; i < Length(); ++i) {
|
||||
AsyncPanZoomController* apzc = mChain[i];
|
||||
if (!apzc->IsDestroyed() && apzc->SnapBackIfOverscrolled()) {
|
||||
// At most one APZC from |aStart| onwards can be overscrolled.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// In debug builds, verify our assumption that only one APZC from |aStart|
|
||||
// onwards is overscrolled.
|
||||
#ifdef DEBUG
|
||||
++i;
|
||||
for (; i < Length(); ++i) {
|
||||
AsyncPanZoomController* apzc = mChain[i];
|
||||
if (!apzc->IsDestroyed()) {
|
||||
MOZ_ASSERT(!apzc->IsOverscrolled());
|
||||
apzc->SnapBackIfOverscrolled();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -71,23 +71,44 @@ ShouldZoomToElement(const nsCOMPtr<dom::Element>& aElement) {
|
|||
}
|
||||
|
||||
// Calculate the bounding rect of |aElement|, relative to the origin
|
||||
// of the document associated with |aShell|.
|
||||
// |aRootScrollFrame| should be the root scroll frame of the document in
|
||||
// question.
|
||||
// The implementation is adapted from Element::GetBoundingClientRect().
|
||||
// of the scrolled content of |aRootScrollFrame|.
|
||||
// The implementation of this calculation is adapted from
|
||||
// Element::GetBoundingClientRect().
|
||||
//
|
||||
// Where the element is contained inside a scrollable subframe, the
|
||||
// bounding rect is clipped to the bounds of the subframe.
|
||||
static CSSRect
|
||||
GetBoundingContentRect(const nsCOMPtr<nsIPresShell>& aShell,
|
||||
const nsCOMPtr<dom::Element>& aElement,
|
||||
GetBoundingContentRect(const nsCOMPtr<dom::Element>& aElement,
|
||||
const nsIScrollableFrame* aRootScrollFrame) {
|
||||
|
||||
CSSRect result;
|
||||
if (nsIFrame* frame = aElement->GetPrimaryFrame()) {
|
||||
return CSSRect::FromAppUnits(
|
||||
nsIFrame* relativeTo = aRootScrollFrame->GetScrolledFrame();
|
||||
result = CSSRect::FromAppUnits(
|
||||
nsLayoutUtils::GetAllInFlowRectsUnion(
|
||||
frame,
|
||||
aShell->GetRootFrame(),
|
||||
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS)
|
||||
+ aRootScrollFrame->GetScrollPosition());
|
||||
relativeTo,
|
||||
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS));
|
||||
|
||||
// If the element is contained in a scrollable frame that is not
|
||||
// the root scroll frame, make sure to clip the result so that it is
|
||||
// not larger than the containing scrollable frame's bounds.
|
||||
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetNearestScrollableFrame(frame);
|
||||
if (scrollFrame && scrollFrame != aRootScrollFrame) {
|
||||
nsIFrame* subFrame = do_QueryFrame(scrollFrame);
|
||||
MOZ_ASSERT(subFrame);
|
||||
// Get the bounds of the scroll frame in the same coordinate space
|
||||
// as |result|.
|
||||
CSSRect subFrameRect = CSSRect::FromAppUnits(
|
||||
nsLayoutUtils::TransformFrameRectToAncestor(
|
||||
subFrame,
|
||||
subFrame->GetRectRelativeToSelf(),
|
||||
relativeTo));
|
||||
|
||||
result = subFrameRect.Intersect(result);
|
||||
}
|
||||
}
|
||||
return CSSRect();
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -143,7 +164,27 @@ CalculateRectToZoomTo(const nsCOMPtr<nsIDocument>& aRootContentDocument,
|
|||
FrameMetrics metrics = nsLayoutUtils::CalculateBasicFrameMetrics(rootScrollFrame);
|
||||
CSSRect compositedArea(metrics.GetScrollOffset(), metrics.CalculateCompositedSizeInCssPixels());
|
||||
const CSSCoord margin = 15;
|
||||
CSSRect rect = GetBoundingContentRect(shell, element, rootScrollFrame);
|
||||
CSSRect rect = GetBoundingContentRect(element, rootScrollFrame);
|
||||
|
||||
// If the element is taller than the visible area of the page scale
|
||||
// the height of the |rect| so that it has the same aspect ratio as
|
||||
// the root frame. The clipped |rect| is centered on the y value of
|
||||
// the touch point. This allows tall narrow elements to be zoomed.
|
||||
if (!rect.IsEmpty() && compositedArea.width > 0.0f) {
|
||||
const float widthRatio = rect.width / compositedArea.width;
|
||||
float targetHeight = compositedArea.height * widthRatio;
|
||||
if (widthRatio < 0.9 && targetHeight < rect.height) {
|
||||
const CSSPoint scrollPoint = CSSPoint::FromAppUnits(rootScrollFrame->GetScrollPosition());
|
||||
float newY = aPoint.y + scrollPoint.y - (targetHeight * 0.5f);
|
||||
if ((newY + targetHeight) > (rect.y + rect.height)) {
|
||||
rect.y += rect.height - targetHeight;
|
||||
} else if (newY > rect.y) {
|
||||
rect.y = newY;
|
||||
}
|
||||
rect.height = targetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
rect = CSSRect(std::max(metrics.GetScrollableRect().x, rect.x - margin),
|
||||
rect.y,
|
||||
rect.width + 2 * margin,
|
||||
|
|
|
@ -91,7 +91,7 @@ BasicPaintedLayer::PaintThebes(gfxContext* aContext,
|
|||
groupContext = aContext;
|
||||
}
|
||||
SetAntialiasingFlags(this, groupContext->GetDrawTarget());
|
||||
aCallback(this, groupContext, toDraw, &toDraw,
|
||||
aCallback(this, groupContext, toDraw, toDraw,
|
||||
DrawRegionClip::NONE, nsIntRegion(), aCallbackData);
|
||||
if (needsGroup) {
|
||||
aContext->PopGroupToSource();
|
||||
|
|
|
@ -112,7 +112,7 @@ protected:
|
|||
BasicManager()->SetTransactionIncomplete();
|
||||
return;
|
||||
}
|
||||
aCallback(this, aContext, aExtendedRegionToDraw, &aExtendedRegionToDraw,
|
||||
aCallback(this, aContext, aExtendedRegionToDraw, aExtendedRegionToDraw,
|
||||
aClip, aRegionToInvalidate, aCallbackData);
|
||||
// Everything that's visible has been validated. Do this instead of just
|
||||
// OR-ing with aRegionToDraw, since that can lead to a very complex region
|
||||
|
|
|
@ -87,7 +87,7 @@ ClientPaintedLayer::PaintThebes()
|
|||
ClientManager()->GetPaintedLayerCallback()(this,
|
||||
ctx,
|
||||
iter.mDrawRegion,
|
||||
nullptr,
|
||||
iter.mDrawRegion,
|
||||
state.mClip,
|
||||
state.mRegionToInvalidate,
|
||||
ClientManager()->GetPaintedLayerCallbackData());
|
||||
|
|
|
@ -270,5 +270,26 @@ CompositableClient::DumpTextureClient(std::stringstream& aStream, TextureClient*
|
|||
aStream << gfxUtils::GetAsLZ4Base64Str(dSurf).get();
|
||||
}
|
||||
|
||||
AutoRemoveTexture::~AutoRemoveTexture()
|
||||
{
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||
if (mCompositable && mTexture && mCompositable->GetForwarder()) {
|
||||
// remove old buffer from CompositableHost
|
||||
RefPtr<AsyncTransactionWaiter> waiter = new AsyncTransactionWaiter();
|
||||
RefPtr<AsyncTransactionTracker> tracker =
|
||||
new RemoveTextureFromCompositableTracker(waiter);
|
||||
// Hold TextureClient until transaction complete.
|
||||
tracker->SetTextureClient(mTexture);
|
||||
mTexture->SetRemoveFromCompositableWaiter(waiter);
|
||||
// RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
|
||||
mCompositable->GetForwarder()->RemoveTextureFromCompositableAsync(tracker, mCompositable, mTexture);
|
||||
}
|
||||
#else
|
||||
if (mCompositable && mTexture) {
|
||||
mCompositable->RemoveTexture(mTexture);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -248,12 +248,7 @@ struct AutoRemoveTexture
|
|||
, mCompositable(aCompositable)
|
||||
{}
|
||||
|
||||
~AutoRemoveTexture()
|
||||
{
|
||||
if (mCompositable && mTexture) {
|
||||
mCompositable->RemoveTexture(mTexture);
|
||||
}
|
||||
}
|
||||
~AutoRemoveTexture();
|
||||
|
||||
RefPtr<TextureClient> mTexture;
|
||||
private:
|
||||
|
|
|
@ -360,7 +360,6 @@ ImageClientOverlay::UpdateImage(ImageContainer* aContainer, uint32_t aContentFla
|
|||
}
|
||||
mLastUpdateGenerationCounter = (uint32_t)image->GetSerial();
|
||||
|
||||
AutoRemoveTexture autoRemoveTexture(this);
|
||||
if (image->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
|
||||
OverlayImage* overlayImage = static_cast<OverlayImage*>(image);
|
||||
uint32_t overlayId = overlayImage->GetOverlayId();
|
||||
|
|
|
@ -181,7 +181,7 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
nsRefPtr<gfxContext> ctx = new gfxContext(dt);
|
||||
ctx->SetMatrix(ctx->CurrentMatrix().Translate(-mTilingOrigin.x, -mTilingOrigin.y));
|
||||
|
||||
aCallback(mPaintedLayer, ctx, paintRegion, &paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
|
||||
aCallback(mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
|
||||
}
|
||||
|
||||
// Mark the area we just drew into the back buffer as invalid in the front buffer as they're
|
||||
|
|
|
@ -964,7 +964,7 @@ ClientMultiTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw",
|
||||
js::ProfileEntry::Category::GRAPHICS);
|
||||
|
||||
mCallback(mPaintedLayer, ctxt, aPaintRegion, &aDirtyRegion,
|
||||
mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion,
|
||||
DrawRegionClip::NONE, nsIntRegion(), mCallbackData);
|
||||
}
|
||||
|
||||
|
@ -1171,7 +1171,7 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
|
|||
ctx->SetMatrix(
|
||||
ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin)));
|
||||
|
||||
mCallback(mPaintedLayer, ctx, aPaintRegion, &aDirtyRegion,
|
||||
mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion,
|
||||
DrawRegionClip::DRAW, nsIntRegion(), mCallbackData);
|
||||
mMoz2DTiles.clear();
|
||||
// Reset:
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#ifdef MOZ_NUWA_PROCESS
|
||||
#include "ipc/Nuwa.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/PContent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/PNuwa.h"
|
||||
#include "mozilla/hal_sandbox/PHal.h"
|
||||
#if defined(DEBUG) || defined(ENABLE_TESTS)
|
||||
|
@ -144,7 +144,7 @@ ProcessLink::Open(mozilla::ipc::Transport* aTransport, MessageLoop *aIOLoop, Sid
|
|||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (IsNuwaProcess() &&
|
||||
if (IsNuwaProcess() && NS_IsMainThread() &&
|
||||
Preferences::GetBool("dom.ipc.processPrelaunch.testMode")) {
|
||||
// The pref value is turned on in a deadlock test against the Nuwa
|
||||
// process. The sleep here makes it easy to trigger the deadlock
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,84 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*
|
||||
* Copyright 2015 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef jit_AsmJSCompile_h
|
||||
#define jit_AsmJSCompile_h
|
||||
|
||||
#include "jit/CompileWrappers.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class AsmFunction;
|
||||
class LifoAlloc;
|
||||
class ModuleCompiler;
|
||||
class ModuleCompileResults;
|
||||
|
||||
namespace jit {
|
||||
class LIRGraph;
|
||||
class MIRGenerator;
|
||||
}
|
||||
|
||||
struct ModuleCompileInputs
|
||||
{
|
||||
jit::CompileCompartment* compartment;
|
||||
jit::CompileRuntime* runtime;
|
||||
bool usesSignalHandlersForOOB;
|
||||
|
||||
ModuleCompileInputs(jit::CompileCompartment* compartment,
|
||||
jit::CompileRuntime* runtime,
|
||||
bool usesSignalHandlersForOOB)
|
||||
: compartment(compartment),
|
||||
runtime(runtime),
|
||||
usesSignalHandlersForOOB(usesSignalHandlersForOOB)
|
||||
{}
|
||||
};
|
||||
|
||||
class MOZ_RAII AsmModuleCompilerScope
|
||||
{
|
||||
ModuleCompiler* m_;
|
||||
|
||||
AsmModuleCompilerScope(const AsmModuleCompilerScope&) = delete;
|
||||
AsmModuleCompilerScope(const AsmModuleCompilerScope&&) = delete;
|
||||
AsmModuleCompilerScope& operator=(const AsmModuleCompilerScope&&) = delete;
|
||||
|
||||
public:
|
||||
AsmModuleCompilerScope()
|
||||
: m_(nullptr)
|
||||
{}
|
||||
|
||||
void setModule(ModuleCompiler* m) {
|
||||
MOZ_ASSERT(m);
|
||||
m_ = m;
|
||||
}
|
||||
|
||||
ModuleCompiler& module() const {
|
||||
MOZ_ASSERT(m_);
|
||||
return *m_;
|
||||
}
|
||||
|
||||
~AsmModuleCompilerScope();
|
||||
};
|
||||
|
||||
bool CreateAsmModuleCompiler(ModuleCompileInputs mci, AsmModuleCompilerScope* scope);
|
||||
bool GenerateAsmFunctionMIR(ModuleCompiler& m, LifoAlloc& lifo, AsmFunction& func, jit::MIRGenerator** mir);
|
||||
bool GenerateAsmFunctionCode(ModuleCompiler& m, AsmFunction& func, jit::MIRGenerator& mir, jit::LIRGraph& lir);
|
||||
void FinishAsmModuleCompilation(ModuleCompiler& m, ScopedJSDeletePtr<ModuleCompileResults>* results);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif // jit_AsmJSCompile_h
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -15,7 +15,8 @@ function usage() {
|
|||
|
||||
clean=1
|
||||
platform=""
|
||||
TIMEOUT=3h
|
||||
# 3 hours. OS X doesn't support the "sleep 3h" syntax.
|
||||
TIMEOUT=10800
|
||||
while [ $# -gt 1 ]; do
|
||||
case "$1" in
|
||||
--dep)
|
||||
|
@ -91,6 +92,8 @@ elif [ "$OSTYPE" = "linux-gnu" ]; then
|
|||
MAKEFLAGS=-j4
|
||||
if [ "$VARIANT" = "arm-sim" ]; then
|
||||
USE_64BIT=false
|
||||
elif [ "$VARIANT" = "arm64-sim" ]; then
|
||||
USE_64BIT=true
|
||||
else
|
||||
case "$platform" in
|
||||
linux64)
|
||||
|
@ -168,6 +171,8 @@ if type setarch >/dev/null 2>&1; then
|
|||
fi
|
||||
|
||||
RUN_JSTESTS=true
|
||||
RUN_JITTEST=true
|
||||
RUN_JSAPITESTS=true
|
||||
|
||||
PARENT=$$
|
||||
|
||||
|
@ -206,11 +211,21 @@ elif [[ "$VARIANT" = "warnaserr" ||
|
|||
elif [[ "$VARIANT" = "arm-sim" ||
|
||||
"$VARIANT" = "plaindebug" ]]; then
|
||||
export JSTESTS_EXTRA_ARGS=--jitflags=debug
|
||||
elif [[ "$VARIANT" = arm64* ]]; then
|
||||
# The ARM64 JIT is not yet fully functional, and asm.js does not work.
|
||||
# Just run "make check". We mostly care about not breaking the build at this point.
|
||||
RUN_JITTEST=false
|
||||
RUN_JSAPITESTS=false
|
||||
RUN_JSTESTS=false
|
||||
fi
|
||||
|
||||
$COMMAND_PREFIX $MAKE check || exit 1
|
||||
$COMMAND_PREFIX $MAKE check-jit-test || exit 1
|
||||
$COMMAND_PREFIX $OBJDIR/dist/bin/jsapi-tests || exit 1
|
||||
if $RUN_JITTEST; then
|
||||
$COMMAND_PREFIX $MAKE check-jit-test || exit 1
|
||||
fi
|
||||
if $RUN_JSAPITESTS; then
|
||||
$COMMAND_PREFIX $OBJDIR/dist/bin/jsapi-tests || exit 1
|
||||
fi
|
||||
if $RUN_JSTESTS; then
|
||||
$COMMAND_PREFIX $MAKE check-jstests || exit 1
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
--enable-optimize
|
||||
--enable-debug
|
||||
--enable-stdcxx-compat
|
||||
--disable-shared-js
|
||||
--enable-simulator=arm64
|
|
@ -38,7 +38,7 @@ function indirectCallCannotGC(fullCaller, fullVariable)
|
|||
if (name == "op" && /GetWeakmapKeyDelegate/.test(caller))
|
||||
return true;
|
||||
|
||||
var CheckCallArgs = "AsmJSValidate.cpp:uint8 CheckCallArgs(FunctionValidator*, js::frontend::ParseNode*, (uint8)(FunctionValidator*,js::frontend::ParseNode*,Type)*, Signature*)";
|
||||
var CheckCallArgs = "AsmJSValidate.cpp:uint8 CheckCallArgs(FunctionValidator*, js::frontend::ParseNode*, (uint8)(FunctionValidator*,js::frontend::ParseNode*,js::wasm::Type)*, js::wasm::Signature*)";
|
||||
if (name == "checkArg" && caller == CheckCallArgs)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -31,6 +31,14 @@
|
|||
#ifndef V8_REGEXP_AST_H_
|
||||
#define V8_REGEXP_AST_H_
|
||||
|
||||
// Prevent msvc build failures as indicated in bug 1205328
|
||||
#ifdef min
|
||||
# undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
# undef max
|
||||
#endif
|
||||
|
||||
#include "irregexp/RegExpEngine.h"
|
||||
|
||||
namespace js {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче