зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team. a=merge
This commit is contained in:
Коммит
3e2bf940ce
|
@ -1042,3 +1042,6 @@ pref("dom.mapped_arraybuffer.enabled", true);
|
|||
|
||||
// UDPSocket API
|
||||
pref("dom.udpsocket.enabled", true);
|
||||
|
||||
// Enable TV Manager API
|
||||
pref("dom.tv.enabled", true);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="28be739bcdcbc9eb91c0bdbff1f7d3eab717969b"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
[
|
||||
{
|
||||
"size": 120750384,
|
||||
"digest": "0e0a0b0dcca020e3283ce8deb33d0eed48fab16ef2fd919120bd7b5abba00713210be17f466d11bf77cca3c9e3b663805be61774476cc669f0a75736d901edfd",
|
||||
"size": 91247216,
|
||||
"digest": "2b4be549f98695488ea7288d9e7f8ac0fa45112bedefa485a6e016c4af73fa21bb6b3992beda516f268417207c5deb57afad3959d3b1fbd07d5269b3a6be6a27",
|
||||
"algorithm": "sha512",
|
||||
"filename": "backup-flame.tar.xz",
|
||||
"comment": "v188-1"
|
||||
"filename": "backup-flame.tar.xz"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="28be739bcdcbc9eb91c0bdbff1f7d3eab717969b"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "ab5fb977047100ac985402e022d24da1dea68f24",
|
||||
"revision": "4830af61b34d751c57da15abfc2efcda571b12c0",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="28be739bcdcbc9eb91c0bdbff1f7d3eab717969b"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a9a847920b51b79c4ad4ad339f0a005777a6228c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0dfc1996eb583c8b507a82bf6b8319624bba23ea"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -197,6 +197,7 @@
|
|||
@BINPATH@/components/dom_telephony.xpt
|
||||
@BINPATH@/components/dom_threads.xpt
|
||||
@BINPATH@/components/dom_traversal.xpt
|
||||
@BINPATH@/components/dom_tv.xpt
|
||||
@BINPATH@/components/dom_views.xpt
|
||||
@BINPATH@/components/dom_voicemail.xpt
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
addon1.xpi
|
||||
|
@ -16,6 +15,7 @@ support-files =
|
|||
code_blackboxing_two.js
|
||||
code_breakpoints-break-on-last-line-of-script-on-reload.js
|
||||
code_breakpoints-other-tabs.js
|
||||
code_frame-script.js
|
||||
code_function-search-01.js
|
||||
code_function-search-02.js
|
||||
code_function-search-03.js
|
||||
|
@ -98,233 +98,452 @@ support-files =
|
|||
testactors.js
|
||||
|
||||
[browser_dbg_aaa_run_first_leaktest.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_addonactor.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_addon-sources.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_addon-modules.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_addon-modules-unpacked.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_addon-panels.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_addon-console.js]
|
||||
skip-if = os == 'win' # bug 1005274
|
||||
skip-if = e10s || os == 'win' # bug 1005274
|
||||
[browser_dbg_auto-pretty-print-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_auto-pretty-print-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_bfcache.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_blackboxing-01.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_blackboxing-02.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_blackboxing-03.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_blackboxing-04.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_blackboxing-05.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_blackboxing-06.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_breadcrumbs-access.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-07.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-08.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_break-on-dom-event-01.js]
|
||||
skip-if = os == "mac" || e10s # Bug 895426
|
||||
skip-if = e10s || os == "mac" || e10s # Bug 895426
|
||||
[browser_dbg_break-on-dom-event-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-actual-location.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-actual-location2.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-button-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-button-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-contextmenu-add.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-contextmenu.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-disabled-reload.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-editor.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-highlight.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-new-script.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-other-tabs.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-pane.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_breakpoints-reload.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_chrome-create.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_chrome-debugging.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_clean-exit-window.js]
|
||||
skip-if = true # Bug 933950 (leaky test)
|
||||
[browser_dbg_clean-exit.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_closure-inspection.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_cmd-blackbox.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_cmd-break.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_cmd-dbg.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_conditional-breakpoints-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_conditional-breakpoints-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_conditional-breakpoints-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_conditional-breakpoints-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_server-conditional-bp-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_server-conditional-bp-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_server-conditional-bp-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_server-conditional-bp-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_controller-evaluate-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_controller-evaluate-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_debugger-statement.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_editor-contextmenu.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_editor-mode.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_event-listeners-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_event-listeners-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_event-listeners-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_file-reload.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_function-display-name.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_global-method-override.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_globalactor.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_hit-counts-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_hit-counts-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_host-layout.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_iframes.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_instruments-pane-collapse.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_interrupts.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_listaddons.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_listtabs-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_listtabs-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_listtabs-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_location-changes-01-simple.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_location-changes-02-blank.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_location-changes-03-new.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_location-changes-04-breakpoint.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_multiple-windows.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_navigation.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_no-page-sources.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_on-pause-highlight.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_on-pause-raise.js]
|
||||
skip-if = os == "linux" || e10s # Bug 888811 & bug 891176
|
||||
skip-if = e10s || os == "linux" || e10s # Bug 888811 & bug 891176
|
||||
[browser_dbg_optimized-out-vars.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_panel-size.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-07.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-08.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-09.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_parser-10.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pause-exceptions-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pause-exceptions-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pause-resume.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pause-warning.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_paused-keybindings.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-07.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-08.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-09.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-10.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-11.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-12.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-13.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_pretty-print-on-paused.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_progress-listener-bug.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_reload-preferred-script-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_reload-preferred-script-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_reload-preferred-script-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_reload-same-script.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_scripts-switching-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_scripts-switching-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_scripts-switching-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-autofill-identifier.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-basic-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-basic-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-basic-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-basic-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-global-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-global-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-global-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-global-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-global-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-global-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-popup-jank.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-sources-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-sources-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-sources-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_search-symbols.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_searchbox-help-popup-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_searchbox-help-popup-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_searchbox-parse.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_source-maps-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_source-maps-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_source-maps-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_source-maps-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_sources-cache.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_sources-labels.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_sources-sorting.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_split-console-paused-reload.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_stack-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_stack-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_stack-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_stack-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_stack-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_stack-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_stack-07.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_step-out.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tabactor-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tabactor-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_terminate-on-tab-close.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-07.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_tracing-08.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-accessibility.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-data.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-edit-cancel.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-edit-click.js]
|
||||
skip-if = (os == 'mac' || os == 'win') && (debug == false) # Bug 986166
|
||||
skip-if = e10s || (os == 'mac' || os == 'win') && (debug == false) # Bug 986166
|
||||
[browser_dbg_variables-view-edit-getset-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-edit-getset-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-edit-value.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-edit-watch.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-filter-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-filter-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-filter-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-filter-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-filter-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-filter-pref.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-filter-searchbox.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-frame-parameters-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-frame-parameters-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-frame-parameters-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-frame-with.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-frozen-sealed-nonext.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
skip-if = e10s || buildapp == 'mulet'
|
||||
[browser_dbg_variables-view-hide-non-enums.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-large-array-buffer.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-override-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-override-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-04.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-05.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-06.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-07.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-08.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-09.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-10.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-11.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-12.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-13.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-14.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-15.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-popup-16.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-reexpand-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-reexpand-02.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-reexpand-03.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_variables-view-webidl.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_watch-expressions-01.js]
|
||||
skip-if = e10s
|
||||
[browser_dbg_watch-expressions-02.js]
|
||||
skip-if = e10s
|
||||
|
|
|
@ -7,12 +7,11 @@
|
|||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gTab, gPanel, gDebugger;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
|
||||
|
@ -48,7 +47,6 @@ function testBlackBoxReload() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
});
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
|
||||
const BLACKBOXME_URL = EXAMPLE_URL + "code_blackboxing_blackboxme.js"
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gTab, gPanel, gDebugger;
|
||||
let gFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
|
@ -44,15 +43,12 @@ function testBlackBoxStack() {
|
|||
"And one of them should be the combined black boxed frames.");
|
||||
});
|
||||
|
||||
// Spin the event loop before causing the debuggee to pause, to allow
|
||||
// this function to return first.
|
||||
executeSoon(() => gDebuggee.runTest());
|
||||
callInTab(gTab, "runTest");
|
||||
return finished;
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gFrames = null;
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
|
||||
const BLACKBOXME_URL = EXAMPLE_URL + "code_blackboxing_blackboxme.js"
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gTab, gPanel, gDebugger;
|
||||
let gFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
|
@ -28,7 +27,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.runTest();
|
||||
callInTab(gTab, "runTest");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -52,7 +51,6 @@ function testBlackBoxSource() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gFrames = null;
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
|
||||
const BLACKBOXME_URL = EXAMPLE_URL + "code_blackboxing_blackboxme.js"
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gTab, gPanel, gDebugger;
|
||||
let gFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
|
@ -46,15 +45,12 @@ function testBlackBoxStack() {
|
|||
"And 'one', 'two', and 'three' should each have their own black boxed frame.");
|
||||
});
|
||||
|
||||
// Spin the event loop before causing the debuggee to pause, to allow
|
||||
// this function to return first.
|
||||
executeSoon(() => gDebuggee.one());
|
||||
callInTab(gTab, "one");
|
||||
return finished;
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gFrames = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gTab, gPanel, gDebugger;
|
||||
let gDeck;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gDeck = gDebugger.document.getElementById("editor-deck");
|
||||
|
@ -64,7 +63,6 @@ function getEditorBlackboxMessageButton() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gDeck = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gTab, gPanel, gDebugger;
|
||||
let gSources;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
|
@ -26,7 +25,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.runTest();
|
||||
callInTab(gTab, "runTest");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -50,7 +49,6 @@ function testBlackBox() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSources = null;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
dump("Frame script loaded.\n");
|
||||
|
||||
addMessageListener("test:call", function (message) {
|
||||
dump("Calling function with name " + message.data + ".\n");
|
||||
|
||||
XPCNativeWrapper.unwrap(content)[message.data]();
|
||||
});
|
|
@ -28,6 +28,7 @@ let TargetFactory = devtools.TargetFactory;
|
|||
let Toolbox = devtools.Toolbox;
|
||||
|
||||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
|
||||
const FRAME_SCRIPT_URL = getRootDirectory(gTestPath) + "code_frame-script.js";
|
||||
|
||||
gDevTools.testing = true;
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
|
@ -86,6 +87,9 @@ function addTab(aUrl, aWindow) {
|
|||
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
info("Loading frame script with url " + FRAME_SCRIPT_URL + ".");
|
||||
linkedBrowser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
|
||||
|
||||
linkedBrowser.addEventListener("load", function onLoad() {
|
||||
linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
info("Tab added and finished loading: " + aUrl);
|
||||
|
@ -936,4 +940,28 @@ function popPrefs() {
|
|||
let deferred = promise.defer();
|
||||
SpecialPowers.popPrefEnv(deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
|
||||
function sendMessageToTab(tab, name, data, objects) {
|
||||
info("Sending message with name " + name + " to tab.");
|
||||
|
||||
tab.linkedBrowser.messageManager.sendAsyncMessage(name, data, objects);
|
||||
}
|
||||
|
||||
function waitForMessageFromTab(tab, name) {
|
||||
info("Waiting for message with name " + name + " from tab.");
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
let messageManager = tab.linkedBrowser.messageManager;
|
||||
messageManager.addMessageListener(name, function listener(message) {
|
||||
messageManager.removeMessageListener(name, listener);
|
||||
resolve(message);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function callInTab(tab, name) {
|
||||
info("Calling function with name " + name + " in tab.");
|
||||
|
||||
sendMessageToTab(tab, "test:call", name);
|
||||
}
|
||||
|
|
|
@ -231,6 +231,7 @@
|
|||
@BINPATH@/components/dom_stylesheets.xpt
|
||||
@BINPATH@/components/dom_telephony.xpt
|
||||
@BINPATH@/components/dom_traversal.xpt
|
||||
@BINPATH@/components/dom_tv.xpt
|
||||
@BINPATH@/components/dom_voicemail.xpt
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@BINPATH@/components/dom_webspeechrecognition.xpt
|
||||
|
|
|
@ -125,6 +125,14 @@ PluginContent.prototype = {
|
|||
pluginTag = pluginHost.getPluginTagForType(pluginElement.actualType);
|
||||
pluginName = BrowserUtils.makeNicePluginName(pluginTag.name);
|
||||
|
||||
// Convert this from nsIPluginTag so it can be serialized.
|
||||
let properties = ["name", "description", "filename", "version", "enabledState"];
|
||||
let pluginTagCopy = {};
|
||||
for (let prop of properties) {
|
||||
pluginTagCopy[prop] = pluginTag[prop];
|
||||
}
|
||||
pluginTag = pluginTagCopy;
|
||||
|
||||
permissionString = pluginHost.getPermissionStringForType(pluginElement.actualType);
|
||||
fallbackType = pluginElement.defaultFallbackType;
|
||||
blocklistState = pluginHost.getBlocklistStateForType(pluginElement.actualType);
|
||||
|
|
|
@ -3127,6 +3127,15 @@ nsDocShell::NotifyAsyncPanZoomStarted(const mozilla::CSSIntPoint aScrollPos)
|
|||
mScrollObservers.RemoveElement(ref);
|
||||
}
|
||||
}
|
||||
|
||||
// Also notify child docshell
|
||||
for (uint32_t i = 0; i < mChildList.Length(); ++i) {
|
||||
nsCOMPtr<nsIDocShell> kid = do_QueryInterface(ChildAt(i));
|
||||
if (kid) {
|
||||
nsDocShell* docShell = static_cast<nsDocShell*>(kid.get());
|
||||
docShell->NotifyAsyncPanZoomStarted(aScrollPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3142,6 +3151,15 @@ nsDocShell::NotifyAsyncPanZoomStopped(const mozilla::CSSIntPoint aScrollPos)
|
|||
mScrollObservers.RemoveElement(ref);
|
||||
}
|
||||
}
|
||||
|
||||
// Also notify child docshell
|
||||
for (uint32_t i = 0; i < mChildList.Length(); ++i) {
|
||||
nsCOMPtr<nsIDocShell> kid = do_QueryInterface(ChildAt(i));
|
||||
if (kid) {
|
||||
nsDocShell* docShell = static_cast<nsDocShell*>(kid.get());
|
||||
docShell->NotifyAsyncPanZoomStopped(aScrollPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -10391,8 +10409,8 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(do_QueryInterface(channel));
|
||||
if (httpChannelInternal) {
|
||||
if (aForceAllowCookies) {
|
||||
httpChannelInternal->SetForceAllowThirdPartyCookie(true);
|
||||
}
|
||||
httpChannelInternal->SetThirdPartyFlags(nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
|
||||
}
|
||||
if (aFirstParty) {
|
||||
httpChannelInternal->SetDocumentURI(aURI);
|
||||
} else {
|
||||
|
|
|
@ -493,6 +493,11 @@ this.PermissionsTable = { geolocation: {
|
|||
trusted: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"tv": {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "mozilla/dom/ServiceWorkerContainer.h"
|
||||
#include "mozilla/dom/Telephony.h"
|
||||
#include "mozilla/dom/Voicemail.h"
|
||||
#include "mozilla/dom/TVManager.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "nsISiteSpecificUserAgent.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
@ -173,6 +174,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileMessageManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTVManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnections)
|
||||
|
@ -256,6 +258,10 @@ Navigator::Invalidate()
|
|||
mVoicemail = nullptr;
|
||||
}
|
||||
|
||||
if (mTVManager) {
|
||||
mTVManager = nullptr;
|
||||
}
|
||||
|
||||
if (mConnection) {
|
||||
mConnection->Shutdown();
|
||||
mConnection = nullptr;
|
||||
|
@ -1093,7 +1099,10 @@ Navigator::SendBeacon(const nsAString& aUrl,
|
|||
}
|
||||
bool isForeign = true;
|
||||
thirdPartyUtil->IsThirdPartyWindow(mWindow, uri, &isForeign);
|
||||
httpChannelInternal->SetForceAllowThirdPartyCookie(!isForeign);
|
||||
uint32_t thirdPartyFlags = isForeign ?
|
||||
0 :
|
||||
nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
|
||||
httpChannelInternal->SetThirdPartyFlags(thirdPartyFlags);
|
||||
|
||||
nsCString mimeType;
|
||||
if (!aData.IsNull()) {
|
||||
|
@ -1579,6 +1588,19 @@ Navigator::GetMozTelephony(ErrorResult& aRv)
|
|||
return mTelephony;
|
||||
}
|
||||
|
||||
TVManager*
|
||||
Navigator::GetTv()
|
||||
{
|
||||
if (!mTVManager) {
|
||||
if (!mWindow) {
|
||||
return nullptr;
|
||||
}
|
||||
mTVManager = TVManager::Create(mWindow);
|
||||
}
|
||||
|
||||
return mTVManager;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
already_AddRefed<Promise>
|
||||
Navigator::GetMobileIdAssertion(const MobileIdOptions& aOptions,
|
||||
|
@ -2323,6 +2345,37 @@ Navigator::HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasTVSupport(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
JS::Rooted<JSObject*> global(aCx, aGlobal);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global);
|
||||
if (!win) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Just for testing, we can enable TV for any kind of app.
|
||||
if (Preferences::GetBool("dom.testing.tv_enabled_for_hosted_apps", false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIDocument* doc = win->GetExtantDoc();
|
||||
if (!doc || !doc->NodePrincipal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIPrincipal* principal = doc->NodePrincipal();
|
||||
uint16_t status;
|
||||
if (NS_FAILED(principal->GetAppStatus(&status))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only support TV Manager API for certified apps for now.
|
||||
return status == nsIPrincipal::APP_STATUS_CERTIFIED;
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<nsPIDOMWindow>
|
||||
Navigator::GetWindowFromGlobal(JSObject* aGlobal)
|
||||
|
|
|
@ -93,6 +93,7 @@ class PowerManager;
|
|||
class CellBroadcast;
|
||||
class Telephony;
|
||||
class Voicemail;
|
||||
class TVManager;
|
||||
|
||||
namespace time {
|
||||
class TimeManager;
|
||||
|
@ -223,6 +224,7 @@ public:
|
|||
MobileMessageManager* GetMozMobileMessage();
|
||||
Telephony* GetMozTelephony(ErrorResult& aRv);
|
||||
Voicemail* GetMozVoicemail(ErrorResult& aRv);
|
||||
TVManager* GetTv();
|
||||
network::Connection* GetConnection(ErrorResult& aRv);
|
||||
nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
|
||||
MediaDevices* GetMediaDevices(ErrorResult& aRv);
|
||||
|
@ -305,6 +307,8 @@ public:
|
|||
static bool HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal);
|
||||
#endif
|
||||
|
||||
static bool HasTVSupport(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return GetWindow();
|
||||
|
@ -334,6 +338,7 @@ private:
|
|||
nsRefPtr<MobileMessageManager> mMobileMessageManager;
|
||||
nsRefPtr<Telephony> mTelephony;
|
||||
nsRefPtr<Voicemail> mVoicemail;
|
||||
nsRefPtr<TVManager> mTVManager;
|
||||
nsRefPtr<network::Connection> mConnection;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsRefPtr<MobileConnectionArray> mMobileConnections;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 sts=2 ts=8 et 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/. */
|
||||
|
@ -166,12 +168,17 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
|
|||
|
||||
nsresult rv;
|
||||
bool doForce = false;
|
||||
bool checkWindowChain = true;
|
||||
bool parentIsThird = false;
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
|
||||
do_QueryInterface(aChannel);
|
||||
if (httpChannelInternal) {
|
||||
rv = httpChannelInternal->GetForceAllowThirdPartyCookie(&doForce);
|
||||
uint32_t flags;
|
||||
rv = httpChannelInternal->GetThirdPartyFlags(&flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
doForce = (flags & nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
|
||||
|
||||
// If aURI was not supplied, and we're forcing, then we're by definition
|
||||
// not foreign. If aURI was supplied, we still want to check whether it's
|
||||
// foreign with respect to the channel URI. (The forcing only applies to
|
||||
|
@ -180,6 +187,28 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
|
|||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_THIRD_PARTY) {
|
||||
// Check that the two PARENT_IS_{THIRD,SAME}_PARTY are mutually exclusive.
|
||||
MOZ_ASSERT(!(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY));
|
||||
|
||||
// If we're not forcing and we know that the window chain of the channel
|
||||
// is third party, then we know now that we're third party.
|
||||
if (!doForce) {
|
||||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
checkWindowChain = false;
|
||||
parentIsThird = true;
|
||||
} else {
|
||||
// In e10s, we can't check the parent chain in the parent, so we do so
|
||||
// in the child and send the result to the parent.
|
||||
// Note that we only check the window chain if neither
|
||||
// THIRD_PARTY_PARENT_IS_* flag is set.
|
||||
checkWindowChain = !(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY);
|
||||
parentIsThird = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain the URI from the channel, and its base domain.
|
||||
|
@ -206,6 +235,12 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
|
|||
}
|
||||
}
|
||||
|
||||
// If we've already computed this in the child process, we're done.
|
||||
if (!checkWindowChain) {
|
||||
*aResult = parentIsThird;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find the associated window and its parent window.
|
||||
nsCOMPtr<nsILoadContext> ctx;
|
||||
NS_QueryNotificationCallbacks(aChannel, ctx);
|
||||
|
|
|
@ -4491,13 +4491,19 @@ nsContentUtils::AppendNodeTextContent(nsINode* aNode, bool aDeep,
|
|||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::HasNonEmptyTextContent(nsINode* aNode)
|
||||
nsContentUtils::HasNonEmptyTextContent(nsINode* aNode,
|
||||
TextContentDiscoverMode aDiscoverMode)
|
||||
{
|
||||
for (nsIContent* child = aNode->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
if (child->IsNodeOfType(nsINode::eTEXT) &&
|
||||
child->TextLength() > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aDiscoverMode == eRecurseIntoChildren &&
|
||||
HasNonEmptyTextContent(child, aDiscoverMode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1240,12 +1240,19 @@ public:
|
|||
nsAString& aResult, const mozilla::fallible_t&);
|
||||
|
||||
/**
|
||||
* Utility method that checks if a given node has any non-empty
|
||||
* children.
|
||||
* NOTE! This method does not descend recursivly into elements.
|
||||
* Though it would be easy to make it so if needed
|
||||
* Utility method that checks if a given node has any non-empty children. This
|
||||
* method does not descend recursively into children by default.
|
||||
*
|
||||
* @param aDiscoverMode Set to eRecurseIntoChildren to descend recursively
|
||||
* into children.
|
||||
*/
|
||||
static bool HasNonEmptyTextContent(nsINode* aNode);
|
||||
enum TextContentDiscoverMode MOZ_ENUM_TYPE(uint8_t) {
|
||||
eRecurseIntoChildren, eDontRecurseIntoChildren
|
||||
};
|
||||
|
||||
static bool HasNonEmptyTextContent(
|
||||
nsINode* aNode,
|
||||
TextContentDiscoverMode aDiscoverMode = eDontRecurseIntoChildren);
|
||||
|
||||
/**
|
||||
* Delete strings allocated for nsContentList matches
|
||||
|
|
|
@ -707,6 +707,8 @@ GK_ATOM(onconnected, "onconnected")
|
|||
GK_ATOM(onconnecting, "onconnecting")
|
||||
GK_ATOM(oncontextmenu, "oncontextmenu")
|
||||
GK_ATOM(oncopy, "oncopy")
|
||||
GK_ATOM(oncurrentchannelchanged, "oncurrentchannelchanged")
|
||||
GK_ATOM(oncurrentsourcechanged, "oncurrentsourcechanged")
|
||||
GK_ATOM(oncut, "oncut")
|
||||
GK_ATOM(ondatachange, "ondatachange")
|
||||
GK_ATOM(ondataerror, "ondataerror")
|
||||
|
@ -746,6 +748,7 @@ GK_ATOM(ondragleave, "ondragleave")
|
|||
GK_ATOM(ondragover, "ondragover")
|
||||
GK_ATOM(ondragstart, "ondragstart")
|
||||
GK_ATOM(ondrop, "ondrop")
|
||||
GK_ATOM(oneitbroadcasted, "oneitbroadcasted")
|
||||
GK_ATOM(onenabled, "onenabled")
|
||||
GK_ATOM(onenterpincodereq, "onenterpincodereq")
|
||||
GK_ATOM(onemergencycbmodechange, "onemergencycbmodechange")
|
||||
|
@ -848,6 +851,7 @@ GK_ATOM(onreset, "onreset")
|
|||
GK_ATOM(onresuming, "onresuming")
|
||||
GK_ATOM(onresize, "onresize")
|
||||
GK_ATOM(onrtchange, "onrtchange")
|
||||
GK_ATOM(onscanningstatechanged, "onscanningstatechanged")
|
||||
GK_ATOM(onscostatuschanged, "onscostatuschanged")
|
||||
GK_ATOM(onscroll, "onscroll")
|
||||
GK_ATOM(onselect, "onselect")
|
||||
|
|
|
@ -202,6 +202,7 @@
|
|||
#include "prrng.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "TimeChangeObserver.h"
|
||||
#include "TouchCaret.h"
|
||||
#include "mozilla/dom/AudioContext.h"
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
|
||||
|
@ -9356,6 +9357,24 @@ nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, in
|
|||
SelectionChangeEventInit init;
|
||||
init.mBubbles = true;
|
||||
if (aSel) {
|
||||
bool isTouchCaretVisible = false;
|
||||
bool isCollapsed = aSel->Collapsed();
|
||||
|
||||
nsIPresShell *shell = mDoc->GetShell();
|
||||
if (shell) {
|
||||
nsRefPtr<TouchCaret> touchCaret = shell->GetTouchCaret();
|
||||
if (touchCaret) {
|
||||
isTouchCaretVisible = touchCaret->GetVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch selection change events when touch caret is visible even if selection
|
||||
// is collapsed because it could be the shortcut mode, otherwise ignore this
|
||||
// UpdateCommands
|
||||
if (isCollapsed && !isTouchCaretVisible) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Selection* selection = static_cast<Selection*>(aSel);
|
||||
int32_t rangeCount = selection->GetRangeCount();
|
||||
nsLayoutUtils::RectAccumulator accumulator;
|
||||
|
|
|
@ -297,6 +297,10 @@ const kEventConstructors = {
|
|||
return new MozNFCPeerEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
MozNFCTagEvent: { create: function (aName, aProps) {
|
||||
return new MozNFCTagEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
MozOtaStatusEvent: { create: function (aName, aProps) {
|
||||
return new MozOtaStatusEvent(aName, aProps);
|
||||
},
|
||||
|
@ -468,6 +472,38 @@ const kEventConstructors = {
|
|||
return new TransitionEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVCurrentChannelChangedEvent: { create: function (aName, aProps) {
|
||||
return new TVCurrentChannelChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVCurrentProgramChangedEvent: { create: function (aName, aProps) {
|
||||
return new TVCurrentProgramChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVCurrentSourceChangedEvent: { create: function (aName, aProps) {
|
||||
return new TVCurrentSourceChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVEITBroadcastedEvent: { create: function (aName, aProps) {
|
||||
return new TVEITBroadcastedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVParentalControlChangedEvent: { create: function (aName, aProps) {
|
||||
return new TVParentalControlChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVProtectionStateChangedEvent: { create: function (aName, aProps) {
|
||||
return new TVProtectionStateChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVScanningStateChangedEvent: { create: function (aName, aProps) {
|
||||
return new TVScanningStateChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
TVTunerChangedEvent: { create: function (aName, aProps) {
|
||||
return new TVTunerChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
UIEvent: { create: function (aName, aProps) {
|
||||
return new UIEvent(aName, aProps);
|
||||
},
|
||||
|
|
|
@ -606,11 +606,6 @@ void HTMLMediaElement::ShutdownDecoder()
|
|||
{
|
||||
RemoveMediaElementFromURITable();
|
||||
NS_ASSERTION(mDecoder, "Must have decoder to shut down");
|
||||
// TODO: This should be handled by ChangeNetworkState() so we have only one
|
||||
// place to call StopProgress().
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING) {
|
||||
mDecoder->StopProgress();
|
||||
}
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
@ -1792,11 +1787,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded)
|
|||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
#ifdef MOZ_EME
|
||||
if (ContainsRestrictedContent()) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
OutputMediaStream* out = mOutputStreams.AppendElement();
|
||||
#ifdef DEBUG
|
||||
// Estimate hints based on the type of the media element
|
||||
|
@ -4001,21 +3992,10 @@ HTMLMediaElement::GetMediaKeys() const
|
|||
return mMediaKeys;
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::ContainsRestrictedContent()
|
||||
{
|
||||
return GetMediaKeys() != nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (MozAudioCaptured()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global =
|
||||
do_QueryInterface(OwnerDoc()->GetInnerWindow());
|
||||
if (!global) {
|
||||
|
@ -4039,7 +4019,7 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
|
|||
mMediaKeys->Shutdown();
|
||||
mMediaKeys = nullptr;
|
||||
}
|
||||
|
||||
|
||||
mMediaKeys = aMediaKeys;
|
||||
if (mMediaKeys) {
|
||||
if (NS_FAILED(mMediaKeys->Bind(this))) {
|
||||
|
@ -4050,8 +4030,6 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
|
|||
if (mDecoder) {
|
||||
mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
|
||||
}
|
||||
// Update the same-origin status.
|
||||
NotifyDecoderPrincipalChanged();
|
||||
}
|
||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
return promise.forget();
|
||||
|
|
|
@ -550,7 +550,6 @@ public:
|
|||
// in the URL bar of the browser window.
|
||||
already_AddRefed<nsIPrincipal> GetTopLevelPrincipal();
|
||||
|
||||
bool ContainsRestrictedContent();
|
||||
#endif // MOZ_EME
|
||||
|
||||
bool MozAutoplayEnabled() const
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "nsPresState.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsRuleData.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsTextEditorState.h"
|
||||
#include "nsIController.h"
|
||||
|
@ -407,6 +408,18 @@ void
|
|||
HTMLTextAreaElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData)
|
||||
{
|
||||
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
|
||||
// wrap=off
|
||||
nsCSSValue* whiteSpace = aData->ValueForWhiteSpace();
|
||||
if (whiteSpace->GetUnit() == eCSSUnit_Null) {
|
||||
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::wrap);
|
||||
if (value && value->Type() == nsAttrValue::eString &&
|
||||
value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
|
||||
whiteSpace->SetIntValue(NS_STYLE_WHITESPACE_PRE, eCSSUnit_Enumerated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aData);
|
||||
nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
|
||||
}
|
||||
|
@ -431,7 +444,13 @@ HTMLTextAreaElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|||
NS_IMETHODIMP_(bool)
|
||||
HTMLTextAreaElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
||||
{
|
||||
static const MappedAttributeEntry attributes[] {
|
||||
{ &nsGkAtoms::wrap },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const MappedAttributeEntry* const map[] = {
|
||||
attributes,
|
||||
sDivAlignAttributeMap,
|
||||
sCommonAttributeMap,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea rows="10" cols="25" wrap="off">
|
||||
0 1 2 3
|
||||
4 5
|
||||
|
||||
6 7 8
|
||||
9
|
||||
|
||||
|
||||
This is a long line that could wrap.
|
||||
</textarea>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea rows="10" cols="25" style="white-space: pre">
|
||||
0 1 2 3
|
||||
4 5
|
||||
|
||||
6 7 8
|
||||
9
|
||||
|
||||
|
||||
This is a long line that could wrap.
|
||||
</textarea>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea rows="10" cols="25" wrap="off" style="white-space: normal">
|
||||
0 1 2 3
|
||||
4 5
|
||||
|
||||
6 7 8
|
||||
9
|
||||
|
||||
|
||||
This is a long line that could wrap.
|
||||
</textarea>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea rows="10" cols="25" style="white-space: normal">
|
||||
0 1 2 3 4 5 6 7 8 9 This is a long line that could wrap.
|
||||
</textarea>
|
||||
</body>
|
||||
</html>
|
|
@ -5,6 +5,9 @@ include toblob-todataurl/reftest.list
|
|||
skip-if(B2G) == 41464-1a.html 41464-1-ref.html
|
||||
skip-if(B2G) == 41464-1b.html 41464-1-ref.html
|
||||
== 52019-1.html 52019-1-ref.html
|
||||
== 82711-1.html 82711-1-ref.html
|
||||
== 82711-2.html 82711-2-ref.html
|
||||
!= 82711-1-ref.html 82711-2-ref.html
|
||||
!= 468263-1a.html about:blank
|
||||
!= 468263-1b.html about:blank
|
||||
!= 468263-1c.html about:blank
|
||||
|
|
|
@ -249,14 +249,34 @@ this.Keyboard = {
|
|||
},
|
||||
|
||||
forwardEvent: function keyboardForwardEvent(newEventName, msg) {
|
||||
this.formMM = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader.messageManager;
|
||||
let mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader.messageManager;
|
||||
if (newEventName === 'Keyboard:FocusChange' &&
|
||||
msg.data.type === 'blur') {
|
||||
// A blur message can't be sent to the keyboard if the focus has
|
||||
// already taken away at first place.
|
||||
// This check is here to prevent problem caused by out-of-order
|
||||
// ipc messages from two processes.
|
||||
if (mm !== this.formMM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.sendToKeyboard(newEventName, msg.data);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.formMM = mm;
|
||||
|
||||
this.sendToKeyboard(newEventName, msg.data);
|
||||
return true;
|
||||
},
|
||||
|
||||
handleFocusChange: function keyboardHandleFocusChange(msg) {
|
||||
this.forwardEvent('Keyboard:FocusChange', msg);
|
||||
let isSent = this.forwardEvent('Keyboard:FocusChange', msg);
|
||||
|
||||
if (!isSent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Chrome event, used also to render value selectors; that's why we need
|
||||
// the info about choices / min / max here as well...
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "mozilla/layers/PCompositorChild.h"
|
||||
#include "mozilla/layers/SharedBufferManagerChild.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
|
@ -932,6 +933,13 @@ ContentChild::DeallocPCycleCollectWithLogsChild(PCycleCollectWithLogsChild* /* a
|
|||
return true;
|
||||
}
|
||||
|
||||
mozilla::plugins::PPluginModuleParent*
|
||||
ContentChild::AllocPPluginModuleParent(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
return plugins::PluginModuleContentParent::Create(aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
PContentBridgeChild*
|
||||
ContentChild::AllocPContentBridgeChild(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
|
|
|
@ -101,6 +101,10 @@ public:
|
|||
}
|
||||
nsRefPtr<ContentBridgeParent> mLastBridge;
|
||||
|
||||
PPluginModuleParent *
|
||||
AllocPPluginModuleParent(mozilla::ipc::Transport* transport,
|
||||
base::ProcessId otherProcess) MOZ_OVERRIDE;
|
||||
|
||||
PContentBridgeParent*
|
||||
AllocPContentBridgeParent(mozilla::ipc::Transport* transport,
|
||||
base::ProcessId otherProcess) MOZ_OVERRIDE;
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "mozilla/layers/ImageBridgeParent.h"
|
||||
#include "mozilla/layers/SharedBufferManagerParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
@ -922,6 +923,20 @@ ContentParent::AnswerBridgeToChildProcess(const uint64_t& id)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::AnswerLoadPlugin(const uint32_t& aPluginId)
|
||||
{
|
||||
return mozilla::plugins::SetupBridge(aPluginId, this);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvFindPlugins(const uint32_t& aPluginEpoch,
|
||||
nsTArray<PluginTag>* aPlugins,
|
||||
uint32_t* aNewPluginEpoch)
|
||||
{
|
||||
return mozilla::plugins::FindPluginsForContent(aPluginEpoch, aPlugins, aNewPluginEpoch);
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
Element* aFrameElement,
|
||||
|
|
|
@ -148,6 +148,11 @@ public:
|
|||
bool* aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool AnswerBridgeToChildProcess(const uint64_t& id) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool AnswerLoadPlugin(const uint32_t& aPluginId) MOZ_OVERRIDE;
|
||||
virtual bool RecvFindPlugins(const uint32_t& aPluginEpoch,
|
||||
nsTArray<PluginTag>* aPlugins,
|
||||
uint32_t* aNewPluginEpoch) MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
|
|
@ -25,7 +25,7 @@ CrashReporterChild::GetCrashReporter()
|
|||
break;
|
||||
}
|
||||
case GeckoProcessType_Plugin: {
|
||||
PluginModuleChild* child = PluginModuleChild::current();
|
||||
PluginModuleChild* child = PluginModuleChild::GetChrome();
|
||||
reporters = &child->ManagedPCrashReporterChild();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ include protocol PImageBridge;
|
|||
include protocol PMemoryReportRequest;
|
||||
include protocol PMobileConnection;
|
||||
include protocol PNecko;
|
||||
include protocol PPluginModule;
|
||||
include protocol PPrinting;
|
||||
include protocol PScreenManager;
|
||||
include protocol PSharedBufferManager;
|
||||
|
@ -41,6 +42,7 @@ include JavaScriptTypes;
|
|||
include InputStreamParams;
|
||||
include PTabContext;
|
||||
include URIParams;
|
||||
include PluginTypes;
|
||||
include ProtocolTypes;
|
||||
|
||||
// Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
|
||||
|
@ -328,6 +330,8 @@ union MaybeFileDesc {
|
|||
|
||||
prio(normal upto high) intr protocol PContent
|
||||
{
|
||||
parent spawns PPluginModule;
|
||||
|
||||
parent opens PCompositor;
|
||||
parent opens PSharedBufferManager;
|
||||
parent opens PImageBridge;
|
||||
|
@ -532,6 +536,29 @@ parent:
|
|||
returns (uint64_t id, bool isForApp, bool isForBrowser);
|
||||
intr BridgeToChildProcess(uint64_t id);
|
||||
|
||||
/**
|
||||
* This call connects the content process to a plugin process. While this
|
||||
* call runs, a new PluginModuleParent will be created in the ContentChild
|
||||
* via bridging. The corresponding PluginModuleChild will live in the plugin
|
||||
* process. We use intr semantics here to ensure that the PluginModuleParent
|
||||
* allocation message is dispatched before LoadPlugin returns.
|
||||
*/
|
||||
intr LoadPlugin(uint32_t pluginId);
|
||||
|
||||
/**
|
||||
* This call returns the set of plugins loaded in the chrome
|
||||
* process. However, in many cases this set will not have changed since the
|
||||
* last FindPlugins message. Consequently, the chrome process increments an
|
||||
* epoch number every time the set of plugins changes. The content process
|
||||
* sends up the last epoch it observed. If the epochs are the same, the
|
||||
* chrome process returns no plugins. Otherwise it returns a complete list.
|
||||
*
|
||||
* |pluginEpoch| is the epoch last observed by the content
|
||||
* process. |newPluginEpoch| is the current epoch in the chrome process. If
|
||||
* |pluginEpoch == newPluginEpoch|, then |plugins| will be left empty.
|
||||
*/
|
||||
sync FindPlugins(uint32_t pluginEpoch) returns (PluginTag[] plugins, uint32_t newPluginEpoch);
|
||||
|
||||
async PJavaScript();
|
||||
|
||||
sync PRemoteSpellcheckEngine();
|
||||
|
|
|
@ -499,8 +499,9 @@ void MediaDecoder::Shutdown()
|
|||
|
||||
ChangeState(PLAY_STATE_SHUTDOWN);
|
||||
|
||||
// If we hit this assertion, there might be a bug in network state transition.
|
||||
NS_ASSERTION(!mProgressTimer, "Progress timer should've been stopped.");
|
||||
if (mProgressTimer) {
|
||||
StopProgress();
|
||||
}
|
||||
mOwner = nullptr;
|
||||
|
||||
MediaShutdownManager::Instance().Unregister(this);
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#include <istream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
|
@ -36,7 +36,7 @@ MaybeFinish()
|
|||
FakeDecryptor::FakeDecryptor()
|
||||
: mCallback(nullptr)
|
||||
{
|
||||
assert(!sInstance);
|
||||
MOZ_ASSERT(!sInstance);
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ void FakeDecryptor::DecryptingComplete()
|
|||
void
|
||||
FakeDecryptor::Message(const std::string& aMessage)
|
||||
{
|
||||
assert(sInstance);
|
||||
MOZ_ASSERT(sInstance);
|
||||
const static std::string sid("fake-session-id");
|
||||
sInstance->mCallback->SessionMessage(sid.c_str(), sid.size(),
|
||||
(const uint8_t*)aMessage.c_str(), aMessage.size(),
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
#include "gmp-test-storage.h"
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class WriteRecordClient : public GMPRecordClient {
|
||||
|
@ -119,7 +120,7 @@ GMPErr
|
|||
ReadRecord(const std::string& aRecordName,
|
||||
ReadContinuation* aContinuation)
|
||||
{
|
||||
assert(aContinuation);
|
||||
MOZ_ASSERT(aContinuation);
|
||||
GMPRecord* record;
|
||||
ReadRecordClient* client = new ReadRecordClient();
|
||||
auto err = GMPOpenRecord(aRecordName.c_str(),
|
||||
|
@ -140,14 +141,14 @@ GMPOpenRecord(const char* aName,
|
|||
GMPRecord** aOutRecord,
|
||||
GMPRecordClient* aClient)
|
||||
{
|
||||
assert(g_platform_api);
|
||||
MOZ_ASSERT(g_platform_api);
|
||||
return g_platform_api->createrecord(aName, aNameLength, aOutRecord, aClient);
|
||||
}
|
||||
|
||||
GMPErr
|
||||
GMPRunOnMainThread(GMPTask* aTask)
|
||||
{
|
||||
assert(g_platform_api);
|
||||
MOZ_ASSERT(g_platform_api);
|
||||
return g_platform_api->runonmainthread(aTask);
|
||||
}
|
||||
|
||||
|
@ -180,7 +181,7 @@ GMPErr
|
|||
GMPOpenRecord(const std::string& aRecordName,
|
||||
OpenContinuation* aContinuation)
|
||||
{
|
||||
assert(aContinuation);
|
||||
MOZ_ASSERT(aContinuation);
|
||||
GMPRecord* record;
|
||||
OpenRecordClient* client = new OpenRecordClient();
|
||||
auto err = GMPOpenRecord(aRecordName.c_str(),
|
||||
|
|
|
@ -84,18 +84,6 @@ public:
|
|||
mTaskQueue = aTaskQueue;
|
||||
}
|
||||
|
||||
void BreakCycles()
|
||||
{
|
||||
if (mReader) {
|
||||
mReader->BreakCycles();
|
||||
mReader = nullptr;
|
||||
}
|
||||
mTaskQueue = nullptr;
|
||||
#ifdef MOZ_EME
|
||||
mCDMProxy = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
virtual nsresult SetCDMProxy(CDMProxy* aProxy)
|
||||
{
|
||||
|
|
|
@ -391,7 +391,7 @@ TrackBuffer::BreakCycles()
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
|
||||
mDecoders[i]->BreakCycles();
|
||||
mDecoders[i]->GetReader()->BreakCycles();
|
||||
}
|
||||
mDecoders.Clear();
|
||||
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
const KEYSYSTEM_TYPE = "org.w3.clearkey";
|
||||
|
||||
function bail(message)
|
||||
{
|
||||
return function(err) {
|
||||
ok(false, message);
|
||||
if (err) {
|
||||
info(err);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function ArrayBufferToString(arr)
|
||||
{
|
||||
var str = '';
|
||||
var view = new Uint8Array(arr);
|
||||
for (var i = 0; i < view.length; i++) {
|
||||
str += String.fromCharCode(view[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function StringToArrayBuffer(str)
|
||||
{
|
||||
var arr = new ArrayBuffer(str.length);
|
||||
var view = new Uint8Array(arr);
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
view[i] = str.charCodeAt(i);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function Base64ToHex(str)
|
||||
{
|
||||
var bin = window.atob(str.replace(/-/g, "+").replace(/_/g, "/"));
|
||||
var res = "";
|
||||
for (var i = 0; i < bin.length; i++) {
|
||||
res += ("0" + bin.charCodeAt(i).toString(16)).substr(-2);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function HexToBase64(hex)
|
||||
{
|
||||
var bin = "";
|
||||
for (var i = 0; i < hex.length; i += 2) {
|
||||
bin += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
||||
}
|
||||
return window.btoa(bin).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
|
||||
function UpdateSessionFunc(test) {
|
||||
return function(ev) {
|
||||
var msgStr = ArrayBufferToString(ev.message);
|
||||
var msg = JSON.parse(msgStr);
|
||||
|
||||
info("got message from CDM: " + msgStr);
|
||||
is(msg.type, test.sessionType, "Key session type should match");
|
||||
ok(msg.kids, "message event should contain key ID array");
|
||||
|
||||
var outKeys = [];
|
||||
|
||||
for (var i = 0; i < msg.kids.length; i++) {
|
||||
var id64 = msg.kids[i];
|
||||
var idHex = Base64ToHex(msg.kids[i]).toLowerCase();
|
||||
var key = test.keys[idHex];
|
||||
|
||||
if (key) {
|
||||
info("found key " + key + " for key id " + idHex);
|
||||
outKeys.push({
|
||||
"kty":"oct",
|
||||
"alg":"A128KW",
|
||||
"kid":id64,
|
||||
"k":HexToBase64(key)
|
||||
});
|
||||
} else {
|
||||
bail("Couldn't find key for key id " + idHex);
|
||||
}
|
||||
}
|
||||
|
||||
var update = JSON.stringify({
|
||||
"keys" : outKeys,
|
||||
"type" : msg.type
|
||||
});
|
||||
info("sending update message to CDM: " + update);
|
||||
|
||||
ev.target.update(StringToArrayBuffer(update)).then(function() {
|
||||
info("MediaKeySession update ok!");
|
||||
}, bail("MediaKeySession update failed"));
|
||||
}
|
||||
}
|
||||
|
||||
function PlayFragmented(test, elem)
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
var ms = new MediaSource();
|
||||
elem.src = URL.createObjectURL(ms);
|
||||
|
||||
var sb;
|
||||
var curFragment = 0;
|
||||
|
||||
function addNextFragment() {
|
||||
if (curFragment >= test.fragments.length) {
|
||||
ms.endOfStream();
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
var fragmentFile = test.fragments[curFragment++];
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", fragmentFile);
|
||||
req.responseType = "arraybuffer";
|
||||
|
||||
req.addEventListener("load", function() {
|
||||
sb.appendBuffer(new Uint8Array(req.response));
|
||||
});
|
||||
|
||||
info("fetching resource " + fragmentFile);
|
||||
req.send(null);
|
||||
}
|
||||
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
sb = ms.addSourceBuffer(test.type);
|
||||
sb.addEventListener("updateend", addNextFragment);
|
||||
|
||||
addNextFragment();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Returns a promise that is resovled when the media element is ready to have
|
||||
// its play() function called; when it's loaded MSE fragments, or once the load
|
||||
// has started for non-MSE video.
|
||||
function LoadTest(test, elem)
|
||||
{
|
||||
if (test.fragments) {
|
||||
return PlayFragmented(test, elem);
|
||||
}
|
||||
|
||||
// This file isn't fragmented; set the media source normally.
|
||||
return new Promise(function(resolve, reject) {
|
||||
elem.src = test.name;
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function SetupEME(test, token, params)
|
||||
{
|
||||
var v = document.createElement("video");
|
||||
|
||||
var onSetKeysFail = (params && params.onSetKeysFail)
|
||||
? params.onSetKeysFail
|
||||
: bail(token + " Failed to set MediaKeys on <video> element");
|
||||
|
||||
v.addEventListener("encrypted", function(ev) {
|
||||
info(token + " got encrypted event");
|
||||
MediaKeys.create(KEYSYSTEM_TYPE).then(function(mediaKeys) {
|
||||
info(token + " created MediaKeys object ok");
|
||||
mediaKeys.sessions = [];
|
||||
return v.setMediaKeys(mediaKeys);
|
||||
}, bail("failed to create MediaKeys object")).then(function() {
|
||||
info(token + " set MediaKeys on <video> element ok");
|
||||
|
||||
var session = v.mediaKeys.createSession(test.sessionType);
|
||||
if (params && params.onsessioncreated) {
|
||||
params.onsessioncreated(session);
|
||||
}
|
||||
session.addEventListener("message", UpdateSessionFunc(test));
|
||||
session.generateRequest(ev.initDataType, ev.initData).then(function() {
|
||||
}, bail(token + " Failed to initialise MediaKeySession"));
|
||||
|
||||
}, onSetKeysFail);
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
|
@ -124,7 +124,7 @@ var gPlayTests = [
|
|||
// With first frame a "duplicate" (empty) frame.
|
||||
{ name:"bug500311.ogv", type:"video/ogg", duration:1.96 },
|
||||
// Small audio file
|
||||
{ name:"small-shot.ogg", type:"video/ogg", duration:0.276 },
|
||||
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
|
||||
// More audio in file than video.
|
||||
{ name:"short-video.ogv", type:"video/ogg", duration:1.081 },
|
||||
// First Theora data packet is zero bytes.
|
||||
|
@ -679,13 +679,17 @@ function checkMetadata(msg, e, test) {
|
|||
// Returns the first test from candidates array which we can play with the
|
||||
// installed video backends.
|
||||
function getPlayableVideo(candidates) {
|
||||
var v = document.createElement("video");
|
||||
var resources = candidates.filter(function(x){return /^video/.test(x.type) && v.canPlayType(x.type);});
|
||||
var resources = getPlayableVideos(candidates);
|
||||
if (resources.length > 0)
|
||||
return resources[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPlayableVideos(candidates) {
|
||||
var v = document.createElement("video");
|
||||
return candidates.filter(function(x){return /^video/.test(x.type) && v.canPlayType(x.type);});
|
||||
}
|
||||
|
||||
function getPlayableAudio(candidates) {
|
||||
var v = document.createElement("audio");
|
||||
var resources = candidates.filter(function(x){return /^audio/.test(x.type) && v.canPlayType(x.type);});
|
||||
|
|
|
@ -140,7 +140,6 @@ support-files =
|
|||
dirac.ogg^headers^
|
||||
dynamic_redirect.sjs
|
||||
dynamic_resource.sjs
|
||||
eme.js
|
||||
gizmo-frag-cenc1.m4s
|
||||
gizmo-frag-cenc2.m4s
|
||||
gizmo-frag-cencinit.mp4
|
||||
|
@ -361,11 +360,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
|
|||
[test_defaultMuted.html]
|
||||
[test_delay_load.html]
|
||||
skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
|
||||
[test_eme_canvas_blocked.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
||||
[test_eme_playback.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
||||
[test_eme_stream_capture_blocked.html]
|
||||
[test_encryptedMediaExtensions.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
||||
[test_error_in_video_document.html]
|
||||
skip-if = toolkit == 'android' || (os == 'win' && !debug) || (os == 'mac' && !debug) # bug 608634
|
||||
|
@ -402,7 +397,6 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
|
|||
[test_mediarecorder_record_gum_video_timeslice.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' # mimetype check, bug 969289
|
||||
[test_mediarecorder_record_immediate_stop.html]
|
||||
skip-if = toolkit == 'gonk' && debug
|
||||
[test_mediarecorder_record_no_timeslice.html]
|
||||
skip-if = toolkit == 'gonk' && debug
|
||||
[test_mediarecorder_record_nosrc.html]
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Encrypted Media Extensions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
<script type="text/javascript" src="eme.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
function startTest(test, token)
|
||||
{
|
||||
manager.started(token);
|
||||
|
||||
var sessions = [];
|
||||
|
||||
var v = SetupEME(test, token);
|
||||
v.preload = "auto"; // Required due to "canplay" not firing for MSE unless we do this.
|
||||
|
||||
v.addEventListener("canplay", function(ev) {
|
||||
var video = ev.target;
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = video.videoWidth;
|
||||
canvas.height = video.videoHeight;
|
||||
document.body.appendChild(canvas);
|
||||
var ctx = canvas.getContext("2d");
|
||||
var threwError = false;
|
||||
try {
|
||||
ctx.drawImage(video, 0, 0);
|
||||
} catch (ex) {
|
||||
threwError = true;
|
||||
}
|
||||
ok(threwError, token + " - Should throw an error when trying to draw EME video to canvas.");
|
||||
manager.finished(token);
|
||||
});
|
||||
|
||||
v.addEventListener("error", bail(token + " got error event"));
|
||||
|
||||
LoadTest(test, v);
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
manager.runTests(gEMETests, startTest);
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "media.mediasource.enabled", true ],
|
||||
[ "media.mediasource.ignore_codecs", true ],
|
||||
];
|
||||
|
||||
if (/Linux/.test(navigator.userAgent) ||
|
||||
!document.createElement('video').canPlayType("video/mp4")) {
|
||||
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
|
||||
prefs.push([ "media.fragmented-mp4.exposed", true ]);
|
||||
prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,128 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Encrypted Media Extensions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
<script type="text/javascript" src="eme.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
|
||||
function KeysChangeFunc(session, keys, token) {
|
||||
session.keyIdsReceived = [];
|
||||
for (var keyid in keys) {
|
||||
info("Set " + keyid + " to false in session.keyIdsReceived");
|
||||
session.keyIdsReceived[keyid] = false;
|
||||
}
|
||||
return function(ev) {
|
||||
var session = ev.target;
|
||||
session.gotKeysChanged = true;
|
||||
session.getUsableKeyIds().then(function(keyIds) {
|
||||
for (var k = 0; k < keyIds.length; k++) {
|
||||
var kid = Base64ToHex(window.btoa(ArrayBufferToString(keyIds[k])));
|
||||
ok(kid in session.keyIdsReceived, token + " session.keyIdsReceived contained " + kid + " as expected.");
|
||||
session.keyIdsReceived[kid] = true;
|
||||
}
|
||||
}, bail("Failed to get keyIds"));
|
||||
}
|
||||
}
|
||||
|
||||
function startTest(test, token)
|
||||
{
|
||||
manager.started(token);
|
||||
|
||||
var sessions = [];
|
||||
|
||||
var v = SetupEME(test, token,
|
||||
{
|
||||
onsessioncreated: function(session) {
|
||||
sessions.push(session);
|
||||
session.addEventListener("keyschange", KeysChangeFunc(session, test.keys, token), false);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var gotEncrypted = false;
|
||||
var gotPlaying = false;
|
||||
|
||||
v.addEventListener("encrypted", function(ev) {
|
||||
ok(MediaKeys.isTypeSupported(KEYSYSTEM_TYPE, ev.initDataType, test.type),
|
||||
token + " MediaKeys should support this keysystem");
|
||||
gotEncrypted = true;
|
||||
});
|
||||
|
||||
v.addEventListener("playing", function () { gotPlaying = true; });
|
||||
|
||||
v.addEventListener("ended", function(ev) {
|
||||
ok(true, token + " got ended event");
|
||||
manager.finished(token);
|
||||
|
||||
ok(gotEncrypted, token + " encrypted event should have fired");
|
||||
ok(gotPlaying, token + " playing event should have fired");
|
||||
|
||||
ok(Math.abs(test.duration - v.duration) < 0.1,
|
||||
token + " Duration of video should be corrrect");
|
||||
ok(Math.abs(test.duration - v.currentTime) < 0.1,
|
||||
token + " Current time should be same as duration");
|
||||
|
||||
// Verify all sessions had all keys went sent the to the CDM usable, and thus
|
||||
// that we received keyschange event(s).
|
||||
is(sessions.length, 1, "should have 1 session");
|
||||
for (var i = 0; i < sessions.length; i++) {
|
||||
var session = sessions[i];
|
||||
ok(session.gotKeysChanged, token + " should have received at least one keychange event");
|
||||
for (var kid in session.keyIdsReceived) {
|
||||
ok(session.keyIdsReceived[kid], token + " key with id " + kid + " was usable as expected");
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
v.addEventListener("error", bail(token + " got error event"));
|
||||
|
||||
LoadTest(test, v).then(function(){v.play();}, bail(token + " failed to load"));
|
||||
}
|
||||
|
||||
function testIsTypeSupported()
|
||||
{
|
||||
var t = MediaKeys.isTypeSupported;
|
||||
const clearkey = "org.w3.clearkey";
|
||||
ok(!t("bogus", "bogon", "video/bogus"), "Invalid type.");
|
||||
ok(t(clearkey), "ClearKey supported.");
|
||||
ok(!t(clearkey, "bogus"), "ClearKey bogus initDataType not supported.");
|
||||
ok(t(clearkey, "cenc"), "ClearKey/cenc should be supported.");
|
||||
ok(!t(clearkey, "cenc", "bogus"), "ClearKey/cenc bogus content type should be supported.");
|
||||
ok(t(clearkey, "cenc", 'video/mp4'), "ClearKey/cenc video/mp4 supported.");
|
||||
ok(t(clearkey, "cenc", 'video/mp4; codecs="avc1.4d4015,mp4a.40.2"'), "ClearKey/cenc H.264/AAC supported.");
|
||||
ok(t(clearkey, "cenc", 'audio/mp4'), "ClearKey/cenc audio/mp4 supported.");
|
||||
ok(t(clearkey, "cenc", 'audio/mp4; codecs="mp4a.40.2"'), "ClearKey/cenc AAC LC supported.");
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
testIsTypeSupported();
|
||||
manager.runTests(gEMETests, startTest);
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "media.mediasource.enabled", true ],
|
||||
[ "media.mediasource.ignore_codecs", true ],
|
||||
];
|
||||
|
||||
if (/Linux/.test(navigator.userAgent) ||
|
||||
!document.createElement('video').canPlayType("video/mp4")) {
|
||||
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
|
||||
prefs.push([ "media.fragmented-mp4.exposed", true ]);
|
||||
prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,102 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Encrypted Media Extensions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
<script type="text/javascript" src="eme.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
function startTest(test, token)
|
||||
{
|
||||
// Three cases:
|
||||
// 1. setting MediaKeys on an element captured by MediaElementSource should fail, and
|
||||
// 2. creating a MediaElementSource on a media element with a MediaKeys should fail, and
|
||||
// 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
|
||||
|
||||
// Case 1. setting MediaKeys on an element captured by MediaElementSource should fail.
|
||||
var case1token = token + "_case1";
|
||||
var setKeysFailed = function() {
|
||||
ok(true, case1token + " setMediaKeys failed as expected.");
|
||||
manager.finished(case1token);
|
||||
};
|
||||
var v1 = SetupEME(test, case1token, { onSetKeysFail: setKeysFailed });
|
||||
var context = new AudioContext();
|
||||
var node = context.createMediaElementSource(v1);
|
||||
v1.preload = "auto"; // Required due to "canplay" not firing for MSE unless we do this.
|
||||
v1.addEventListener("error", bail(case1token + " got error event"));
|
||||
v1.addEventListener("canplay", function(ev) {
|
||||
ok(false, case1token + " should never reach canplay, as setMediaKeys should fail");
|
||||
});
|
||||
manager.started(case1token);
|
||||
LoadTest(test, v1);
|
||||
|
||||
|
||||
// Case 2. creating a MediaElementSource on a media element with a MediaKeys should fail.
|
||||
var case2token = token + "_case2";
|
||||
var v2 = SetupEME(test, case2token);
|
||||
v2.preload = "auto"; // Required due to "canplay" not firing for MSE unless we do this.
|
||||
v2.addEventListener("error", bail(case2token + " got error event"));
|
||||
v2.addEventListener("canplay", function(ev) {
|
||||
ok(true, case2token + " should reach canplay");
|
||||
var threw = false;
|
||||
try {
|
||||
var context = new AudioContext();
|
||||
var node = context.createMediaElementSource(v2);
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
}
|
||||
ok(threw, "Should throw an error creating a MediaElementSource on an EME video.");
|
||||
manager.finished(case2token);
|
||||
});
|
||||
manager.started(case2token);
|
||||
LoadTest(test, v2);
|
||||
|
||||
|
||||
// Case 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
|
||||
var case3token = token + "_case3";
|
||||
var v3 = SetupEME(test, case3token);
|
||||
v3.preload = "auto"; // Required due to "canplay" not firing for MSE unless we do this.
|
||||
v3.addEventListener("error", bail(case3token + " got error event"));
|
||||
v3.addEventListener("canplay", function(ev) {
|
||||
ok(true, case3token + " should reach canplay");
|
||||
var threw = false;
|
||||
try {
|
||||
var stream = v3.mozCaptureStreamUntilEnded();
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
}
|
||||
ok(threw, "Should throw an error calling mozCaptureStreamUntilEnded an EME video.");
|
||||
manager.finished(case3token);
|
||||
});
|
||||
manager.started(case3token);
|
||||
LoadTest(test, v3);
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
manager.runTests(gEMETests, startTest);
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "media.mediasource.enabled", true ],
|
||||
[ "media.mediasource.ignore_codecs", true ],
|
||||
];
|
||||
|
||||
if (/Linux/.test(navigator.userAgent) ||
|
||||
!document.createElement('video').canPlayType("video/mp4")) {
|
||||
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
|
||||
prefs.push([ "media.fragmented-mp4.exposed", true ]);
|
||||
prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,278 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Encrypted Media Extensions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
const KEYSYSTEM_TYPE = "org.w3.clearkey";
|
||||
|
||||
function bail(message)
|
||||
{
|
||||
return function(err) {
|
||||
ok(false, message);
|
||||
if (err) {
|
||||
info(err);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function ArrayBufferToString(arr)
|
||||
{
|
||||
var str = '';
|
||||
var view = new Uint8Array(arr);
|
||||
for (var i = 0; i < view.length; i++) {
|
||||
str += String.fromCharCode(view[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function StringToArrayBuffer(str)
|
||||
{
|
||||
var arr = new ArrayBuffer(str.length);
|
||||
var view = new Uint8Array(arr);
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
view[i] = str.charCodeAt(i);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function Base64ToHex(str)
|
||||
{
|
||||
var bin = window.atob(str.replace(/-/g, "+").replace(/_/g, "/"));
|
||||
var res = "";
|
||||
for (var i = 0; i < bin.length; i++) {
|
||||
res += ("0" + bin.charCodeAt(i).toString(16)).substr(-2);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function HexToBase64(hex)
|
||||
{
|
||||
var bin = "";
|
||||
for (var i = 0; i < hex.length; i += 2) {
|
||||
bin += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
||||
}
|
||||
return window.btoa(bin).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
|
||||
function UpdateSessionFunc(test) {
|
||||
return function(ev) {
|
||||
var msgStr = ArrayBufferToString(ev.message);
|
||||
var msg = JSON.parse(msgStr);
|
||||
|
||||
info("got message from CDM: " + msgStr);
|
||||
is(msg.type, test.sessionType, "Key session type should match");
|
||||
ok(msg.kids, "message event should contain key ID array");
|
||||
|
||||
var outKeys = [];
|
||||
|
||||
for (var i = 0; i < msg.kids.length; i++) {
|
||||
var id64 = msg.kids[i];
|
||||
var idHex = Base64ToHex(msg.kids[i]).toLowerCase();
|
||||
var key = test.keys[idHex];
|
||||
|
||||
if (key) {
|
||||
info("found key " + key + " for key id " + idHex);
|
||||
outKeys.push({
|
||||
"kty":"oct",
|
||||
"alg":"A128KW",
|
||||
"kid":id64,
|
||||
"k":HexToBase64(key)
|
||||
});
|
||||
} else {
|
||||
bail("Couldn't find key for key id " + idHex);
|
||||
}
|
||||
}
|
||||
|
||||
var update = JSON.stringify({
|
||||
"keys" : outKeys,
|
||||
"type" : msg.type
|
||||
});
|
||||
info("sending update message to CDM: " + update);
|
||||
|
||||
ev.target.update(StringToArrayBuffer(update)).then(function() {
|
||||
info("MediaKeySession update ok!");
|
||||
}, bail("MediaKeySession update failed"));
|
||||
}
|
||||
}
|
||||
|
||||
function PlayFragmented(test, elem)
|
||||
{
|
||||
var ms = new MediaSource();
|
||||
elem.src = URL.createObjectURL(ms);
|
||||
|
||||
var sb;
|
||||
var curFragment = 0;
|
||||
|
||||
function addNextFragment() {
|
||||
if (curFragment >= test.fragments.length) {
|
||||
ms.endOfStream();
|
||||
elem.play();
|
||||
return;
|
||||
}
|
||||
|
||||
var fragmentFile = test.fragments[curFragment++];
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", fragmentFile);
|
||||
req.responseType = "arraybuffer";
|
||||
|
||||
req.addEventListener("load", function() {
|
||||
sb.appendBuffer(new Uint8Array(req.response));
|
||||
});
|
||||
|
||||
info("fetching resource " + fragmentFile);
|
||||
req.send(null);
|
||||
}
|
||||
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
sb = ms.addSourceBuffer(test.type);
|
||||
sb.addEventListener("updateend", addNextFragment);
|
||||
|
||||
addNextFragment();
|
||||
});
|
||||
}
|
||||
|
||||
function PlayTest(test, elem)
|
||||
{
|
||||
if (test.fragments) {
|
||||
PlayFragmented(test, elem);
|
||||
return;
|
||||
}
|
||||
|
||||
// This file isn't fragmented; set the media source normally.
|
||||
elem.src = test.name;
|
||||
elem.play();
|
||||
}
|
||||
|
||||
function KeysChangeFunc(session, keys) {
|
||||
session.keyIdsReceived = [];
|
||||
for (var keyid in keys) {
|
||||
info("Set " + keyid + " to false in session.keyIdsReceived");
|
||||
session.keyIdsReceived[keyid] = false;
|
||||
}
|
||||
return function(ev) {
|
||||
var session = ev.target;
|
||||
session.gotKeysChanged = true;
|
||||
session.getUsableKeyIds().then(function(keyIds) {
|
||||
for (var k = 0; k < keyIds.length; k++) {
|
||||
var kid = Base64ToHex(window.btoa(ArrayBufferToString(keyIds[k])));
|
||||
ok(kid in session.keyIdsReceived, "session.keyIdsReceived contained " + kid + " as expected.");
|
||||
session.keyIdsReceived[kid] = true;
|
||||
}
|
||||
}, bail("Failed to get keyIds"));
|
||||
}
|
||||
}
|
||||
|
||||
function startTest(test, token)
|
||||
{
|
||||
manager.started(test._token);
|
||||
|
||||
var v = document.createElement("video");
|
||||
var gotEncrypted = false;
|
||||
var gotPlaying = false;
|
||||
|
||||
v.addEventListener("encrypted", function(ev) {
|
||||
gotEncrypted = true;
|
||||
|
||||
info(token + " got encrypted event");
|
||||
ok(MediaKeys.isTypeSupported(KEYSYSTEM_TYPE, ev.initDataType, test.type),
|
||||
token + " MediaKeys should support this keysystem");
|
||||
|
||||
MediaKeys.create(KEYSYSTEM_TYPE).then(function(mediaKeys) {
|
||||
info(token + " created MediaKeys object ok");
|
||||
mediaKeys.sessions = [];
|
||||
return v.setMediaKeys(mediaKeys);
|
||||
}, bail("failed to create MediaKeys object")).then(function() {
|
||||
info(token + " set MediaKeys on <video> element ok");
|
||||
|
||||
ok(MediaKeys.isTypeSupported(KEYSYSTEM_TYPE, ev.initDataType, test.type),
|
||||
"MediaKeys should still support keysystem after CDM created...");
|
||||
|
||||
var session = v.mediaKeys.createSession(test.sessionType);
|
||||
v.mediaKeys.sessions.push(session);
|
||||
session.addEventListener("keyschange", KeysChangeFunc(session, test.keys), false);
|
||||
session.addEventListener("message", UpdateSessionFunc(test));
|
||||
session.generateRequest(ev.initDataType, ev.initData).then(function() {
|
||||
}, bail(token + " Failed to initialise MediaKeySession"));
|
||||
|
||||
}, bail(token + " Failed to set MediaKeys on <video> element"));
|
||||
});
|
||||
|
||||
v.addEventListener("playing", function () { gotPlaying = true; });
|
||||
|
||||
v.addEventListener("ended", function(ev) {
|
||||
ok(true, token + " got ended event");
|
||||
manager.finished(test._token);
|
||||
|
||||
ok(gotEncrypted, token + " encrypted event should have fired");
|
||||
ok(gotPlaying, token + " playing event should have fired");
|
||||
|
||||
ok(Math.abs(test.duration - v.duration) < 0.1,
|
||||
token + " Duration of video should be corrrect");
|
||||
ok(Math.abs(test.duration - v.currentTime) < 0.1,
|
||||
token + " Current time should be same as duration");
|
||||
// Verify all sessions had all keys went sent the to the CDM usable, and thus
|
||||
// that we received keyschange event(s).
|
||||
var sessions = v.mediaKeys.sessions;
|
||||
is(sessions.length, 1, "should have 1 session");
|
||||
for (var i = 0; i < sessions.length; i++) {
|
||||
var session = sessions[i];
|
||||
ok(session.gotKeysChanged, "Should have received at least one keychange event");
|
||||
for (var kid in session.keyIdsReceived) {
|
||||
ok(session.keyIdsReceived[kid], "key with id " + kid + " was usable as expected");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
v.addEventListener("error", bail(token + " got error event"));
|
||||
|
||||
PlayTest(test, v);
|
||||
}
|
||||
|
||||
function testIsTypeSupported()
|
||||
{
|
||||
var t = MediaKeys.isTypeSupported;
|
||||
const clearkey = "org.w3.clearkey";
|
||||
ok(!t("bogus", "bogon", "video/bogus"), "Invalid type.");
|
||||
ok(t(clearkey), "ClearKey supported.");
|
||||
ok(!t(clearkey, "bogus"), "ClearKey bogus initDataType not supported.");
|
||||
ok(t(clearkey, "cenc"), "ClearKey/cenc should be supported.");
|
||||
ok(!t(clearkey, "cenc", "bogus"), "ClearKey/cenc bogus content type should be supported.");
|
||||
ok(t(clearkey, "cenc", 'video/mp4'), "ClearKey/cenc video/mp4 supported.");
|
||||
ok(t(clearkey, "cenc", 'video/mp4; codecs="avc1.4d4015,mp4a.40.2"'), "ClearKey/cenc H.264/AAC supported.");
|
||||
ok(t(clearkey, "cenc", 'audio/mp4'), "ClearKey/cenc audio/mp4 supported.");
|
||||
ok(t(clearkey, "cenc", 'audio/mp4; codecs="mp4a.40.2"'), "ClearKey/cenc AAC LC supported.");
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
testIsTypeSupported();
|
||||
manager.runTests(gEMETests, startTest);
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "media.mediasource.enabled", true ],
|
||||
[ "media.mediasource.ignore_codecs", true ],
|
||||
];
|
||||
|
||||
if (/Linux/.test(navigator.userAgent) ||
|
||||
!document.createElement('video').canPlayType("video/mp4")) {
|
||||
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
|
||||
prefs.push([ "media.fragmented-mp4.exposed", true ]);
|
||||
prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -14,27 +14,33 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=804875
|
|||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=804875">Mozilla Bug 804875</a>
|
||||
|
||||
<video style="border: 4px solid red" controls></video>
|
||||
<canvas></canvas>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
function finish(v) {
|
||||
removeNodeAndSource(v);
|
||||
manager.finished(v.token);
|
||||
}
|
||||
|
||||
function onLoadedMetadata_Audio(e) {
|
||||
var t = e.target;
|
||||
is(t.videoHeight, 0, "videoHeight should be zero when there is no video.");
|
||||
is(t.videoWidth, 0, "videoWidth should be zero when there is no video.");
|
||||
is(t.mozPaintedFrames, 0, "mozPaintedFrames should be zero when there is no video.");
|
||||
is(t.mozFrameDelay, 0, "mozFrameDelay should be zero when there is no video.");
|
||||
is(t.videoHeight, 0, t.name + ": videoHeight should be zero when there is no video.");
|
||||
is(t.videoWidth, 0, t.name + ": videoWidth should be zero when there is no video.");
|
||||
is(t.mozPaintedFrames, 0, t.name + ": mozPaintedFrames should be zero when there is no video.");
|
||||
is(t.mozFrameDelay, 0, t.name + ": mozFrameDelay should be zero when there is no video.");
|
||||
var c = document.getElementsByTagName("canvas")[0].getContext("2d");
|
||||
try {
|
||||
c.drawImage(t, 0, 0, t.videoHeight, t.videoWidth);
|
||||
} catch (e) {
|
||||
ok(true, "Trying to draw to a canvas should throw, since we don't have a frame anymore");
|
||||
SimpleTest.finish();
|
||||
ok(true, t.name + ": Trying to draw to a canvas should throw, since we don't have a frame anymore");
|
||||
finish(t);
|
||||
return;
|
||||
}
|
||||
ok(false, "We should not succeed to draw a video frame on the canvas.");
|
||||
ok(false, t.name + ": We should not succeed to draw a video frame on the canvas.");
|
||||
}
|
||||
|
||||
function onTimeUpdate_Video(e) {
|
||||
|
@ -43,17 +49,17 @@ function onTimeUpdate_Video(e) {
|
|||
return;
|
||||
}
|
||||
t.removeEventListener("timeupdate", onTimeUpdate_Video);
|
||||
ok(t.mozPaintedFrames > 0, "mozPaintedFrames should be positive, is " + t.mozPaintedFrames + ".");
|
||||
ok(t.mozFrameDelay >= 0, "mozFrameDelay should be positive or zero, is " + t.mozFrameDelay + ".");
|
||||
ok(t.mozPaintedFrames > 0, t.name + ": mozPaintedFrames should be positive, is " + t.mozPaintedFrames + ".");
|
||||
ok(t.mozFrameDelay >= 0, t.name + ": mozFrameDelay should be positive or zero, is " + t.mozFrameDelay + ".");
|
||||
|
||||
if (v._firstTime) {
|
||||
if (t._firstTime) {
|
||||
t.src = t.src;
|
||||
v._firstTime = false;
|
||||
t._firstTime = false;
|
||||
} else {
|
||||
var source = getPlayableAudio(gPlayTests);
|
||||
if (!source) {
|
||||
todo("No audio file available.")
|
||||
SimpleTest.finish();
|
||||
finish(t);
|
||||
} else {
|
||||
t.removeEventListener("loadedmetadata", onLoadedMetadata_Video);
|
||||
t.addEventListener("loadedmetadata", onLoadedMetadata_Audio);
|
||||
|
@ -64,22 +70,25 @@ function onTimeUpdate_Video(e) {
|
|||
|
||||
function onLoadedMetadata_Video(e) {
|
||||
var t = e.target;
|
||||
ok(t.videoHeight != 0, "We should have a videoHeight.");
|
||||
ok(t.videoWidth != 0, "We should have a videoWidth.");
|
||||
isnot(t.videoHeight, 0, t.name + ": We should have a videoHeight.");
|
||||
isnot(t.videoWidth, 0, t.name + ": We should have a videoWidth.");
|
||||
t.addEventListener("timeupdate", onTimeUpdate_Video);
|
||||
t.play();
|
||||
}
|
||||
|
||||
var v = document.getElementsByTagName("video")[0];
|
||||
v._firstTime = true;
|
||||
var source = getPlayableVideo(gPlayTests);
|
||||
if (!source) {
|
||||
todo("No video file available.");
|
||||
} else {
|
||||
function startTest(test, token) {
|
||||
var v = document.createElement('video');
|
||||
document.body.appendChild(v);
|
||||
v.preload = "metadata";
|
||||
v._firstTime = true;
|
||||
v.addEventListener("loadedmetadata", onLoadedMetadata_Video);
|
||||
v.src = source.name;
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
v.src = test.name;
|
||||
v.token = token;
|
||||
v.name = test.name;
|
||||
manager.started(token);
|
||||
}
|
||||
|
||||
manager.runTests(getPlayableVideos(gSmallTests.concat(gSeekTests)), startTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -285,12 +285,6 @@ AudioContext::CreateMediaElementSource(HTMLMediaElement& aMediaElement,
|
|||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
#ifdef MOZ_EME
|
||||
if (aMediaElement.ContainsRestrictedContent()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
nsRefPtr<DOMMediaStream> stream = aMediaElement.MozCaptureStream(aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
|
|
|
@ -93,6 +93,7 @@ DIRS += [
|
|||
'promise',
|
||||
'smil',
|
||||
'telephony',
|
||||
'tv',
|
||||
'voicemail',
|
||||
'inputmethod',
|
||||
'webidl',
|
||||
|
|
|
@ -28,6 +28,8 @@ GetNetUtilsLibHandle()
|
|||
return sNetUtilsLib;
|
||||
}
|
||||
|
||||
mozilla::Mutex NetUtils::sIfcMutex("NetUtils::sIfcMutex");
|
||||
|
||||
// static
|
||||
void*
|
||||
NetUtils::GetSharedLibrary()
|
||||
|
@ -62,21 +64,20 @@ DEFINE_DLFUNC(ifc_remove_default_route, int32_t, const char*)
|
|||
DEFINE_DLFUNC(dhcp_stop, int32_t, const char*)
|
||||
|
||||
NetUtils::NetUtils()
|
||||
: mIfcMutex("NetUtils::mIfcMutex")
|
||||
{
|
||||
}
|
||||
|
||||
int32_t NetUtils::do_ifc_enable(const char *ifname)
|
||||
{
|
||||
USE_DLFUNC(ifc_enable)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_enable(ifname);
|
||||
}
|
||||
|
||||
int32_t NetUtils::do_ifc_disable(const char *ifname)
|
||||
{
|
||||
USE_DLFUNC(ifc_disable)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_disable(ifname);
|
||||
}
|
||||
|
||||
|
@ -88,7 +89,7 @@ int32_t NetUtils::do_ifc_configure(const char *ifname,
|
|||
in_addr_t dns2)
|
||||
{
|
||||
USE_DLFUNC(ifc_configure)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
int32_t ret = ifc_configure(ifname, address, prefixLength, gateway, dns1, dns2);
|
||||
return ret;
|
||||
}
|
||||
|
@ -97,7 +98,7 @@ int32_t NetUtils::do_ifc_reset_connections(const char *ifname,
|
|||
const int32_t resetMask)
|
||||
{
|
||||
USE_DLFUNC(ifc_reset_connections)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_reset_connections(ifname, resetMask);
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ int32_t NetUtils::do_ifc_set_default_route(const char *ifname,
|
|||
in_addr_t gateway)
|
||||
{
|
||||
USE_DLFUNC(ifc_set_default_route)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_set_default_route(ifname, gateway);
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,7 @@ int32_t NetUtils::do_ifc_add_route(const char *ifname,
|
|||
const char *gateway)
|
||||
{
|
||||
USE_DLFUNC(ifc_add_route)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_add_route(ifname, dst, prefixLength, gateway);
|
||||
}
|
||||
|
||||
|
@ -125,21 +126,21 @@ int32_t NetUtils::do_ifc_remove_route(const char *ifname,
|
|||
const char *gateway)
|
||||
{
|
||||
USE_DLFUNC(ifc_remove_route)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_remove_route(ifname, dst, prefixLength, gateway);
|
||||
}
|
||||
|
||||
int32_t NetUtils::do_ifc_remove_host_routes(const char *ifname)
|
||||
{
|
||||
USE_DLFUNC(ifc_remove_host_routes)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_remove_host_routes(ifname);
|
||||
}
|
||||
|
||||
int32_t NetUtils::do_ifc_remove_default_route(const char *ifname)
|
||||
{
|
||||
USE_DLFUNC(ifc_remove_default_route)
|
||||
mozilla::MutexAutoLock lock(mIfcMutex);
|
||||
mozilla::MutexAutoLock lock(sIfcMutex);
|
||||
return ifc_remove_default_route(ifname);
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
static int32_t SdkVersion();
|
||||
|
||||
private:
|
||||
mozilla::Mutex mIfcMutex;
|
||||
static mozilla::Mutex sIfcMutex;
|
||||
};
|
||||
|
||||
// Defines a function type with the right arguments and return type.
|
||||
|
|
|
@ -408,12 +408,19 @@ NfcContentHelper.prototype = {
|
|||
break;
|
||||
case "NFC:DOMEvent":
|
||||
switch (result.event) {
|
||||
case NFC.NFC_PEER_EVENT_READY:
|
||||
case NFC.PEER_EVENT_READY:
|
||||
this.eventTarget.notifyPeerReady(result.sessionToken);
|
||||
break;
|
||||
case NFC.NFC_PEER_EVENT_LOST:
|
||||
case NFC.PEER_EVENT_LOST:
|
||||
this.eventTarget.notifyPeerLost(result.sessionToken);
|
||||
break;
|
||||
case NFC.TAG_EVENT_FOUND:
|
||||
let event = new NfcTagEvent(result.techList);
|
||||
this.eventTarget.notifyTagFound(result.sessionToken, event, result.records);
|
||||
break;
|
||||
case NFC.TAG_EVENT_LOST:
|
||||
this.eventTarget.notifyTagLost(result.sessionToken);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -462,6 +469,15 @@ NfcContentHelper.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
function NfcTagEvent(techList) {
|
||||
this.techList = techList;
|
||||
}
|
||||
NfcTagEvent.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINfcTagEvent]),
|
||||
|
||||
techList: null
|
||||
};
|
||||
|
||||
if (NFC_ENABLED) {
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NfcContentHelper]);
|
||||
}
|
||||
|
|
|
@ -247,10 +247,25 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
|||
|
||||
// Remember the target that receives onpeerready.
|
||||
this.currentPeer = target;
|
||||
this.notifyDOMEvent(target, {event: NFC.NFC_PEER_EVENT_READY,
|
||||
this.notifyDOMEvent(target, {event: NFC.PEER_EVENT_READY,
|
||||
sessionToken: sessionToken});
|
||||
},
|
||||
|
||||
onTagFound: function onTagFound(message) {
|
||||
message.event = NFC.TAG_EVENT_FOUND;
|
||||
for (let target of this.eventTargets) {
|
||||
this.notifyDOMEvent(target, message);
|
||||
}
|
||||
delete message.event;
|
||||
},
|
||||
|
||||
onTagLost: function onTagLost(sessionToken) {
|
||||
for (let target of this.eventTargets) {
|
||||
this.notifyDOMEvent(target, {event: NFC.TAG_EVENT_LOST,
|
||||
sessionToken: sessionToken});
|
||||
}
|
||||
},
|
||||
|
||||
onPeerLost: function onPeerLost(sessionToken) {
|
||||
if (!this.currentPeer) {
|
||||
// The target is already killed.
|
||||
|
@ -259,7 +274,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
|||
|
||||
// For peerlost, the message is delievered to the target which
|
||||
// onpeerready has been called before.
|
||||
this.notifyDOMEvent(this.currentPeer, {event: NFC.NFC_PEER_EVENT_LOST,
|
||||
this.notifyDOMEvent(this.currentPeer, {event: NFC.PEER_EVENT_LOST,
|
||||
sessionToken: sessionToken});
|
||||
this.currentPeer = null;
|
||||
},
|
||||
|
@ -526,8 +541,13 @@ Nfc.prototype = {
|
|||
SessionHelper.registerSession(message.sessionId, message.techList);
|
||||
|
||||
// Do not expose the actual session to the content
|
||||
let sessionId = message.sessionId;
|
||||
delete message.sessionId;
|
||||
|
||||
if (!SessionHelper.isP2PSession(sessionId)) {
|
||||
gMessageManager.onTagFound(message);
|
||||
}
|
||||
|
||||
gSystemMessenger.broadcastMessage("nfc-manager-tech-discovered", message);
|
||||
break;
|
||||
case "TechLostNotification":
|
||||
|
@ -537,6 +557,8 @@ Nfc.prototype = {
|
|||
message.sessionToken = SessionHelper.getToken(message.sessionId);
|
||||
if (SessionHelper.isP2PSession(message.sessionId)) {
|
||||
gMessageManager.onPeerLost(message.sessionToken);
|
||||
} else {
|
||||
gMessageManager.onTagLost(message.sessionToken);
|
||||
}
|
||||
|
||||
SessionHelper.unregisterSession(message.sessionId);
|
||||
|
|
|
@ -86,8 +86,10 @@ this.TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
|
|||
|
||||
this.SETTING_NFC_DEBUG = "nfc.debugging.enabled";
|
||||
|
||||
this.NFC_PEER_EVENT_READY = 0x01;
|
||||
this.NFC_PEER_EVENT_LOST = 0x02;
|
||||
this.PEER_EVENT_READY = 0x01;
|
||||
this.PEER_EVENT_LOST = 0x02;
|
||||
this.TAG_EVENT_FOUND = 0x03;
|
||||
this.TAG_EVENT_LOST = 0x04;
|
||||
|
||||
// Allow this file to be imported via Components.utils.import().
|
||||
this.EXPORTED_SYMBOLS = Object.keys(this);
|
||||
|
|
|
@ -7,24 +7,52 @@
|
|||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(e81cc1ac-6f0b-4581-a9fb-7ee47ed0158e)]
|
||||
[scriptable, uuid(44eb02f4-6eba-4c12-8ed1-c142513776c9)]
|
||||
interface nsINfcTagEvent : nsISupports
|
||||
{
|
||||
readonly attribute nsIVariant techList;
|
||||
};
|
||||
|
||||
[scriptable, uuid(8d77d653-f76a-4a21-ae3f-c4cc6074d8ec)]
|
||||
interface nsINfcDOMEventTarget : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback function used to notify tagfound.
|
||||
*
|
||||
* @param sessionToken
|
||||
* SessionToken received from parent process
|
||||
* @param event
|
||||
* nsINfcTagFoundEvent received from parent process.
|
||||
* @param ndefRecords
|
||||
* NDEF records pre-read during tag-discovered.
|
||||
*/
|
||||
void notifyTagFound(in DOMString sessionToken,
|
||||
in nsINfcTagEvent event,
|
||||
in nsIVariant ndefRecords);
|
||||
|
||||
/**
|
||||
* Callback function used to notify taglost.
|
||||
*
|
||||
* @param sessionToken
|
||||
* SessionToken received from parent process
|
||||
*/
|
||||
void notifyTagLost(in DOMString sessionToken);
|
||||
|
||||
/**
|
||||
* Callback function used to notify peerready.
|
||||
*
|
||||
* @param sessionToken
|
||||
* SessionToken received from Chrome process
|
||||
* SessionToken received from parent process
|
||||
*/
|
||||
void notifyPeerReady(in DOMString sessionToken);
|
||||
void notifyPeerReady(in DOMString sessionToken);
|
||||
|
||||
/**
|
||||
* Callback function used to notify peerlost.
|
||||
*
|
||||
* @param sessionToken
|
||||
* SessionToken received from Chrome process
|
||||
* SessionToken received from parent process
|
||||
*/
|
||||
void notifyPeerLost(in DOMString sessionToken);
|
||||
void notifyPeerLost(in DOMString sessionToken);
|
||||
};
|
||||
|
||||
[scriptable, uuid(cb9c934d-a7fa-422b-bcc1-4ac39741e6ec)]
|
||||
|
@ -44,23 +72,23 @@ interface nsINfcContentHelper : nsISupports
|
|||
nsIDOMDOMRequest connect(in nsIDOMWindow window, in unsigned long techType, in DOMString sessionToken);
|
||||
nsIDOMDOMRequest close(in nsIDOMWindow window, in DOMString sessionToken);
|
||||
|
||||
/**
|
||||
* Initiate Send file operation
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param blob
|
||||
* Raw data of the file to be sent. This object represents a file-like
|
||||
* (nsIDOMFile) object of immutable, raw data. The blob data needs
|
||||
* to be 'object wrapped' before calling this interface.
|
||||
*
|
||||
* @param sessionToken
|
||||
* Current token
|
||||
*
|
||||
* Returns DOMRequest, if initiation of send file operation is successful
|
||||
* then 'onsuccess' is called else 'onerror'
|
||||
*/
|
||||
/**
|
||||
* Initiate send file operation.
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param blob
|
||||
* Raw data of the file to be sent. This object represents a file-like
|
||||
* (nsIDOMFile) object of immutable, raw data. The blob data needs
|
||||
* to be 'object wrapped' before calling this interface.
|
||||
*
|
||||
* @param sessionToken
|
||||
* Current token
|
||||
*
|
||||
* Returns DOMRequest, if initiation of send file operation is successful
|
||||
* then 'onsuccess' is called else 'onerror'
|
||||
*/
|
||||
nsIDOMDOMRequest sendFile(in nsIDOMWindow window,
|
||||
in jsval blob,
|
||||
in DOMString sessionToken);
|
||||
|
@ -72,66 +100,66 @@ interface nsINfcContentHelper : nsISupports
|
|||
*/
|
||||
void registerEventTarget(in nsINfcDOMEventTarget target);
|
||||
|
||||
/**
|
||||
* Register the given application id with Chrome process
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID to be registered
|
||||
*/
|
||||
/**
|
||||
* Register the given application id with parent process
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID to be registered
|
||||
*/
|
||||
void registerTargetForPeerReady(in nsIDOMWindow window,
|
||||
in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Unregister the given application id with Chrome process
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID to be registered
|
||||
*/
|
||||
/**
|
||||
* Unregister the given application id with parent process
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID to be registered
|
||||
*/
|
||||
void unregisterTargetForPeerReady(in nsIDOMWindow window,
|
||||
in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Checks if the given application's id is a registered peer target (with the Chrome process)
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID to be updated with Chrome process
|
||||
*
|
||||
* Returns DOMRequest, if appId is registered then 'onsuccess' is called else 'onerror'
|
||||
*/
|
||||
/**
|
||||
* Checks if the given application's id is a registered peer target (with the parent process)
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID to be updated with parent process
|
||||
*
|
||||
* Returns DOMRequest, if appId is registered then 'onsuccess' is called else 'onerror'
|
||||
*/
|
||||
nsIDOMDOMRequest checkP2PRegistration(in nsIDOMWindow window, in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Notify the Chrome process that user has accepted to share nfc message on P2P UI
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID that is capable of handling NFC_EVENT_PEER_READY event
|
||||
*/
|
||||
/**
|
||||
* Notify the parent process that user has accepted to share nfc message on P2P UI
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param appId
|
||||
* Application ID that is capable of handling NFC_EVENT_PEER_READY event
|
||||
*/
|
||||
void notifyUserAcceptedP2P(in nsIDOMWindow window, in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Notify the status of sendFile operation to Chrome process
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param status
|
||||
* Status of sendFile operation
|
||||
*
|
||||
* @param requestId
|
||||
* Request ID of SendFile DOM Request
|
||||
*/
|
||||
/**
|
||||
* Notify the status of sendFile operation to parent process
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param status
|
||||
* Status of sendFile operation
|
||||
*
|
||||
* @param requestId
|
||||
* Request ID of SendFile DOM Request
|
||||
*/
|
||||
void notifySendFileStatus(in nsIDOMWindow window,
|
||||
in octet status,
|
||||
in DOMString requestId);
|
||||
|
|
101
dom/nfc/nsNfc.js
101
dom/nfc/nsNfc.js
|
@ -125,6 +125,11 @@ mozNfc.prototype = {
|
|||
init: function init(aWindow) {
|
||||
debug("mozNfc init called");
|
||||
this._window = aWindow;
|
||||
this.defineEventHandlerGetterSetter("ontagfound");
|
||||
this.defineEventHandlerGetterSetter("ontaglost");
|
||||
this.defineEventHandlerGetterSetter("onpeerready");
|
||||
this.defineEventHandlerGetterSetter("onpeerlost");
|
||||
|
||||
if (this._nfcContentHelper) {
|
||||
this._nfcContentHelper.init(aWindow);
|
||||
}
|
||||
|
@ -162,14 +167,6 @@ mozNfc.prototype = {
|
|||
return this._nfcContentHelper.powerOff(this._window);
|
||||
},
|
||||
|
||||
getNFCTag: function getNFCTag(sessionToken) {
|
||||
let obj = new MozNFCTag(this._window, sessionToken);
|
||||
if (this._nfcContentHelper.checkSessionToken(sessionToken)) {
|
||||
return this._window.MozNFCTag._create(this._window, obj);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getNFCPeer: function getNFCPeer(sessionToken) {
|
||||
if (!sessionToken || !this._nfcContentHelper.checkSessionToken(sessionToken)) {
|
||||
return null;
|
||||
|
@ -184,22 +181,15 @@ mozNfc.prototype = {
|
|||
return this.nfcObject.contentObject;
|
||||
},
|
||||
|
||||
// get/set onpeerready
|
||||
get onpeerready() {
|
||||
return this.__DOM_IMPL__.getEventHandler("onpeerready");
|
||||
},
|
||||
|
||||
set onpeerready(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("onpeerready", handler);
|
||||
},
|
||||
|
||||
// get/set onpeerlost
|
||||
get onpeerlost() {
|
||||
return this.__DOM_IMPL__.getEventHandler("onpeerlost");
|
||||
},
|
||||
|
||||
set onpeerlost(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler("onpeerlost", handler);
|
||||
defineEventHandlerGetterSetter: function defineEventHandlerGetterSetter(name) {
|
||||
Object.defineProperty(this, name, {
|
||||
get: function get() {
|
||||
return this.__DOM_IMPL__.getEventHandler(name);
|
||||
},
|
||||
set: function set(handler) {
|
||||
this.__DOM_IMPL__.setEventHandler(name, handler);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
eventListenerWasAdded: function(eventType) {
|
||||
|
@ -220,6 +210,54 @@ mozNfc.prototype = {
|
|||
this._nfcContentHelper.unregisterTargetForPeerReady(this._window, appId);
|
||||
},
|
||||
|
||||
notifyTagFound: function notifyTagFound(sessionToken, event, records) {
|
||||
if (this.hasDeadWrapper()) {
|
||||
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.checkPermissions(["nfc-read", "nfc-write"])) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tag = new MozNFCTag(this._window, sessionToken);
|
||||
let tagContentObj = this._window.MozNFCTag._create(this._window, tag);
|
||||
|
||||
let length = records ? records.length : 0;
|
||||
let ndefRecords = records ? [] : null;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let record = records[i];
|
||||
ndefRecords.push(new this._window.MozNDEFRecord({tnf: record.tnf,
|
||||
type: record.type,
|
||||
id: record.id,
|
||||
payload: record.payload}));
|
||||
}
|
||||
|
||||
let eventData = {
|
||||
"tag": tagContentObj,
|
||||
"ndefRecords": ndefRecords
|
||||
};
|
||||
|
||||
debug("fire ontagfound " + sessionToken);
|
||||
let tagEvent = new this._window.MozNFCTagEvent("tagfound", eventData);
|
||||
this.__DOM_IMPL__.dispatchEvent(tagEvent);
|
||||
},
|
||||
|
||||
notifyTagLost: function notifyTagLost(sessionToken) {
|
||||
if (this.hasDeadWrapper()) {
|
||||
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.checkPermissions(["nfc-read", "nfc-write"])) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug("fire ontaglost " + sessionToken);
|
||||
let event = new this._window.Event("taglost");
|
||||
this.__DOM_IMPL__.dispatchEvent(event);
|
||||
},
|
||||
|
||||
notifyPeerReady: function notifyPeerReady(sessionToken) {
|
||||
if (this.hasDeadWrapper()) {
|
||||
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
||||
|
@ -259,6 +297,21 @@ mozNfc.prototype = {
|
|||
this.__DOM_IMPL__.dispatchEvent(event);
|
||||
},
|
||||
|
||||
checkPermissions: function checkPermissions(perms) {
|
||||
let principal = this._window.document.nodePrincipal;
|
||||
for (let perm of perms) {
|
||||
let permValue =
|
||||
Services.perms.testExactPermissionFromPrincipal(principal, perm);
|
||||
if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
return true;
|
||||
} else {
|
||||
debug("doesn't have " + perm + " permission.");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
hasDeadWrapper: function hasDeadWrapper() {
|
||||
return Cu.isDeadWrapper(this._window) || Cu.isDeadWrapper(this.__DOM_IMPL__);
|
||||
},
|
||||
|
|
|
@ -191,18 +191,6 @@ function testPeerInvalidToken() {
|
|||
runNextTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Added for completeness in Bug 1042651,
|
||||
* TODO: remove once Bug 963531 lands
|
||||
*/
|
||||
function testTagInvalidToken() {
|
||||
log("testTagInvalidToken");
|
||||
let tag = nfc.getNFCTag("fakeSessionToken");
|
||||
is(tag, null, "NFCTag should be null on wrong session token");
|
||||
|
||||
runNextTest();
|
||||
}
|
||||
|
||||
let tests = [
|
||||
testPeerReady,
|
||||
testGetNFCPeer,
|
||||
|
@ -210,8 +198,7 @@ let tests = [
|
|||
testPeerLostShouldBeCalled,
|
||||
testPeerLostShouldNotBeCalled,
|
||||
testPeerShouldThrow,
|
||||
testPeerInvalidToken,
|
||||
testTagInvalidToken
|
||||
testPeerInvalidToken
|
||||
];
|
||||
|
||||
SpecialPowers.pushPermissions(
|
||||
|
|
|
@ -80,7 +80,8 @@ using mozilla::PluginLibrary;
|
|||
using mozilla::PluginPRLibrary;
|
||||
|
||||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
using mozilla::plugins::PluginModuleParent;
|
||||
using mozilla::plugins::PluginModuleChromeParent;
|
||||
using mozilla::plugins::PluginModuleContentParent;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
#include "mozilla/X11Util.h"
|
||||
|
@ -247,6 +248,10 @@ nsNPAPIPlugin::PluginCrashed(const nsAString& pluginDumpID,
|
|||
bool
|
||||
nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (MOZ_WIDGET_GTK == 3)
|
||||
// We force OOP on Linux/GTK3 because some plugins use GTK2 and both GTK
|
||||
// libraries can't be loaded in the same process.
|
||||
|
@ -388,8 +393,12 @@ GetNewPluginLibrary(nsPluginTag *aPluginTag)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
return PluginModuleContentParent::LoadModule(aPluginTag->mId);
|
||||
}
|
||||
|
||||
if (nsNPAPIPlugin::RunPluginOOP(aPluginTag)) {
|
||||
return PluginModuleParent::LoadModule(aPluginTag->mFullPath.get());
|
||||
return PluginModuleChromeParent::LoadModule(aPluginTag->mFullPath.get(), aPluginTag->mId);
|
||||
}
|
||||
return new PluginPRLibrary(aPluginTag->mFullPath.get(), aPluginTag->mLibrary);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,10 @@
|
|||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsPluginStreamListenerPeer.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "nsEnumeratorUtils.h"
|
||||
|
@ -106,6 +109,7 @@
|
|||
|
||||
using namespace mozilla;
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::plugins::PluginTag;
|
||||
|
||||
// Null out a strong ref to a linked list iteratively to avoid
|
||||
// exhausting the stack (bug 486349).
|
||||
|
@ -309,6 +313,10 @@ bool nsPluginHost::IsRunningPlugin(nsPluginTag * aPluginTag)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (aPluginTag->mContentProcessRunningCount) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mInstances.Length(); i++) {
|
||||
nsNPAPIPluginInstance *instance = mInstances[i].get();
|
||||
if (instance &&
|
||||
|
@ -1272,6 +1280,76 @@ nsresult nsPluginHost::EnsurePluginLoaded(nsPluginTag* aPluginTag)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::GetPluginForContentProcess(uint32_t aPluginId, nsNPAPIPlugin** aPlugin)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
// If plugins haven't been scanned yet, do so now
|
||||
LoadPlugins();
|
||||
|
||||
nsPluginTag* pluginTag = PluginWithId(aPluginId);
|
||||
if (pluginTag) {
|
||||
nsresult rv = EnsurePluginLoaded(pluginTag);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We only get here if a content process doesn't have a PluginModuleParent
|
||||
// for the given plugin already. Therefore, this counter is counting the
|
||||
// number of outstanding PluginModuleParents for the plugin, excluding the
|
||||
// one from the chrome process.
|
||||
pluginTag->mContentProcessRunningCount++;
|
||||
NS_ADDREF(*aPlugin = pluginTag->mPlugin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
class nsPluginUnloadRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit nsPluginUnloadRunnable(uint32_t aPluginId) : mPluginId(aPluginId) {}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
|
||||
if (!host) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsPluginTag* pluginTag = host->PluginWithId(mPluginId);
|
||||
if (!pluginTag) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pluginTag->mContentProcessRunningCount > 0);
|
||||
pluginTag->mContentProcessRunningCount--;
|
||||
|
||||
if (!pluginTag->mContentProcessRunningCount) {
|
||||
if (!host->IsRunningPlugin(pluginTag)) {
|
||||
pluginTag->TryUnloadPlugin(false);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t mPluginId;
|
||||
};
|
||||
|
||||
void
|
||||
nsPluginHost::NotifyContentModuleDestroyed(uint32_t aPluginId)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
// This is called in response to a message from the plugin. Don't unload the
|
||||
// plugin until the message handler is off the stack.
|
||||
nsRefPtr<nsPluginUnloadRunnable> runnable =
|
||||
new nsPluginUnloadRunnable(aPluginId);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
nsresult nsPluginHost::GetPlugin(const char *aMimeType, nsNPAPIPlugin** aPlugin)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
@ -1614,6 +1692,17 @@ nsPluginHost::FirstPluginWithPath(const nsCString& path)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsPluginTag*
|
||||
nsPluginHost::PluginWithId(uint32_t aId)
|
||||
{
|
||||
for (nsPluginTag* tag = mPlugins; tag; tag = tag->mNext) {
|
||||
if (tag->mId == aId) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
int64_t GetPluginLastModifiedTime(const nsCOMPtr<nsIFile>& localfile)
|
||||
|
@ -1700,12 +1789,32 @@ struct CompareFilesByTime
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag)
|
||||
{
|
||||
aPluginTag->mNext = mPlugins;
|
||||
mPlugins = aPluginTag;
|
||||
|
||||
if (aPluginTag->IsActive()) {
|
||||
nsAdoptingCString disableFullPage =
|
||||
Preferences::GetCString(kPrefDisableFullPage);
|
||||
for (uint32_t i = 0; i < aPluginTag->mMimeTypes.Length(); i++) {
|
||||
if (!IsTypeInList(aPluginTag->mMimeTypes[i], disableFullPage)) {
|
||||
RegisterWithCategoryManager(aPluginTag->mMimeTypes[i],
|
||||
ePluginRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
|
||||
|
||||
nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||
bool aCreatePluginList,
|
||||
bool *aPluginsChanged)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aPluginsChanged);
|
||||
nsresult rv;
|
||||
|
||||
|
@ -1895,42 +2004,7 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Add plugin tags such that the list is ordered by modification date,
|
||||
// newest to oldest. This is ugly, it'd be easier with just about anything
|
||||
// other than a single-directional linked list.
|
||||
if (mPlugins) {
|
||||
nsPluginTag *prev = nullptr;
|
||||
nsPluginTag *next = mPlugins;
|
||||
while (next) {
|
||||
if (pluginTag->mLastModifiedTime >= next->mLastModifiedTime) {
|
||||
pluginTag->mNext = next;
|
||||
if (prev) {
|
||||
prev->mNext = pluginTag;
|
||||
} else {
|
||||
mPlugins = pluginTag;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = next;
|
||||
next = prev->mNext;
|
||||
if (!next) {
|
||||
prev->mNext = pluginTag;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mPlugins = pluginTag;
|
||||
}
|
||||
|
||||
if (pluginTag->IsActive()) {
|
||||
nsAdoptingCString disableFullPage =
|
||||
Preferences::GetCString(kPrefDisableFullPage);
|
||||
for (uint32_t i = 0; i < pluginTag->mMimeTypes.Length(); i++) {
|
||||
if (!IsTypeInList(pluginTag->mMimeTypes[i], disableFullPage)) {
|
||||
RegisterWithCategoryManager(pluginTag->mMimeTypes[i],
|
||||
ePluginRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
AddPluginTag(pluginTag);
|
||||
}
|
||||
|
||||
if (warnOutdated) {
|
||||
|
@ -1944,6 +2018,8 @@ nsresult nsPluginHost::ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
|
|||
bool aCreatePluginList,
|
||||
bool *aPluginsChanged)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED(dirEnum->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
|
@ -1968,6 +2044,34 @@ nsresult nsPluginHost::ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginHost::IncrementChromeEpoch()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
mPluginEpoch++;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsPluginHost::ChromeEpoch()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
return mPluginEpoch;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsPluginHost::ChromeEpochForContent()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
|
||||
return mPluginEpoch;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginHost::SetChromeEpochForContent(uint32_t aEpoch)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
|
||||
mPluginEpoch = aEpoch;
|
||||
}
|
||||
|
||||
nsresult nsPluginHost::LoadPlugins()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
|
@ -1990,6 +2094,10 @@ nsresult nsPluginHost::LoadPlugins()
|
|||
|
||||
// only if plugins have changed will we notify plugin-change observers
|
||||
if (pluginschanged) {
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
IncrementChromeEpoch();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (obsService)
|
||||
|
@ -1999,6 +2107,54 @@ nsresult nsPluginHost::LoadPlugins()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::FindPluginsInContent(bool aCreatePluginList, bool* aPluginsChanged)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
|
||||
|
||||
dom::ContentChild* cp = dom::ContentChild::GetSingleton();
|
||||
nsTArray<PluginTag> plugins;
|
||||
uint32_t parentEpoch;
|
||||
if (!cp->SendFindPlugins(ChromeEpochForContent(), &plugins, &parentEpoch)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (parentEpoch != ChromeEpochForContent()) {
|
||||
SetChromeEpochForContent(parentEpoch);
|
||||
*aPluginsChanged = true;
|
||||
if (!aCreatePluginList) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < plugins.Length(); i++) {
|
||||
PluginTag& tag = plugins[i];
|
||||
|
||||
// Don't add the same plugin again.
|
||||
if (PluginWithId(tag.id())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsPluginTag *pluginTag = new nsPluginTag(tag.id(),
|
||||
tag.name().get(),
|
||||
tag.description().get(),
|
||||
tag.filename().get(),
|
||||
"", // aFullPath
|
||||
tag.version().get(),
|
||||
nsTArray<nsCString>(tag.mimeTypes()),
|
||||
nsTArray<nsCString>(tag.mimeDescriptions()),
|
||||
nsTArray<nsCString>(tag.extensions()),
|
||||
tag.isJavaPlugin(),
|
||||
tag.isFlashPlugin(),
|
||||
tag.lastModifiedTime(),
|
||||
tag.isFromExtension());
|
||||
AddPluginTag(pluginTag);
|
||||
}
|
||||
}
|
||||
|
||||
mPluginsLoaded = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if aCreatePluginList is false we will just scan for plugins
|
||||
// and see if any changes have been made to the plugins.
|
||||
// This is needed in ReloadPlugins to prevent possible recursive reloads
|
||||
|
@ -2009,6 +2165,11 @@ nsresult nsPluginHost::FindPlugins(bool aCreatePluginList, bool * aPluginsChange
|
|||
NS_ENSURE_ARG_POINTER(aPluginsChanged);
|
||||
|
||||
*aPluginsChanged = false;
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
return FindPluginsInContent(aCreatePluginList, aPluginsChanged);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Read cached plugins info. If the profile isn't yet available then don't
|
||||
|
@ -2167,9 +2328,58 @@ nsresult nsPluginHost::FindPlugins(bool aCreatePluginList, bool * aPluginsChange
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
mozilla::plugins::FindPluginsForContent(uint32_t aPluginEpoch,
|
||||
nsTArray<PluginTag>* aPlugins,
|
||||
uint32_t* aNewPluginEpoch)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
|
||||
host->FindPluginsForContent(aPluginEpoch, aPlugins, aNewPluginEpoch);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
|
||||
nsTArray<PluginTag>* aPlugins,
|
||||
uint32_t* aNewPluginEpoch)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
// Load plugins so that the epoch is correct.
|
||||
LoadPlugins();
|
||||
|
||||
*aNewPluginEpoch = ChromeEpoch();
|
||||
if (aPluginEpoch == ChromeEpoch()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<nsPluginTag>> plugins;
|
||||
GetPlugins(plugins);
|
||||
|
||||
for (size_t i = 0; i < plugins.Length(); i++) {
|
||||
nsRefPtr<nsPluginTag> tag = plugins[i];
|
||||
aPlugins->AppendElement(PluginTag(tag->mId,
|
||||
tag->mName,
|
||||
tag->mDescription,
|
||||
tag->mMimeTypes,
|
||||
tag->mMimeDescriptions,
|
||||
tag->mExtensions,
|
||||
tag->mIsJavaPlugin,
|
||||
tag->mIsFlashPlugin,
|
||||
tag->mFileName,
|
||||
tag->mVersion,
|
||||
tag->mLastModifiedTime,
|
||||
tag->IsFromExtension()));
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
ReadPluginInfo();
|
||||
WritePluginInfo();
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
|
@ -2261,6 +2471,7 @@ nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType,
|
|||
nsresult
|
||||
nsPluginHost::WritePluginInfo()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID,&rv));
|
||||
|
@ -2405,6 +2616,8 @@ nsPluginHost::WritePluginInfo()
|
|||
nsresult
|
||||
nsPluginHost::ReadPluginInfo()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
const long PLUGIN_REG_MIMETYPES_ARRAY_SIZE = 12;
|
||||
const long PLUGIN_REG_MAX_MIMETYPES = 1000;
|
||||
|
||||
|
@ -3542,6 +3755,7 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin,
|
|||
// instance of this plugin we reload it (launch a new plugin process).
|
||||
|
||||
crashedPluginTag->mPlugin = nullptr;
|
||||
crashedPluginTag->mContentProcessRunningCount = 0;
|
||||
|
||||
#ifdef XP_WIN
|
||||
CheckForDisabledWindows();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsIEffectiveTLDService.h"
|
||||
#include "nsIIDNService.h"
|
||||
#include "nsCRT.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
|
||||
class nsNPAPIPlugin;
|
||||
class nsIComponentManager;
|
||||
|
@ -36,6 +37,7 @@ class nsIChannel;
|
|||
class nsPluginNativeWindow;
|
||||
class nsObjectLoadingContent;
|
||||
class nsPluginInstanceOwner;
|
||||
class nsPluginUnloadRunnable;
|
||||
class nsNPAPIPluginInstance;
|
||||
class nsNPAPIPluginStreamListener;
|
||||
class nsIPluginInstanceOwner;
|
||||
|
@ -88,6 +90,9 @@ public:
|
|||
nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
|
||||
|
||||
void GetPlugins(nsTArray<nsRefPtr<nsPluginTag> >& aPluginArray);
|
||||
void FindPluginsForContent(uint32_t aPluginEpoch,
|
||||
nsTArray<mozilla::plugins::PluginTag>* aPlugins,
|
||||
uint32_t* aNewPluginEpoch);
|
||||
|
||||
nsresult GetURL(nsISupports* pluginInst,
|
||||
const char* url,
|
||||
|
@ -191,12 +196,16 @@ public:
|
|||
nsPluginTag* TagForPlugin(nsNPAPIPlugin* aPlugin);
|
||||
|
||||
nsresult GetPlugin(const char *aMimeType, nsNPAPIPlugin** aPlugin);
|
||||
nsresult GetPluginForContentProcess(uint32_t aPluginId, nsNPAPIPlugin** aPlugin);
|
||||
void NotifyContentModuleDestroyed(uint32_t aPluginId);
|
||||
|
||||
nsresult NewPluginStreamListener(nsIURI* aURL,
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsIStreamListener **aStreamListener);
|
||||
|
||||
private:
|
||||
friend class nsPluginUnloadRunnable;
|
||||
|
||||
nsresult
|
||||
TrySetUpPluginInstance(const char *aMimeType, nsIURI *aURL, nsPluginInstanceOwner *aOwner);
|
||||
|
||||
|
@ -214,6 +223,8 @@ private:
|
|||
nsresult
|
||||
FindStoppedPluginForURL(nsIURI* aURL, nsIPluginInstanceOwner *aOwner);
|
||||
|
||||
nsresult FindPluginsInContent(bool aCreatePluginList, bool * aPluginsChanged);
|
||||
|
||||
nsresult
|
||||
FindPlugins(bool aCreatePluginList, bool * aPluginsChanged);
|
||||
|
||||
|
@ -222,6 +233,8 @@ private:
|
|||
enum nsRegisterType { ePluginRegister, ePluginUnregister };
|
||||
void RegisterWithCategoryManager(nsCString &aMimeType, nsRegisterType aType);
|
||||
|
||||
void AddPluginTag(nsPluginTag* aPluginTag);
|
||||
|
||||
nsresult
|
||||
ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||
bool aCreatePluginList,
|
||||
|
@ -255,11 +268,23 @@ private:
|
|||
|
||||
// Returns the first plugin at |path|
|
||||
nsPluginTag* FirstPluginWithPath(const nsCString& path);
|
||||
nsPluginTag* PluginWithId(uint32_t aId);
|
||||
|
||||
nsresult EnsurePrivateDirServiceProvider();
|
||||
|
||||
void OnPluginInstanceDestroyed(nsPluginTag* aPluginTag);
|
||||
|
||||
// To be used by the chrome process whenever the set of plugins changes.
|
||||
void IncrementChromeEpoch();
|
||||
|
||||
// To be used by the chrome process; returns the current epoch.
|
||||
uint32_t ChromeEpoch();
|
||||
|
||||
// To be used by the content process to get/set the last observed epoch value
|
||||
// from the chrome process.
|
||||
uint32_t ChromeEpochForContent();
|
||||
void SetChromeEpochForContent(uint32_t aEpoch);
|
||||
|
||||
nsRefPtr<nsPluginTag> mPlugins;
|
||||
nsRefPtr<nsPluginTag> mCachedPlugins;
|
||||
nsRefPtr<nsInvalidPluginTag> mInvalidPlugins;
|
||||
|
@ -295,6 +320,12 @@ private:
|
|||
|
||||
nsWeakPtr mCurrentDocument; // weak reference, we use it to id document only
|
||||
|
||||
// This epoch increases each time we load the list of plugins from disk.
|
||||
// In the chrome process, this stores the actual epoch.
|
||||
// In the content process, this stores the last epoch value observed
|
||||
// when reading plugins from chrome.
|
||||
uint32_t mPluginEpoch;
|
||||
|
||||
static nsIFile *sPluginTempDir;
|
||||
|
||||
// We need to hold a global ptr to ourselves because we register for
|
||||
|
|
|
@ -66,10 +66,14 @@ GetStatePrefNameForPlugin(nsPluginTag* aTag)
|
|||
|
||||
/* nsPluginTag */
|
||||
|
||||
uint32_t nsPluginTag::sNextId;
|
||||
|
||||
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo,
|
||||
int64_t aLastModifiedTime,
|
||||
bool fromExtension)
|
||||
: mName(aPluginInfo->fName),
|
||||
: mId(sNextId++),
|
||||
mContentProcessRunningCount(0),
|
||||
mName(aPluginInfo->fName),
|
||||
mDescription(aPluginInfo->fDescription),
|
||||
mLibrary(nullptr),
|
||||
mIsJavaPlugin(false),
|
||||
|
@ -103,7 +107,9 @@ nsPluginTag::nsPluginTag(const char* aName,
|
|||
int64_t aLastModifiedTime,
|
||||
bool fromExtension,
|
||||
bool aArgsAreUTF8)
|
||||
: mName(aName),
|
||||
: mId(sNextId++),
|
||||
mContentProcessRunningCount(0),
|
||||
mName(aName),
|
||||
mDescription(aDescription),
|
||||
mLibrary(nullptr),
|
||||
mIsJavaPlugin(false),
|
||||
|
@ -124,6 +130,39 @@ nsPluginTag::nsPluginTag(const char* aName,
|
|||
FixupVersion();
|
||||
}
|
||||
|
||||
nsPluginTag::nsPluginTag(uint32_t aId,
|
||||
const char* aName,
|
||||
const char* aDescription,
|
||||
const char* aFileName,
|
||||
const char* aFullPath,
|
||||
const char* aVersion,
|
||||
nsTArray<nsCString> aMimeTypes,
|
||||
nsTArray<nsCString> aMimeDescriptions,
|
||||
nsTArray<nsCString> aExtensions,
|
||||
bool aIsJavaPlugin,
|
||||
bool aIsFlashPlugin,
|
||||
int64_t aLastModifiedTime,
|
||||
bool aFromExtension)
|
||||
: mId(aId),
|
||||
mContentProcessRunningCount(0),
|
||||
mName(aName),
|
||||
mDescription(aDescription),
|
||||
mMimeTypes(aMimeTypes),
|
||||
mMimeDescriptions(aMimeDescriptions),
|
||||
mExtensions(aExtensions),
|
||||
mLibrary(nullptr),
|
||||
mIsJavaPlugin(aIsJavaPlugin),
|
||||
mIsFlashPlugin(aIsFlashPlugin),
|
||||
mFileName(aFileName),
|
||||
mVersion(aVersion),
|
||||
mLastModifiedTime(aLastModifiedTime),
|
||||
mNiceFileName(),
|
||||
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
||||
mCachedBlocklistStateValid(false),
|
||||
mIsFromExtension(aFromExtension)
|
||||
{
|
||||
}
|
||||
|
||||
nsPluginTag::~nsPluginTag()
|
||||
{
|
||||
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
|
||||
|
|
|
@ -51,6 +51,19 @@ public:
|
|||
int64_t aLastModifiedTime,
|
||||
bool fromExtension,
|
||||
bool aArgsAreUTF8 = false);
|
||||
nsPluginTag(uint32_t aId,
|
||||
const char* aName,
|
||||
const char* aDescription,
|
||||
const char* aFileName,
|
||||
const char* aFullPath,
|
||||
const char* aVersion,
|
||||
nsTArray<nsCString> aMimeTypes,
|
||||
nsTArray<nsCString> aMimeDescriptions,
|
||||
nsTArray<nsCString> aExtensions,
|
||||
bool aIsJavaPlugin,
|
||||
bool aIsFlashPlugin,
|
||||
int64_t aLastModifiedTime,
|
||||
bool aFromExtension);
|
||||
|
||||
void TryUnloadPlugin(bool inShutdown);
|
||||
|
||||
|
@ -74,6 +87,10 @@ public:
|
|||
bool IsFromExtension() const;
|
||||
|
||||
nsRefPtr<nsPluginTag> mNext;
|
||||
uint32_t mId;
|
||||
|
||||
// Number of PluginModuleParents living in all content processes.
|
||||
size_t mContentProcessRunningCount;
|
||||
nsCString mName; // UTF-8
|
||||
nsCString mDescription; // UTF-8
|
||||
nsTArray<nsCString> mMimeTypes; // UTF-8
|
||||
|
@ -106,6 +123,8 @@ private:
|
|||
uint32_t aVariantCount);
|
||||
nsresult EnsureMembersAreUTF8();
|
||||
void FixupVersion();
|
||||
|
||||
static uint32_t sNextId;
|
||||
};
|
||||
|
||||
#endif // nsPluginTags_h_
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
include protocol PPluginInstance;
|
||||
include protocol PPluginScriptableObject;
|
||||
include protocol PCrashReporter;
|
||||
include protocol PContent;
|
||||
|
||||
using NPError from "npapi.h";
|
||||
using NPNVariable from "npapi.h";
|
||||
|
@ -18,6 +19,8 @@ namespace plugins {
|
|||
|
||||
intr protocol PPluginModule
|
||||
{
|
||||
bridges PContent, PPluginModule;
|
||||
|
||||
manages PPluginInstance;
|
||||
manages PCrashReporter;
|
||||
|
||||
|
@ -107,10 +110,14 @@ parent:
|
|||
async PopCursor();
|
||||
sync GetNativeCursorsSupported() returns (bool supported);
|
||||
|
||||
sync NPN_SetException(nullable PPluginScriptableObject actor,
|
||||
nsCString message);
|
||||
sync NPN_SetException(nsCString message);
|
||||
|
||||
async NPN_ReloadPlugins(bool aReloadPages);
|
||||
|
||||
// Notifies the chrome process that a PluginModuleChild linked to a content
|
||||
// process was destroyed. The chrome process may choose to asynchronously shut
|
||||
// down the plugin process in response.
|
||||
async NotifyContentModuleDestroyed();
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 et :
|
||||
* 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_plugins_PluginBridge_h
|
||||
#define mozilla_plugins_PluginBridge_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
}
|
||||
|
||||
namespace plugins {
|
||||
|
||||
bool
|
||||
SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent);
|
||||
|
||||
bool
|
||||
FindPluginsForContent(uint32_t aPluginEpoch,
|
||||
nsTArray<PluginTag>* aPlugins,
|
||||
uint32_t* aNewPluginEpoch);
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_PluginBridge_h
|
|
@ -69,7 +69,7 @@ private:
|
|||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
PluginHangUIParent::PluginHangUIParent(PluginModuleParent* aModule,
|
||||
PluginHangUIParent::PluginHangUIParent(PluginModuleChromeParent* aModule,
|
||||
const int32_t aHangUITimeoutPref,
|
||||
const int32_t aChildTimeoutPref)
|
||||
: mMutex("mozilla::plugins::PluginHangUIParent::mMutex"),
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class PluginModuleParent;
|
||||
class PluginModuleChromeParent;
|
||||
|
||||
/**
|
||||
* This class is responsible for launching and communicating with the
|
||||
|
@ -35,7 +35,7 @@ class PluginModuleParent;
|
|||
class PluginHangUIParent : public MiniShmObserver
|
||||
{
|
||||
public:
|
||||
PluginHangUIParent(PluginModuleParent* aModule,
|
||||
PluginHangUIParent(PluginModuleChromeParent* aModule,
|
||||
const int32_t aHangUITimeoutPref,
|
||||
const int32_t aChildTimeoutPref);
|
||||
virtual ~PluginHangUIParent();
|
||||
|
@ -135,7 +135,7 @@ private:
|
|||
|
||||
private:
|
||||
Mutex mMutex;
|
||||
PluginModuleParent* mModule;
|
||||
PluginModuleChromeParent* mModule;
|
||||
const uint32_t mTimeoutPrefMs;
|
||||
const uint32_t mIPCTimeoutMs;
|
||||
MessageLoop* mMainThreadMessageLoop;
|
||||
|
|
|
@ -165,6 +165,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
|
|||
, mDoAlphaExtraction(false)
|
||||
, mHasPainted(false)
|
||||
, mSurfaceDifferenceRect(0,0,0,0)
|
||||
, mDestroyed(false)
|
||||
{
|
||||
memset(&mWindow, 0, sizeof(mWindow));
|
||||
mWindow.type = NPWindowTypeWindow;
|
||||
|
@ -212,7 +213,7 @@ PluginInstanceChild::~PluginInstanceChild()
|
|||
int
|
||||
PluginInstanceChild::GetQuirks()
|
||||
{
|
||||
return PluginModuleChild::current()->GetQuirks();
|
||||
return PluginModuleChild::GetChrome()->GetQuirks();
|
||||
}
|
||||
|
||||
NPError
|
||||
|
@ -2393,7 +2394,7 @@ PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
|
|||
}
|
||||
|
||||
PluginScriptableObjectChild* actor =
|
||||
PluginModuleChild::current()->GetActorForNPObject(aObject);
|
||||
PluginScriptableObjectChild::GetActorForNPObject(aObject);
|
||||
if (actor) {
|
||||
// Plugin-provided object that we've previously wrapped.
|
||||
return actor;
|
||||
|
@ -3276,7 +3277,7 @@ PluginInstanceChild::ShowPluginFrame()
|
|||
SharedDIBSurface* s = static_cast<SharedDIBSurface*>(mCurrentSurface.get());
|
||||
if (!mCurrentSurfaceActor) {
|
||||
base::SharedMemoryHandle handle = nullptr;
|
||||
s->ShareToProcess(PluginModuleChild::current()->OtherProcess(), &handle);
|
||||
s->ShareToProcess(OtherProcess(), &handle);
|
||||
|
||||
mCurrentSurfaceActor =
|
||||
SendPPluginSurfaceConstructor(handle,
|
||||
|
@ -3678,12 +3679,13 @@ PluginInstanceChild::ClearAllSurfaces()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
||||
void
|
||||
PluginInstanceChild::Destroy()
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
*aResult = NPERR_NO_ERROR;
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
mDestroyed = true;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1);
|
||||
|
@ -3707,7 +3709,7 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
|||
// NPP_Destroy() should be a synchronization point for plugin threads
|
||||
// calling NPN_AsyncCall: after this function returns, they are no longer
|
||||
// allowed to make async calls on this instance.
|
||||
PluginModuleChild::current()->NPP_Destroy(this);
|
||||
static_cast<PluginModuleChild *>(Manager())->NPP_Destroy(this);
|
||||
mData.ndata = 0;
|
||||
|
||||
if (mCurrentInvalidateTask) {
|
||||
|
@ -3729,7 +3731,7 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
|||
ClearAllSurfaces();
|
||||
|
||||
mDeletingHash = new nsTHashtable<DeletingObjectEntry>;
|
||||
PluginModuleChild::current()->FindNPObjectsForInstance(this);
|
||||
PluginScriptableObjectChild::NotifyOfInstanceShutdown(this);
|
||||
|
||||
mDeletingHash->EnumerateEntries(InvalidateObject, nullptr);
|
||||
mDeletingHash->EnumerateEntries(DeleteObject, nullptr);
|
||||
|
@ -3761,6 +3763,22 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
|||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
DeleteWindow();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
*aResult = NPERR_NO_ERROR;
|
||||
|
||||
Destroy();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,8 @@ class PluginInstanceChild : public PPluginInstanceChild
|
|||
{
|
||||
friend class BrowserStreamChild;
|
||||
friend class PluginStreamChild;
|
||||
friend class StreamNotifyChild;
|
||||
friend class StreamNotifyChild;
|
||||
friend class PluginScriptableObjectChild;
|
||||
|
||||
#ifdef OS_WIN
|
||||
friend LRESULT CALLBACK PluginWindowProc(HWND hWnd,
|
||||
|
@ -524,6 +525,10 @@ private:
|
|||
// Clear all surfaces in response to NPP_Destroy
|
||||
void ClearAllSurfaces();
|
||||
|
||||
void Destroy();
|
||||
|
||||
void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
// Set as true when SetupLayer called
|
||||
// and go with different path in InvalidateRect function
|
||||
bool mLayersRendering;
|
||||
|
@ -597,6 +602,9 @@ private:
|
|||
// Used for reading back to current surface and syncing data,
|
||||
// in plugin coordinates.
|
||||
nsIntRect mSurfaceDifferenceRect;
|
||||
|
||||
// Has this instance been destroyed, either by ActorDestroy or NPP_Destroy?
|
||||
bool mDestroyed;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -1778,7 +1778,7 @@ PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
|
|||
mSharedSize = newPort;
|
||||
|
||||
base::SharedMemoryHandle handle;
|
||||
if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(mParent->ChildProcessHandle(), &handle)))
|
||||
if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(OtherProcess(), &handle)))
|
||||
return false;
|
||||
|
||||
aRemoteWindow.surfaceHandle = handle;
|
||||
|
|
|
@ -545,7 +545,7 @@ bool NSCursorInfo::GetNativeCursorsSupported()
|
|||
{
|
||||
if (mNativeCursorsSupported == -1) {
|
||||
AssertPluginThread();
|
||||
PluginModuleChild *pmc = PluginModuleChild::current();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
bool result = pmc->GetNativeCursorsSupported();
|
||||
if (result) {
|
||||
|
@ -691,7 +691,7 @@ void NotifyBrowserOfPluginShowWindow(uint32_t window_id, CGRect bounds,
|
|||
bool modal) {
|
||||
AssertPluginThread();
|
||||
|
||||
PluginModuleChild *pmc = PluginModuleChild::current();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc)
|
||||
pmc->PluginShowWindow(window_id, modal, bounds);
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ void NotifyBrowserOfPluginShowWindow(uint32_t window_id, CGRect bounds,
|
|||
void NotifyBrowserOfPluginHideWindow(uint32_t window_id, CGRect bounds) {
|
||||
AssertPluginThread();
|
||||
|
||||
PluginModuleChild *pmc = PluginModuleChild::current();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc)
|
||||
pmc->PluginHideWindow(window_id);
|
||||
}
|
||||
|
@ -707,7 +707,7 @@ void NotifyBrowserOfPluginHideWindow(uint32_t window_id, CGRect bounds) {
|
|||
void NotifyBrowserOfSetCursor(NSCursorInfo& aCursorInfo)
|
||||
{
|
||||
AssertPluginThread();
|
||||
PluginModuleChild *pmc = PluginModuleChild::current();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->SetCursor(aCursorInfo);
|
||||
}
|
||||
|
@ -716,7 +716,7 @@ void NotifyBrowserOfSetCursor(NSCursorInfo& aCursorInfo)
|
|||
void NotifyBrowserOfShowCursor(bool show)
|
||||
{
|
||||
AssertPluginThread();
|
||||
PluginModuleChild *pmc = PluginModuleChild::current();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->ShowCursor(show);
|
||||
}
|
||||
|
@ -725,7 +725,7 @@ void NotifyBrowserOfShowCursor(bool show)
|
|||
void NotifyBrowserOfPushCursor(NSCursorInfo& aCursorInfo)
|
||||
{
|
||||
AssertPluginThread();
|
||||
PluginModuleChild *pmc = PluginModuleChild::current();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->PushCursor(aCursorInfo);
|
||||
}
|
||||
|
@ -734,7 +734,7 @@ void NotifyBrowserOfPushCursor(NSCursorInfo& aCursorInfo)
|
|||
void NotifyBrowserOfPopCursor()
|
||||
{
|
||||
AssertPluginThread();
|
||||
PluginModuleChild *pmc = PluginModuleChild::current();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->PopCursor();
|
||||
}
|
||||
|
|
|
@ -65,7 +65,8 @@ const wchar_t * kMozillaWindowClass = L"MozillaWindowClass";
|
|||
#endif
|
||||
|
||||
namespace {
|
||||
PluginModuleChild* gInstance = nullptr;
|
||||
PluginModuleChild* gChromeInstance = nullptr;
|
||||
nsTArray<PluginModuleChild*>* gAllInstances;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
|
@ -84,10 +85,31 @@ static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
|
|||
static HWND sBrowserHwnd = nullptr;
|
||||
#endif
|
||||
|
||||
PluginModuleChild::PluginModuleChild()
|
||||
/* static */
|
||||
PluginModuleChild*
|
||||
PluginModuleChild::CreateForContentProcess(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
PluginModuleChild* child = new PluginModuleChild(false);
|
||||
ProcessHandle handle;
|
||||
if (!base::OpenProcessHandle(aOtherProcess, &handle)) {
|
||||
// XXX need to kill |aOtherProcess|, it's boned
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!child->InitForContent(handle, XRE_GetIOMessageLoop(), aTransport)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
PluginModuleChild::PluginModuleChild(bool aIsChrome)
|
||||
: mLibrary(0)
|
||||
, mPluginFilename("")
|
||||
, mQuirks(QUIRKS_NOT_INITIALIZED)
|
||||
, mIsChrome(aIsChrome)
|
||||
, mTransport(nullptr)
|
||||
, mShutdownFunc(0)
|
||||
, mInitializeFunc(0)
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
|
@ -102,10 +124,16 @@ PluginModuleChild::PluginModuleChild()
|
|||
, mGlobalCallWndProcHook(nullptr)
|
||||
#endif
|
||||
{
|
||||
NS_ASSERTION(!gInstance, "Something terribly wrong here!");
|
||||
if (!gAllInstances) {
|
||||
gAllInstances = new nsTArray<PluginModuleChild*>(1);
|
||||
}
|
||||
gAllInstances->AppendElement(this);
|
||||
|
||||
memset(&mFunctions, 0, sizeof(mFunctions));
|
||||
memset(&mSavedData, 0, sizeof(mSavedData));
|
||||
gInstance = this;
|
||||
if (mIsChrome) {
|
||||
MOZ_ASSERT(!gChromeInstance);
|
||||
gChromeInstance = this;
|
||||
}
|
||||
mUserAgent.SetIsVoid(true);
|
||||
#ifdef XP_MACOSX
|
||||
mac_plugin_interposing::child::SetUpCocoaInterposing();
|
||||
|
@ -114,40 +142,89 @@ PluginModuleChild::PluginModuleChild()
|
|||
|
||||
PluginModuleChild::~PluginModuleChild()
|
||||
{
|
||||
NS_ASSERTION(gInstance == this, "Something terribly wrong here!");
|
||||
if (mTransport) {
|
||||
// For some reason IPDL doesn't autmatically delete the channel for a
|
||||
// bridged protocol (bug 1090570). So we have to do it ourselves. This
|
||||
// code is only invoked for PluginModuleChild instances created via
|
||||
// bridging; otherwise mTransport is null.
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport));
|
||||
}
|
||||
|
||||
// We don't unload the plugin library in case it uses atexit handlers or
|
||||
// other similar hooks.
|
||||
gAllInstances->RemoveElement(this);
|
||||
MOZ_ASSERT_IF(mIsChrome, gAllInstances->Length() == 0);
|
||||
if (gAllInstances->IsEmpty()) {
|
||||
delete gAllInstances;
|
||||
gAllInstances = nullptr;
|
||||
}
|
||||
|
||||
DeinitGraphics();
|
||||
PluginScriptableObjectChild::ClearIdentifiers();
|
||||
if (mIsChrome) {
|
||||
MOZ_ASSERT(gChromeInstance == this);
|
||||
|
||||
gInstance = nullptr;
|
||||
// We don't unload the plugin library in case it uses atexit handlers or
|
||||
// other similar hooks.
|
||||
|
||||
DeinitGraphics();
|
||||
PluginScriptableObjectChild::ClearIdentifiers();
|
||||
|
||||
gChromeInstance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
PluginModuleChild*
|
||||
PluginModuleChild::current()
|
||||
PluginModuleChild::GetChrome()
|
||||
{
|
||||
NS_ASSERTION(gInstance, "Null instance!");
|
||||
return gInstance;
|
||||
MOZ_ASSERT(gChromeInstance);
|
||||
return gChromeInstance;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChild::Init(const std::string& aPluginFilename,
|
||||
base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel)
|
||||
PluginModuleChild::CommonInit(base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
|
||||
GetIPCChannel()->SetAbortOnError(true);
|
||||
|
||||
// Request Windows message deferral behavior on our channel. This
|
||||
// applies to the top level and all sub plugin protocols since they
|
||||
// all share the same channel.
|
||||
// Bug 1090573 - Don't do this for connections to content processes.
|
||||
GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
|
||||
|
||||
if (!Open(aChannel, aParentProcessHandle, aIOLoop))
|
||||
return false;
|
||||
|
||||
memset((void*) &mFunctions, 0, sizeof(mFunctions));
|
||||
mFunctions.size = sizeof(mFunctions);
|
||||
mFunctions.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChild::InitForContent(base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel)
|
||||
{
|
||||
if (!CommonInit(aParentProcessHandle, aIOLoop, aChannel)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mTransport = aChannel;
|
||||
|
||||
mLibrary = GetChrome()->mLibrary;
|
||||
mQuirks = GetChrome()->mQuirks;
|
||||
mFunctions = GetChrome()->mFunctions;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
|
||||
base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
COMMessageFilter::Initialize(this);
|
||||
#endif
|
||||
|
@ -201,12 +278,11 @@ PluginModuleChild::Init(const std::string& aPluginFilename,
|
|||
}
|
||||
NS_ASSERTION(mLibrary, "couldn't open shared object");
|
||||
|
||||
if (!Open(aChannel, aParentProcessHandle, aIOLoop))
|
||||
if (!CommonInit(aParentProcessHandle, aIOLoop, aChannel)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset((void*) &mFunctions, 0, sizeof(mFunctions));
|
||||
mFunctions.size = sizeof(mFunctions);
|
||||
mFunctions.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
|
||||
GetIPCChannel()->SetAbortOnError(true);
|
||||
|
||||
// TODO: use PluginPRLibrary here
|
||||
|
||||
|
@ -591,6 +667,7 @@ bool
|
|||
PluginModuleChild::AnswerNP_Shutdown(NPError *rv)
|
||||
{
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(mIsChrome);
|
||||
|
||||
#if defined XP_WIN
|
||||
mozilla::widget::StopAudioSession();
|
||||
|
@ -678,6 +755,13 @@ PluginModuleChild::QuickExit()
|
|||
_exit(0);
|
||||
}
|
||||
|
||||
PPluginModuleChild*
|
||||
PluginModuleChild::AllocPPluginModuleChild(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
return PluginModuleChild::CreateForContentProcess(aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
PCrashReporterChild*
|
||||
PluginModuleChild::AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
|
||||
uint32_t* processType)
|
||||
|
@ -708,6 +792,17 @@ PluginModuleChild::AnswerPCrashReporterConstructor(
|
|||
void
|
||||
PluginModuleChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (!mIsChrome) {
|
||||
PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
|
||||
if (chromeInstance) {
|
||||
chromeInstance->SendNotifyContentModuleDestroyed();
|
||||
}
|
||||
|
||||
// Destroy ourselves once we finish other teardown activities.
|
||||
MessageLoop::current()->PostTask(FROM_HERE, new DeleteTask<PluginModuleChild>(this));
|
||||
return;
|
||||
}
|
||||
|
||||
if (AbnormalShutdown == why) {
|
||||
NS_WARNING("shutting down early because of crash!");
|
||||
QuickExit();
|
||||
|
@ -732,59 +827,6 @@ PluginModuleChild::GetUserAgent()
|
|||
return NullableStringGet(mUserAgent);
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChild::RegisterActorForNPObject(NPObject* aObject,
|
||||
PluginScriptableObjectChild* aActor)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NS_ASSERTION(aObject && aActor, "Null pointer!");
|
||||
|
||||
NPObjectData* d = mObjectMap.GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("NPObject not in object table");
|
||||
return false;
|
||||
}
|
||||
|
||||
d->actor = aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChild::UnregisterActorForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NS_ASSERTION(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = mObjectMap.GetEntry(aObject);
|
||||
NS_ASSERTION(d, "NPObject not in object table");
|
||||
if (d) {
|
||||
d->actor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PluginScriptableObjectChild*
|
||||
PluginModuleChild::GetActorForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NS_ASSERTION(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = mObjectMap.GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("Plugin using object not created with NPN_CreateObject?");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return d->actor;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
PluginModuleChild::NPObjectIsRegistered(NPObject* aObject)
|
||||
{
|
||||
return !!mObjectMap.GetEntry(aObject);
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FIXME/cjones: just getting this out of the way for the moment ...
|
||||
|
||||
|
@ -1085,7 +1127,7 @@ _getvalue(NPP aNPP,
|
|||
case NPNVSupportsWindowless: { // Intentional fall-through
|
||||
NPError result;
|
||||
bool value;
|
||||
PluginModuleChild::current()->
|
||||
PluginModuleChild::GetChrome()->
|
||||
CallNPN_GetValue_WithBoolReturn(aVariable, &result, &value);
|
||||
*(NPBool*)aValue = value ? true : false;
|
||||
return result;
|
||||
|
@ -1276,7 +1318,10 @@ _reloadplugins(NPBool aReloadPages)
|
|||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
|
||||
PluginModuleChild::current()->SendNPN_ReloadPlugins(!!aReloadPages);
|
||||
// Send the reload message to all modules. Chrome will need to reload from
|
||||
// disk and content will need to request a new list of plugin tags from
|
||||
// chrome.
|
||||
PluginModuleChild::GetChrome()->SendNPN_ReloadPlugins(!!aReloadPages);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1315,7 +1360,7 @@ _useragent(NPP aNPP)
|
|||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
ENSURE_PLUGIN_THREAD(nullptr);
|
||||
return PluginModuleChild::current()->GetUserAgent();
|
||||
return PluginModuleChild::GetChrome()->GetUserAgent();
|
||||
}
|
||||
|
||||
void*
|
||||
|
@ -1546,18 +1591,7 @@ _setexception(NPObject* aNPObj,
|
|||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
|
||||
PluginModuleChild* self = PluginModuleChild::current();
|
||||
PluginScriptableObjectChild* actor = nullptr;
|
||||
if (aNPObj) {
|
||||
actor = self->GetActorForNPObject(aNPObj);
|
||||
if (!actor) {
|
||||
NS_ERROR("Failed to get actor!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self->SendNPN_SetException(static_cast<PPluginScriptableObjectChild*>(actor),
|
||||
NullableString(aMessage));
|
||||
// Do nothing. We no longer support this API.
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1747,7 +1781,7 @@ _popupcontextmenu(NPP instance, NPMenu* menu)
|
|||
if (success) {
|
||||
return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
|
||||
screenX, screenY,
|
||||
PluginModuleChild::current(),
|
||||
PluginModuleChild::GetChrome(),
|
||||
ProcessBrowserEvents);
|
||||
} else {
|
||||
NS_WARNING("Convertpoint failed, could not created contextmenu.");
|
||||
|
@ -1805,6 +1839,7 @@ PluginModuleChild::AnswerNP_GetEntryPoints(NPError* _retval)
|
|||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(mIsChrome);
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_BSD)
|
||||
return true;
|
||||
|
@ -1821,6 +1856,7 @@ PluginModuleChild::AnswerNP_Initialize(NPError* _retval)
|
|||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(mIsChrome);
|
||||
|
||||
#ifdef OS_WIN
|
||||
SetEventHooks();
|
||||
|
@ -2050,10 +2086,7 @@ PluginModuleChild::NPN_CreateObject(NPP aNPP, NPClass* aClass)
|
|||
NS_LOG_ADDREF(newObject, 1, "NPObject", sizeof(NPObject));
|
||||
}
|
||||
|
||||
NPObjectData* d = static_cast<PluginModuleChild*>(i->Manager())
|
||||
->mObjectMap.PutEntry(newObject);
|
||||
NS_ASSERTION(!d->instance, "New NPObject already mapped?");
|
||||
d->instance = i;
|
||||
PluginScriptableObjectChild::RegisterObject(newObject, i);
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
@ -2077,15 +2110,15 @@ PluginModuleChild::NPN_ReleaseObject(NPObject* aNPObj)
|
|||
{
|
||||
AssertPluginThread();
|
||||
|
||||
NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
|
||||
if (!d) {
|
||||
PluginInstanceChild* instance = PluginScriptableObjectChild::GetInstanceForNPObject(aNPObj);
|
||||
if (!instance) {
|
||||
NS_ERROR("Releasing object not in mObjectMap?");
|
||||
return;
|
||||
}
|
||||
|
||||
DeletingObjectEntry* doe = nullptr;
|
||||
if (d->instance->mDeletingHash) {
|
||||
doe = d->instance->mDeletingHash->GetEntry(aNPObj);
|
||||
if (instance->mDeletingHash) {
|
||||
doe = instance->mDeletingHash->GetEntry(aNPObj);
|
||||
if (!doe) {
|
||||
NS_ERROR("An object for a destroyed instance isn't in the instance deletion hash");
|
||||
return;
|
||||
|
@ -2114,29 +2147,11 @@ PluginModuleChild::DeallocNPObject(NPObject* aNPObj)
|
|||
child::_memfree(aNPObj);
|
||||
}
|
||||
|
||||
NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
|
||||
if (d->actor)
|
||||
d->actor->NPObjectDestroyed();
|
||||
PluginScriptableObjectChild* actor = PluginScriptableObjectChild::GetActorForNPObject(aNPObj);
|
||||
if (actor)
|
||||
actor->NPObjectDestroyed();
|
||||
|
||||
current()->mObjectMap.RemoveEntry(aNPObj);
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChild::FindNPObjectsForInstance(PluginInstanceChild* instance)
|
||||
{
|
||||
NS_ASSERTION(instance->mDeletingHash, "filling null mDeletingHash?");
|
||||
mObjectMap.EnumerateEntries(CollectForInstance, instance);
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
PluginModuleChild::CollectForInstance(NPObjectData* d, void* userArg)
|
||||
{
|
||||
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
|
||||
if (d->instance == instance) {
|
||||
NPObject* o = d->GetKey();
|
||||
instance->mDeletingHash->PutEntry(o);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
PluginScriptableObjectChild::UnregisterObject(aNPObj);
|
||||
}
|
||||
|
||||
NPIdentifier
|
||||
|
@ -2272,7 +2287,7 @@ PluginModuleChild::CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam)
|
|||
LRESULT CALLBACK
|
||||
PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PluginModuleChild* self = current();
|
||||
PluginModuleChild* self = GetChrome();
|
||||
uint32_t len = self->mIncallPumpingStack.Length();
|
||||
if (nCode >= 0 && len && !self->mIncallPumpingStack[len - 1]._spinning) {
|
||||
MessageLoop* loop = MessageLoop::current();
|
||||
|
|
|
@ -76,6 +76,10 @@ protected:
|
|||
virtual bool AnswerNP_GetEntryPoints(NPError* rv) MOZ_OVERRIDE;
|
||||
virtual bool AnswerNP_Initialize(NPError* rv) MOZ_OVERRIDE;
|
||||
|
||||
virtual PPluginModuleChild*
|
||||
AllocPPluginModuleChild(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
|
||||
|
||||
virtual PPluginInstanceChild*
|
||||
AllocPPluginInstanceChild(const nsCString& aMimeType,
|
||||
const uint16_t& aMode,
|
||||
|
@ -140,14 +144,26 @@ protected:
|
|||
AnswerGeckoGetProfile(nsCString* aProfile) MOZ_OVERRIDE;
|
||||
|
||||
public:
|
||||
PluginModuleChild();
|
||||
PluginModuleChild(bool aIsChrome);
|
||||
virtual ~PluginModuleChild();
|
||||
|
||||
bool CommonInit(base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel);
|
||||
|
||||
// aPluginFilename is UTF8, not native-charset!
|
||||
bool Init(const std::string& aPluginFilename,
|
||||
base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel);
|
||||
bool InitForChrome(const std::string& aPluginFilename,
|
||||
base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel);
|
||||
|
||||
bool InitForContent(base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel);
|
||||
|
||||
static PluginModuleChild*
|
||||
CreateForContentProcess(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess);
|
||||
|
||||
void CleanUp();
|
||||
|
||||
|
@ -155,18 +171,7 @@ public:
|
|||
|
||||
static const NPNetscapeFuncs sBrowserFuncs;
|
||||
|
||||
static PluginModuleChild* current();
|
||||
|
||||
bool RegisterActorForNPObject(NPObject* aObject,
|
||||
PluginScriptableObjectChild* aActor);
|
||||
|
||||
void UnregisterActorForNPObject(NPObject* aObject);
|
||||
|
||||
PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool NPObjectIsRegistered(NPObject* aObject);
|
||||
#endif
|
||||
static PluginModuleChild* GetChrome();
|
||||
|
||||
/**
|
||||
* The child implementation of NPN_CreateObject.
|
||||
|
@ -299,6 +304,9 @@ private:
|
|||
nsCString mUserAgent;
|
||||
int mQuirks;
|
||||
|
||||
bool mIsChrome;
|
||||
Transport* mTransport;
|
||||
|
||||
// we get this from the plugin
|
||||
NP_PLUGINSHUTDOWN mShutdownFunc;
|
||||
#if defined(OS_LINUX) || defined(OS_BSD)
|
||||
|
@ -309,7 +317,6 @@ private:
|
|||
#endif
|
||||
|
||||
NPPluginFuncs mFunctions;
|
||||
NPSavedData mSavedData;
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
// If a plugin spins a nested glib event loop in response to a
|
||||
|
@ -353,26 +360,6 @@ private:
|
|||
NestedLoopTimer *mNestedLoopTimerObject;
|
||||
#endif
|
||||
|
||||
struct NPObjectData : public nsPtrHashKey<NPObject>
|
||||
{
|
||||
explicit NPObjectData(const NPObject* key)
|
||||
: nsPtrHashKey<NPObject>(key)
|
||||
, instance(nullptr)
|
||||
, actor(nullptr)
|
||||
{ }
|
||||
|
||||
// never nullptr
|
||||
PluginInstanceChild* instance;
|
||||
|
||||
// sometimes nullptr (no actor associated with an NPObject)
|
||||
PluginScriptableObjectChild* actor;
|
||||
};
|
||||
/**
|
||||
* mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
|
||||
* final release/dealloc, whether or not an actor is currently associated with the object.
|
||||
*/
|
||||
nsTHashtable<NPObjectData> mObjectMap;
|
||||
|
||||
public: // called by PluginInstanceChild
|
||||
/**
|
||||
* Dealloc an NPObject after last-release or when the associated instance
|
||||
|
@ -384,15 +371,7 @@ public: // called by PluginInstanceChild
|
|||
return mFunctions.destroy(instance->GetNPP(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill PluginInstanceChild.mDeletingHash with all the remaining NPObjects
|
||||
* associated with that instance.
|
||||
*/
|
||||
void FindNPObjectsForInstance(PluginInstanceChild* instance);
|
||||
|
||||
private:
|
||||
static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
virtual void EnteredCall() MOZ_OVERRIDE;
|
||||
virtual void ExitedCall() MOZ_OVERRIDE;
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
|
||||
#include "base/process_util.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/PCrashReporterParent.h"
|
||||
#include "mozilla/ipc/MessageChannel.h"
|
||||
#include "mozilla/plugins/BrowserStreamParent.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
@ -83,16 +86,82 @@ struct RunnableMethodTraits<mozilla::plugins::PluginModuleParent>
|
|||
static void ReleaseCallee(Class* obj) { }
|
||||
};
|
||||
|
||||
bool
|
||||
mozilla::plugins::SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent)
|
||||
{
|
||||
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
|
||||
nsRefPtr<nsNPAPIPlugin> plugin;
|
||||
nsresult rv = host->GetPluginForContentProcess(aPluginId, getter_AddRefs(plugin));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
PluginModuleParent* chromeParent = static_cast<PluginModuleParent*>(plugin->GetLibrary());
|
||||
return PPluginModule::Bridge(aContentParent, chromeParent);
|
||||
}
|
||||
|
||||
PluginModuleContentParent* PluginModuleContentParent::sSavedModuleParent;
|
||||
|
||||
/* static */ PluginLibrary*
|
||||
PluginModuleContentParent::LoadModule(uint32_t aPluginId)
|
||||
{
|
||||
MOZ_ASSERT(!sSavedModuleParent);
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
|
||||
|
||||
/*
|
||||
* We send a LoadPlugin message to the chrome process using an intr
|
||||
* message. Before it sends its response, it sends a message to create
|
||||
* PluginModuleParent instance. That message is handled by
|
||||
* PluginModuleContentParent::Create, which saves the instance in
|
||||
* sSavedModuleParent. We fetch it from there after LoadPlugin finishes.
|
||||
*/
|
||||
dom::ContentChild* cp = dom::ContentChild::GetSingleton();
|
||||
if (!cp->CallLoadPlugin(aPluginId)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PluginModuleContentParent* parent = sSavedModuleParent;
|
||||
MOZ_ASSERT(parent);
|
||||
sSavedModuleParent = nullptr;
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
/* static */ PluginModuleContentParent*
|
||||
PluginModuleContentParent::Create(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
nsAutoPtr<PluginModuleContentParent> parent(new PluginModuleContentParent());
|
||||
ProcessHandle handle;
|
||||
if (!base::OpenProcessHandle(aOtherProcess, &handle)) {
|
||||
// Bug 1090578 - need to kill |aOtherProcess|, it's boned.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!sSavedModuleParent);
|
||||
sSavedModuleParent = parent;
|
||||
|
||||
DebugOnly<bool> ok = parent->Open(aTransport, handle, XRE_GetIOMessageLoop(),
|
||||
mozilla::ipc::ParentSide);
|
||||
MOZ_ASSERT(ok);
|
||||
|
||||
// Request Windows message deferral behavior on our channel. This
|
||||
// applies to the top level and all sub plugin protocols since they
|
||||
// all share the same channel.
|
||||
parent->GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
|
||||
|
||||
return parent.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
PluginLibrary*
|
||||
PluginModuleParent::LoadModule(const char* aFilePath)
|
||||
PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
|
||||
int32_t prefSecs = Preferences::GetInt(kLaunchTimeoutPref, 0);
|
||||
|
||||
// Block on the child process being launched and initialized.
|
||||
nsAutoPtr<PluginModuleParent> parent(new PluginModuleParent(aFilePath));
|
||||
nsAutoPtr<PluginModuleChromeParent> parent(new PluginModuleChromeParent(aFilePath, aPluginId));
|
||||
bool launched = parent->mSubprocess->Launch(prefSecs * 1000);
|
||||
if (!launched) {
|
||||
// We never reached open
|
||||
|
@ -124,15 +193,40 @@ PluginModuleParent::LoadModule(const char* aFilePath)
|
|||
return parent.forget();
|
||||
}
|
||||
|
||||
|
||||
PluginModuleParent::PluginModuleParent(const char* aFilePath)
|
||||
: mSubprocess(new PluginProcessParent(aFilePath))
|
||||
PluginModuleParent::PluginModuleParent(bool aIsChrome)
|
||||
: mIsChrome(aIsChrome)
|
||||
, mShutdown(false)
|
||||
, mClearSiteDataSupported(false)
|
||||
, mGetSitesWithDataSupported(false)
|
||||
, mNPNIface(nullptr)
|
||||
, mPlugin(nullptr)
|
||||
, mTaskFactory(MOZ_THIS_IN_INITIALIZER_LIST())
|
||||
{
|
||||
}
|
||||
|
||||
PluginModuleParent::~PluginModuleParent()
|
||||
{
|
||||
if (!OkToCleanup()) {
|
||||
NS_RUNTIMEABORT("unsafe destruction");
|
||||
}
|
||||
|
||||
if (!mShutdown) {
|
||||
NS_WARNING("Plugin host deleted the module without shutting down.");
|
||||
NPError err;
|
||||
NP_Shutdown(&err);
|
||||
}
|
||||
}
|
||||
|
||||
PluginModuleContentParent::PluginModuleContentParent()
|
||||
: PluginModuleParent(false)
|
||||
{
|
||||
}
|
||||
|
||||
PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId)
|
||||
: PluginModuleParent(true)
|
||||
, mSubprocess(new PluginProcessParent(aFilePath))
|
||||
, mPluginId(aPluginId)
|
||||
, mChromeTaskFactory(MOZ_THIS_IN_INITIALIZER_LIST())
|
||||
, mHangAnnotationFlags(0)
|
||||
#ifdef XP_WIN
|
||||
, mPluginCpuUsageOnHang()
|
||||
|
@ -165,7 +259,7 @@ PluginModuleParent::PluginModuleParent(const char* aFilePath)
|
|||
mozilla::HangMonitor::RegisterAnnotator(*this);
|
||||
}
|
||||
|
||||
PluginModuleParent::~PluginModuleParent()
|
||||
PluginModuleChromeParent::~PluginModuleChromeParent()
|
||||
{
|
||||
if (!OkToCleanup()) {
|
||||
NS_RUNTIMEABORT("unsafe destruction");
|
||||
|
@ -212,7 +306,7 @@ PluginModuleParent::~PluginModuleParent()
|
|||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void
|
||||
PluginModuleParent::WriteExtraDataForMinidump(AnnotationTable& notes)
|
||||
PluginModuleChromeParent::WriteExtraDataForMinidump(AnnotationTable& notes)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
// mCrashReporterMutex is already held by the caller
|
||||
|
@ -257,7 +351,7 @@ PluginModuleParent::WriteExtraDataForMinidump(AnnotationTable& notes)
|
|||
#endif // MOZ_CRASHREPORTER
|
||||
|
||||
void
|
||||
PluginModuleParent::SetChildTimeout(const int32_t aChildTimeout)
|
||||
PluginModuleChromeParent::SetChildTimeout(const int32_t aChildTimeout)
|
||||
{
|
||||
int32_t timeoutMs = (aChildTimeout > 0) ? (1000 * aChildTimeout) :
|
||||
MessageChannel::kNoTimeout;
|
||||
|
@ -265,29 +359,29 @@ PluginModuleParent::SetChildTimeout(const int32_t aChildTimeout)
|
|||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule)
|
||||
PluginModuleChromeParent::TimeoutChanged(const char* aPref, void* aModule)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
#ifndef XP_WIN
|
||||
if (!strcmp(aPref, kChildTimeoutPref)) {
|
||||
// The timeout value used by the parent for children
|
||||
int32_t timeoutSecs = Preferences::GetInt(kChildTimeoutPref, 0);
|
||||
static_cast<PluginModuleParent*>(aModule)->SetChildTimeout(timeoutSecs);
|
||||
static_cast<PluginModuleChromeParent*>(aModule)->SetChildTimeout(timeoutSecs);
|
||||
#else
|
||||
if (!strcmp(aPref, kChildTimeoutPref) ||
|
||||
!strcmp(aPref, kHangUIMinDisplayPref) ||
|
||||
!strcmp(aPref, kHangUITimeoutPref)) {
|
||||
static_cast<PluginModuleParent*>(aModule)->EvaluateHangUIState(true);
|
||||
static_cast<PluginModuleChromeParent*>(aModule)->EvaluateHangUIState(true);
|
||||
#endif // XP_WIN
|
||||
} else if (!strcmp(aPref, kParentTimeoutPref)) {
|
||||
// The timeout value used by the child for its parent
|
||||
int32_t timeoutSecs = Preferences::GetInt(kParentTimeoutPref, 0);
|
||||
unused << static_cast<PluginModuleParent*>(aModule)->SendSetParentHangTimeout(timeoutSecs);
|
||||
unused << static_cast<PluginModuleChromeParent*>(aModule)->SendSetParentHangTimeout(timeoutSecs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::CleanupFromTimeout(const bool aFromHangUI)
|
||||
PluginModuleChromeParent::CleanupFromTimeout(const bool aFromHangUI)
|
||||
{
|
||||
if (mShutdown) {
|
||||
return;
|
||||
|
@ -297,8 +391,8 @@ PluginModuleParent::CleanupFromTimeout(const bool aFromHangUI)
|
|||
// there's still plugin code on the C++ stack, try again
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
mTaskFactory.NewRunnableMethod(
|
||||
&PluginModuleParent::CleanupFromTimeout, aFromHangUI), 10);
|
||||
mChromeTaskFactory.NewRunnableMethod(
|
||||
&PluginModuleChromeParent::CleanupFromTimeout, aFromHangUI), 10);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -385,13 +479,13 @@ GetProcessCpuUsage(const InfallibleTArray<base::ProcessHandle>& processHandles,
|
|||
#endif // #ifdef XP_WIN
|
||||
|
||||
void
|
||||
PluginModuleParent::EnteredCxxStack()
|
||||
PluginModuleChromeParent::EnteredCxxStack()
|
||||
{
|
||||
mHangAnnotationFlags |= kInPluginCall;
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::ExitedCxxStack()
|
||||
PluginModuleChromeParent::ExitedCxxStack()
|
||||
{
|
||||
mHangAnnotationFlags = 0;
|
||||
#ifdef XP_WIN
|
||||
|
@ -403,7 +497,7 @@ PluginModuleParent::ExitedCxxStack()
|
|||
* This function is always called by the HangMonitor thread.
|
||||
*/
|
||||
void
|
||||
PluginModuleParent::AnnotateHang(mozilla::HangMonitor::HangAnnotations& aAnnotations)
|
||||
PluginModuleChromeParent::AnnotateHang(mozilla::HangMonitor::HangAnnotations& aAnnotations)
|
||||
{
|
||||
uint32_t flags = mHangAnnotationFlags;
|
||||
if (flags) {
|
||||
|
@ -451,7 +545,7 @@ CreateFlashMinidump(DWORD processId, ThreadId childThread,
|
|||
#endif
|
||||
|
||||
bool
|
||||
PluginModuleParent::ShouldContinueFromReplyTimeout()
|
||||
PluginModuleChromeParent::ShouldContinueFromReplyTimeout()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
if (LaunchHangUI()) {
|
||||
|
@ -466,7 +560,7 @@ PluginModuleParent::ShouldContinueFromReplyTimeout()
|
|||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::TerminateChildProcess(MessageLoop* aMsgLoop)
|
||||
PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#ifdef XP_WIN
|
||||
|
@ -556,8 +650,8 @@ PluginModuleParent::TerminateChildProcess(MessageLoop* aMsgLoop)
|
|||
bool isFromHangUI = aMsgLoop != MessageLoop::current();
|
||||
aMsgLoop->PostTask(
|
||||
FROM_HERE,
|
||||
mTaskFactory.NewRunnableMethod(
|
||||
&PluginModuleParent::CleanupFromTimeout, isFromHangUI));
|
||||
mChromeTaskFactory.NewRunnableMethod(
|
||||
&PluginModuleChromeParent::CleanupFromTimeout, isFromHangUI));
|
||||
|
||||
if (!KillProcess(OtherProcess(), 1, false))
|
||||
NS_WARNING("failed to kill subprocess!");
|
||||
|
@ -582,7 +676,7 @@ PluginModuleParent::GetPluginDetails(nsACString& aPluginName,
|
|||
|
||||
#ifdef XP_WIN
|
||||
void
|
||||
PluginModuleParent::EvaluateHangUIState(const bool aReset)
|
||||
PluginModuleChromeParent::EvaluateHangUIState(const bool aReset)
|
||||
{
|
||||
int32_t minDispSecs = Preferences::GetInt(kHangUIMinDisplayPref, 10);
|
||||
int32_t autoStopSecs = Preferences::GetInt(kChildTimeoutPref, 0);
|
||||
|
@ -616,7 +710,7 @@ PluginModuleParent::EvaluateHangUIState(const bool aReset)
|
|||
}
|
||||
|
||||
bool
|
||||
PluginModuleParent::LaunchHangUI()
|
||||
PluginModuleChromeParent::LaunchHangUI()
|
||||
{
|
||||
if (!mHangUIEnabled) {
|
||||
return false;
|
||||
|
@ -653,7 +747,7 @@ PluginModuleParent::LaunchHangUI()
|
|||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::FinishHangUI()
|
||||
PluginModuleChromeParent::FinishHangUI()
|
||||
{
|
||||
if (mHangUIEnabled && mHangUIParent) {
|
||||
bool needsCancel = mHangUIParent->IsShowing();
|
||||
|
@ -674,7 +768,7 @@ PluginModuleParent::FinishHangUI()
|
|||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::OnHangUIContinue()
|
||||
PluginModuleChromeParent::OnHangUIContinue()
|
||||
{
|
||||
mHangAnnotationFlags |= kHangUIContinued;
|
||||
}
|
||||
|
@ -682,7 +776,7 @@ PluginModuleParent::OnHangUIContinue()
|
|||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
CrashReporterParent*
|
||||
PluginModuleParent::CrashReporter()
|
||||
PluginModuleChromeParent::CrashReporter()
|
||||
{
|
||||
return static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
|
||||
}
|
||||
|
@ -704,7 +798,7 @@ RemoveMinidump(nsIFile* minidump)
|
|||
#endif // MOZ_CRASHREPORTER_INJECTOR
|
||||
|
||||
void
|
||||
PluginModuleParent::ProcessFirstMinidump()
|
||||
PluginModuleChromeParent::ProcessFirstMinidump()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
mozilla::MutexAutoLock lock(mCrashReporterMutex);
|
||||
|
@ -781,10 +875,6 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
|
|||
{
|
||||
switch (why) {
|
||||
case AbnormalShutdown: {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
ProcessFirstMinidump();
|
||||
#endif
|
||||
|
||||
mShutdown = true;
|
||||
// Defer the PluginCrashed method so that we don't re-enter
|
||||
// and potentially modify the actor child list while enumerating it.
|
||||
|
@ -804,6 +894,18 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChromeParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (why == AbnormalShutdown) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
ProcessFirstMinidump();
|
||||
#endif
|
||||
}
|
||||
|
||||
PluginModuleParent::ActorDestroy(why);
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::NotifyPluginCrashed()
|
||||
{
|
||||
|
@ -1173,13 +1275,16 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!CallNP_Initialize(error)) {
|
||||
Close();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else if (*error != NPERR_NO_ERROR) {
|
||||
Close();
|
||||
return NS_OK;
|
||||
*error = NPERR_NO_ERROR;
|
||||
if (IsChrome()) {
|
||||
if (!CallNP_Initialize(error)) {
|
||||
Close();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else if (*error != NPERR_NO_ERROR) {
|
||||
Close();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
SetPluginFuncs(pFuncs);
|
||||
|
@ -1199,6 +1304,17 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*error = NPERR_NO_ERROR;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginModuleChromeParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
|
||||
{
|
||||
nsresult rv = PluginModuleParent::NP_Initialize(bFuncs, error);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!CallNP_Initialize(error)) {
|
||||
Close();
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1238,7 +1354,10 @@ PluginModuleParent::NP_Shutdown(NPError* error)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool ok = CallNP_Shutdown(error);
|
||||
bool ok = true;
|
||||
if (IsChrome()) {
|
||||
ok = CallNP_Shutdown(error);
|
||||
}
|
||||
|
||||
// if NP_Shutdown() is nested within another interrupt call, this will
|
||||
// break things. but lord help us if we're doing that anyway; the
|
||||
|
@ -1276,16 +1395,21 @@ PluginModuleParent::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error)
|
|||
{
|
||||
NS_ASSERTION(pFuncs, "Null pointer!");
|
||||
|
||||
// We need to have the child process update its function table
|
||||
// here by actually calling NP_GetEntryPoints since the parent's
|
||||
// function table can reflect nullptr entries in the child's table.
|
||||
if (!CallNP_GetEntryPoints(error)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else if (*error != NPERR_NO_ERROR) {
|
||||
return NS_OK;
|
||||
// We need to have the plugin process update its function table here by
|
||||
// actually calling NP_GetEntryPoints. The parent's function table will
|
||||
// reflect nullptr entries in the child's table once SetPluginFuncs is
|
||||
// called.
|
||||
|
||||
if (IsChrome()) {
|
||||
if (!CallNP_GetEntryPoints(error)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else if (*error != NPERR_NO_ERROR) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
*error = NPERR_NO_ERROR;
|
||||
SetPluginFuncs(pFuncs);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1347,11 +1471,17 @@ PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
TimeoutChanged(kParentTimeoutPref, this);
|
||||
|
||||
UpdatePluginTimeout();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChromeParent::UpdatePluginTimeout()
|
||||
{
|
||||
TimeoutChanged(kParentTimeoutPref, this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::NPP_ClearSiteData(const char* site, uint64_t flags,
|
||||
uint64_t maxAge)
|
||||
|
@ -1527,6 +1657,19 @@ PluginModuleParent::RecvPluginHideWindow(const uint32_t& aWindowId)
|
|||
PCrashReporterParent*
|
||||
PluginModuleParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
|
||||
uint32_t* processType)
|
||||
{
|
||||
MOZ_CRASH("unreachable");
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
|
||||
{
|
||||
MOZ_CRASH("unreachable");
|
||||
}
|
||||
|
||||
PCrashReporterParent*
|
||||
PluginModuleChromeParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
|
||||
uint32_t* processType)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
return new CrashReporterParent();
|
||||
|
@ -1536,7 +1679,7 @@ PluginModuleParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
|
|||
}
|
||||
|
||||
bool
|
||||
PluginModuleParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
|
||||
PluginModuleChromeParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#ifdef XP_WIN
|
||||
|
@ -1622,20 +1765,12 @@ PluginModuleParent::RecvGetNativeCursorsSupported(bool* supported)
|
|||
}
|
||||
|
||||
bool
|
||||
PluginModuleParent::RecvNPN_SetException(PPluginScriptableObjectParent* aActor,
|
||||
const nsCString& aMessage)
|
||||
PluginModuleParent::RecvNPN_SetException(const nsCString& aMessage)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
|
||||
|
||||
NPObject* aNPObj = nullptr;
|
||||
if (aActor) {
|
||||
aNPObj = static_cast<PluginScriptableObjectParent*>(aActor)->GetObject(true);
|
||||
if (!aNPObj) {
|
||||
NS_ERROR("Failed to get object!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
mozilla::plugins::parent::_setexception(aNPObj, NullableStringGet(aMessage));
|
||||
// This function ignores its first argument.
|
||||
mozilla::plugins::parent::_setexception(nullptr, NullableStringGet(aMessage));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1648,6 +1783,16 @@ PluginModuleParent::RecvNPN_ReloadPlugins(const bool& aReloadPages)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChromeParent::RecvNotifyContentModuleDestroyed()
|
||||
{
|
||||
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
|
||||
if (host) {
|
||||
host->NotifyContentModuleDestroyed(mPluginId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
|
||||
// We only add the crash reporter to subprocess which have the filename
|
||||
|
@ -1678,7 +1823,7 @@ GetFlashChildOfPID(DWORD pid, HANDLE snapshot)
|
|||
#define FLASH_PLUGIN_PREFIX "NPSWF"
|
||||
|
||||
void
|
||||
PluginModuleParent::InitializeInjector()
|
||||
PluginModuleChromeParent::InitializeInjector()
|
||||
{
|
||||
if (!Preferences::GetBool("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false))
|
||||
return;
|
||||
|
@ -1710,7 +1855,7 @@ PluginModuleParent::InitializeInjector()
|
|||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::OnCrash(DWORD processID)
|
||||
PluginModuleChromeParent::OnCrash(DWORD processID)
|
||||
{
|
||||
if (!mShutdown) {
|
||||
GetIPCChannel()->CloseWithError();
|
||||
|
@ -1756,7 +1901,7 @@ PluginProfilerObserver::Observe(nsISupports *aSubject,
|
|||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::InitPluginProfiling()
|
||||
PluginModuleChromeParent::InitPluginProfiling()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
|
@ -1766,7 +1911,7 @@ PluginModuleParent::InitPluginProfiling()
|
|||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::ShutdownPluginProfiling()
|
||||
PluginModuleChromeParent::ShutdownPluginProfiling()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
|
|
|
@ -53,6 +53,12 @@ class PluginHangUIParent;
|
|||
* This class /also/ implements a version of the NPN API, because the
|
||||
* child process needs to make these calls back into Gecko proper.
|
||||
* This class is responsible for "actually" making those function calls.
|
||||
*
|
||||
* If a plugin is running, there will always be one PluginModuleParent for it in
|
||||
* the chrome process. In addition, any content process using the plugin will
|
||||
* have its own PluginModuleParent. The subclasses PluginModuleChromeParent and
|
||||
* PluginModuleContentParent implement functionality that is specific to one
|
||||
* case or the other.
|
||||
*/
|
||||
class PluginModuleParent
|
||||
: public PPluginModuleParent
|
||||
|
@ -60,15 +66,12 @@ class PluginModuleParent
|
|||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
, public CrashReporter::InjectorCrashCallback
|
||||
#endif
|
||||
, public mozilla::HangMonitor::Annotator
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
typedef mozilla::PluginLibrary PluginLibrary;
|
||||
typedef mozilla::dom::PCrashReporterParent PCrashReporterParent;
|
||||
typedef mozilla::dom::CrashReporterParent CrashReporterParent;
|
||||
|
||||
protected:
|
||||
|
||||
PPluginInstanceParent*
|
||||
AllocPPluginInstanceParent(const nsCString& aMimeType,
|
||||
const uint16_t& aMode,
|
||||
|
@ -80,10 +83,11 @@ protected:
|
|||
DeallocPPluginInstanceParent(PPluginInstanceParent* aActor) MOZ_OVERRIDE;
|
||||
|
||||
public:
|
||||
// aFilePath is UTF8, not native!
|
||||
explicit PluginModuleParent(const char* aFilePath);
|
||||
explicit PluginModuleParent(bool aIsChrome);
|
||||
virtual ~PluginModuleParent();
|
||||
|
||||
bool IsChrome() const { return mIsChrome; }
|
||||
|
||||
virtual void SetPlugin(nsNPAPIPlugin* plugin) MOZ_OVERRIDE
|
||||
{
|
||||
mPlugin = plugin;
|
||||
|
@ -91,47 +95,16 @@ public:
|
|||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* LoadModule
|
||||
*
|
||||
* This may or may not launch a plugin child process,
|
||||
* and may or may not be very expensive.
|
||||
*/
|
||||
static PluginLibrary* LoadModule(const char* aFilePath);
|
||||
|
||||
const NPNetscapeFuncs* GetNetscapeFuncs() {
|
||||
return mNPNIface;
|
||||
}
|
||||
|
||||
PluginProcessParent* Process() const { return mSubprocess; }
|
||||
base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
|
||||
|
||||
bool OkToCleanup() const {
|
||||
return !IsOnCxxStack();
|
||||
}
|
||||
|
||||
void ProcessRemoteNativeEventsInInterruptCall();
|
||||
|
||||
void TerminateChildProcess(MessageLoop* aMsgLoop);
|
||||
|
||||
virtual void
|
||||
EnteredCxxStack() MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
ExitedCxxStack() MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
AnnotateHang(mozilla::HangMonitor::HangAnnotations& aAnnotations) MOZ_OVERRIDE;
|
||||
|
||||
#ifdef XP_WIN
|
||||
/**
|
||||
* Called by Plugin Hang UI to notify that the user has clicked continue.
|
||||
* Used for chrome hang annotations.
|
||||
*/
|
||||
void
|
||||
OnHangUIContinue();
|
||||
#endif // XP_WIN
|
||||
|
||||
protected:
|
||||
virtual mozilla::ipc::RacyInterruptPolicy
|
||||
MediateInterruptRace(const Message& parent, const Message& child) MOZ_OVERRIDE
|
||||
|
@ -139,8 +112,6 @@ protected:
|
|||
return MediateRace(parent, child);
|
||||
}
|
||||
|
||||
virtual bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvBackUpXResources(const FileDescriptor& aXSocketFd) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -187,8 +158,7 @@ protected:
|
|||
RecvGetNativeCursorsSupported(bool* supported) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNPN_SetException(PPluginScriptableObjectParent* aActor,
|
||||
const nsCString& aMessage) MOZ_OVERRIDE;
|
||||
RecvNPN_SetException(const nsCString& aMessage) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNPN_ReloadPlugins(const bool& aReloadPages) MOZ_OVERRIDE;
|
||||
|
@ -196,18 +166,12 @@ protected:
|
|||
static PluginInstanceParent* InstCast(NPP instance);
|
||||
static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
|
||||
|
||||
private:
|
||||
void SetPluginFuncs(NPPluginFuncs* aFuncs);
|
||||
protected:
|
||||
virtual void UpdatePluginTimeout() {}
|
||||
|
||||
// Implement the module-level functions from NPAPI; these are
|
||||
// normally resolved directly from the DSO.
|
||||
#ifdef OS_LINUX
|
||||
NPError NP_Initialize(const NPNetscapeFuncs* npnIface,
|
||||
NPPluginFuncs* nppIface);
|
||||
#else
|
||||
NPError NP_Initialize(const NPNetscapeFuncs* npnIface);
|
||||
NPError NP_GetEntryPoints(NPPluginFuncs* nppIface);
|
||||
#endif
|
||||
virtual bool RecvNotifyContentModuleDestroyed() MOZ_OVERRIDE { return true; }
|
||||
|
||||
void SetPluginFuncs(NPPluginFuncs* aFuncs);
|
||||
|
||||
// NPP-like API that Gecko calls are trampolined into. These
|
||||
// messages then get forwarded along to the plugin instance,
|
||||
|
@ -255,6 +219,7 @@ private:
|
|||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error);
|
||||
#endif
|
||||
virtual nsresult NP_Shutdown(NPError* error);
|
||||
|
||||
virtual nsresult NP_GetMIMEDescription(const char** mimeDesc);
|
||||
virtual nsresult NP_GetValue(void *future, NPPVariable aVariable,
|
||||
void *aValue, NPError* error);
|
||||
|
@ -274,24 +239,10 @@ private:
|
|||
virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor);
|
||||
#endif
|
||||
|
||||
private:
|
||||
CrashReporterParent* CrashReporter();
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void ProcessFirstMinidump();
|
||||
void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
|
||||
#endif
|
||||
void CleanupFromTimeout(const bool aByHangUI);
|
||||
void SetChildTimeout(const int32_t aChildTimeout);
|
||||
static void TimeoutChanged(const char* aPref, void* aModule);
|
||||
protected:
|
||||
void NotifyPluginCrashed();
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
void InitPluginProfiling();
|
||||
void ShutdownPluginProfiling();
|
||||
#endif
|
||||
|
||||
PluginProcessParent* mSubprocess;
|
||||
bool mIsChrome;
|
||||
bool mShutdown;
|
||||
bool mClearSiteDataSupported;
|
||||
bool mGetSitesWithDataSupported;
|
||||
|
@ -302,6 +253,120 @@ private:
|
|||
nsString mBrowserDumpID;
|
||||
nsString mHangID;
|
||||
nsRefPtr<nsIObserver> mProfilerObserver;
|
||||
nsCString mPluginName;
|
||||
nsCString mPluginVersion;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// Dup of plugin's X socket, used to scope its resources to this
|
||||
// object instead of the plugin process's lifetime
|
||||
ScopedClose mPluginXSocketFdDup;
|
||||
#endif
|
||||
|
||||
bool
|
||||
GetPluginDetails(nsACString& aPluginName, nsACString& aPluginVersion);
|
||||
|
||||
friend class mozilla::dom::CrashReporterParent;
|
||||
};
|
||||
|
||||
class PluginModuleContentParent : public PluginModuleParent
|
||||
{
|
||||
public:
|
||||
static PluginLibrary* LoadModule(uint32_t aPluginId);
|
||||
|
||||
static PluginModuleContentParent* Create(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess);
|
||||
|
||||
private:
|
||||
explicit PluginModuleContentParent();
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
void OnCrash(DWORD processID) MOZ_OVERRIDE {}
|
||||
#endif
|
||||
|
||||
static PluginModuleContentParent* sSavedModuleParent;
|
||||
};
|
||||
|
||||
class PluginModuleChromeParent
|
||||
: public PluginModuleParent
|
||||
, public mozilla::HangMonitor::Annotator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* LoadModule
|
||||
*
|
||||
* This may or may not launch a plugin child process,
|
||||
* and may or may not be very expensive.
|
||||
*/
|
||||
static PluginLibrary* LoadModule(const char* aFilePath, uint32_t aPluginId);
|
||||
|
||||
virtual ~PluginModuleChromeParent();
|
||||
|
||||
void TerminateChildProcess(MessageLoop* aMsgLoop);
|
||||
|
||||
#ifdef XP_WIN
|
||||
/**
|
||||
* Called by Plugin Hang UI to notify that the user has clicked continue.
|
||||
* Used for chrome hang annotations.
|
||||
*/
|
||||
void
|
||||
OnHangUIContinue();
|
||||
#endif // XP_WIN
|
||||
|
||||
private:
|
||||
virtual void
|
||||
EnteredCxxStack() MOZ_OVERRIDE;
|
||||
|
||||
void
|
||||
ExitedCxxStack() MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
AnnotateHang(mozilla::HangMonitor::HangAnnotations& aAnnotations) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void ProcessFirstMinidump();
|
||||
void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
|
||||
#endif
|
||||
|
||||
virtual PCrashReporterParent*
|
||||
AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
|
||||
uint32_t* processType) MOZ_OVERRIDE;
|
||||
virtual bool
|
||||
DeallocPCrashReporterParent(PCrashReporterParent* actor) MOZ_OVERRIDE;
|
||||
|
||||
PluginProcessParent* Process() const { return mSubprocess; }
|
||||
base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
|
||||
|
||||
#if !defined(XP_UNIX) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GONK)
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error);
|
||||
#endif
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
|
||||
// aFilePath is UTF8, not native!
|
||||
explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId);
|
||||
|
||||
CrashReporterParent* CrashReporter();
|
||||
|
||||
void CleanupFromTimeout(const bool aByHangUI);
|
||||
void SetChildTimeout(const int32_t aChildTimeout);
|
||||
static void TimeoutChanged(const char* aPref, void* aModule);
|
||||
|
||||
virtual void UpdatePluginTimeout() MOZ_OVERRIDE;
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
void InitPluginProfiling();
|
||||
void ShutdownPluginProfiling();
|
||||
#endif
|
||||
|
||||
virtual bool RecvNotifyContentModuleDestroyed() MOZ_OVERRIDE;
|
||||
|
||||
PluginProcessParent* mSubprocess;
|
||||
uint32_t mPluginId;
|
||||
|
||||
ScopedMethodFactory<PluginModuleChromeParent> mChromeTaskFactory;
|
||||
|
||||
enum HangAnnotationFlags
|
||||
{
|
||||
kInPluginCall = (1u << 0),
|
||||
|
@ -310,8 +375,6 @@ private:
|
|||
kHangUIDontShow = (1u << 3)
|
||||
};
|
||||
Atomic<uint32_t> mHangAnnotationFlags;
|
||||
nsCString mPluginName;
|
||||
nsCString mPluginVersion;
|
||||
#ifdef XP_WIN
|
||||
InfallibleTArray<float> mPluginCpuUsageOnHang;
|
||||
PluginHangUIParent *mHangUIParent;
|
||||
|
@ -349,15 +412,6 @@ private:
|
|||
FinishHangUI();
|
||||
#endif
|
||||
|
||||
bool
|
||||
GetPluginDetails(nsACString& aPluginName, nsACString& aPluginVersion);
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// Dup of plugin's X socket, used to scope its resources to this
|
||||
// object instead of the plugin process's lifetime
|
||||
ScopedClose mPluginXSocketFdDup;
|
||||
#endif
|
||||
|
||||
friend class mozilla::dom::CrashReporterParent;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
|
|
|
@ -119,9 +119,9 @@ PluginProcessChild::Init()
|
|||
return false;
|
||||
}
|
||||
|
||||
return mPlugin.Init(pluginFilename, ParentHandle(),
|
||||
IOThreadChild::message_loop(),
|
||||
IOThreadChild::channel());
|
||||
return mPlugin.InitForChrome(pluginFilename, ParentHandle(),
|
||||
IOThreadChild::message_loop(),
|
||||
IOThreadChild::channel());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -19,7 +19,8 @@ protected:
|
|||
typedef mozilla::ipc::ProcessChild ProcessChild;
|
||||
|
||||
public:
|
||||
explicit PluginProcessChild(ProcessHandle aParentHandle) : ProcessChild(aParentHandle)
|
||||
explicit PluginProcessChild(ProcessHandle aParentHandle)
|
||||
: ProcessChild(aParentHandle), mPlugin(true)
|
||||
{ }
|
||||
|
||||
virtual ~PluginProcessChild()
|
||||
|
|
|
@ -539,7 +539,7 @@ PluginScriptableObjectChild::~PluginScriptableObjectChild()
|
|||
AssertPluginThread();
|
||||
|
||||
if (mObject) {
|
||||
PluginModuleChild::current()->UnregisterActorForNPObject(mObject);
|
||||
UnregisterActor(mObject);
|
||||
|
||||
if (mObject->_class == GetClass()) {
|
||||
NS_ASSERTION(mType == Proxy, "Wrong type!");
|
||||
|
@ -569,8 +569,8 @@ PluginScriptableObjectChild::InitializeProxy()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!PluginModuleChild::current()->RegisterActorForNPObject(object, this)) {
|
||||
NS_ERROR("RegisterActorForNPObject failed");
|
||||
if (!RegisterActor(object)) {
|
||||
NS_ERROR("RegisterActor failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -594,8 +594,8 @@ PluginScriptableObjectChild::InitializeLocal(NPObject* aObject)
|
|||
NS_ASSERTION(!mProtectCount, "Should be zero!");
|
||||
mProtectCount++;
|
||||
|
||||
if (!PluginModuleChild::current()->RegisterActorForNPObject(aObject, this)) {
|
||||
NS_ERROR("RegisterActorForNPObject failed");
|
||||
if (!RegisterActor(aObject)) {
|
||||
NS_ERROR("RegisterActor failed");
|
||||
}
|
||||
|
||||
mObject = aObject;
|
||||
|
@ -688,7 +688,7 @@ PluginScriptableObjectChild::DropNPObject()
|
|||
|
||||
// We think we're about to be deleted, but we could be racing with the other
|
||||
// process.
|
||||
PluginModuleChild::current()->UnregisterActorForNPObject(mObject);
|
||||
UnregisterActor(mObject);
|
||||
mObject = nullptr;
|
||||
|
||||
SendUnprotect();
|
||||
|
@ -1181,3 +1181,105 @@ PluginScriptableObjectChild::Evaluate(NPString* aScript,
|
|||
ConvertToVariant(result, *aResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsTHashtable<PluginScriptableObjectChild::NPObjectData>* PluginScriptableObjectChild::sObjectMap;
|
||||
|
||||
bool
|
||||
PluginScriptableObjectChild::RegisterActor(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("NPObject not in object table");
|
||||
return false;
|
||||
}
|
||||
|
||||
d->actor = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginScriptableObjectChild::UnregisterActor(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
MOZ_ASSERT(d, "NPObject not in object table");
|
||||
if (d) {
|
||||
d->actor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ PluginScriptableObjectChild*
|
||||
PluginScriptableObjectChild::GetActorForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("Plugin using object not created with NPN_CreateObject?");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return d->actor;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginScriptableObjectChild::RegisterObject(NPObject* aObject, PluginInstanceChild* aInstance)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
if (!sObjectMap) {
|
||||
sObjectMap = new nsTHashtable<PluginScriptableObjectChild::NPObjectData>();
|
||||
}
|
||||
|
||||
NPObjectData* d = sObjectMap->PutEntry(aObject);
|
||||
MOZ_ASSERT(!d->instance, "New NPObject already mapped?");
|
||||
d->instance = aInstance;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginScriptableObjectChild::UnregisterObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
sObjectMap->RemoveEntry(aObject);
|
||||
|
||||
if (!sObjectMap->Count()) {
|
||||
delete sObjectMap;
|
||||
sObjectMap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ PluginInstanceChild*
|
||||
PluginScriptableObjectChild::GetInstanceForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
if (!d) {
|
||||
return nullptr;
|
||||
}
|
||||
return d->instance;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
PluginScriptableObjectChild::CollectForInstance(NPObjectData* d, void* userArg)
|
||||
{
|
||||
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
|
||||
if (d->instance == instance) {
|
||||
NPObject* o = d->GetKey();
|
||||
instance->mDeletingHash->PutEntry(o);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginScriptableObjectChild::NotifyOfInstanceShutdown(PluginInstanceChild* aInstance)
|
||||
{
|
||||
AssertPluginThread();
|
||||
sObjectMap->EnumerateEntries(CollectForInstance, aInstance);
|
||||
}
|
||||
|
|
|
@ -217,6 +217,22 @@ public:
|
|||
|
||||
static void ClearIdentifiers();
|
||||
|
||||
bool RegisterActor(NPObject* aObject);
|
||||
void UnregisterActor(NPObject* aObject);
|
||||
|
||||
static PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
|
||||
|
||||
static void RegisterObject(NPObject* aObject, PluginInstanceChild* aInstance);
|
||||
static void UnregisterObject(NPObject* aObject);
|
||||
|
||||
static PluginInstanceChild* GetInstanceForNPObject(NPObject* aObject);
|
||||
|
||||
/**
|
||||
* Fill PluginInstanceChild.mDeletingHash with all the remaining NPObjects
|
||||
* associated with that instance.
|
||||
*/
|
||||
static void NotifyOfInstanceShutdown(PluginInstanceChild* aInstance);
|
||||
|
||||
private:
|
||||
static NPObject*
|
||||
ScriptableAllocate(NPP aInstance,
|
||||
|
@ -297,6 +313,29 @@ private:
|
|||
|
||||
typedef nsDataHashtable<nsCStringHashKey, nsRefPtr<StoredIdentifier>> IdentifierTable;
|
||||
static IdentifierTable sIdentifiers;
|
||||
|
||||
struct NPObjectData : public nsPtrHashKey<NPObject>
|
||||
{
|
||||
explicit NPObjectData(const NPObject* key)
|
||||
: nsPtrHashKey<NPObject>(key),
|
||||
instance(nullptr),
|
||||
actor(nullptr)
|
||||
{ }
|
||||
|
||||
// never nullptr
|
||||
PluginInstanceChild* instance;
|
||||
|
||||
// sometimes nullptr (no actor associated with an NPObject)
|
||||
PluginScriptableObjectChild* actor;
|
||||
};
|
||||
|
||||
static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
|
||||
|
||||
/**
|
||||
* mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
|
||||
* final release/dealloc, whether or not an actor is currently associated with the object.
|
||||
*/
|
||||
static nsTHashtable<NPObjectData>* sObjectMap;
|
||||
};
|
||||
|
||||
} /* namespace plugins */
|
||||
|
|
|
@ -90,7 +90,7 @@ mozilla::plugins::ConvertToVariant(const Variant& aRemoteVariant,
|
|||
|
||||
case Variant::TPPluginScriptableObjectChild: {
|
||||
NS_ASSERTION(!aInstance, "No instance should be given!");
|
||||
NS_ASSERTION(PluginModuleChild::current(),
|
||||
NS_ASSERTION(XRE_GetProcessType() == GeckoProcessType_Plugin,
|
||||
"Should be running on child only!");
|
||||
|
||||
NPObject* object = NPObjectFromVariant(aRemoteVariant);
|
||||
|
|
|
@ -112,7 +112,7 @@ ReleaseRemoteVariant(Variant& aVariant)
|
|||
}
|
||||
|
||||
case Variant::TPPluginScriptableObjectChild: {
|
||||
NS_ASSERTION(PluginModuleChild::current(),
|
||||
NS_ASSERTION(XRE_GetProcessType() == GeckoProcessType_Plugin,
|
||||
"Should only be running in the child!");
|
||||
PluginScriptableObjectChild* actor =
|
||||
const_cast<PluginScriptableObjectChild*>(
|
||||
|
|
|
@ -6,6 +6,22 @@
|
|||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
struct PluginTag
|
||||
{
|
||||
uint32_t id;
|
||||
nsCString name;
|
||||
nsCString description;
|
||||
nsCString[] mimeTypes;
|
||||
nsCString[] mimeDescriptions;
|
||||
nsCString[] extensions;
|
||||
bool isJavaPlugin;
|
||||
bool isFlashPlugin;
|
||||
nsCString filename;
|
||||
nsCString version;
|
||||
int64_t lastModifiedTime;
|
||||
bool isFromExtension;
|
||||
};
|
||||
|
||||
union PluginIdentifier
|
||||
{
|
||||
nsCString;
|
||||
|
|
|
@ -21,6 +21,7 @@ EXPORTS.mozilla.plugins += [
|
|||
'NPEventOSX.h',
|
||||
'NPEventUnix.h',
|
||||
'NPEventWindows.h',
|
||||
'PluginBridge.h',
|
||||
'PluginInstanceChild.h',
|
||||
'PluginInstanceParent.h',
|
||||
'PluginMessageUtils.h',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[DEFAULT]
|
||||
skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') || e10s #b2g-desktop(tests that use plugins)
|
||||
skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') || (e10s && debug) #b2g-desktop(tests that use plugins)
|
||||
support-files =
|
||||
307-xo-redirect.sjs
|
||||
crashing_subpage.html
|
||||
|
@ -63,8 +63,9 @@ skip-if = !crashreporter || e10s
|
|||
[test_enumerate.html]
|
||||
[test_fullpage.html]
|
||||
[test_getauthenticationinfo.html]
|
||||
skip-if = e10s
|
||||
[test_hanging.html]
|
||||
skip-if = !crashreporter
|
||||
skip-if = !crashreporter || e10s
|
||||
[test_instance_re-parent.html]
|
||||
[test_instance_unparent1.html]
|
||||
[test_instance_unparent2.html]
|
||||
|
@ -81,7 +82,6 @@ skip-if = !crashreporter
|
|||
[test_npruntime_npnevaluate.html]
|
||||
[test_npruntime_npninvoke.html]
|
||||
[test_npruntime_npninvokedefault.html]
|
||||
[test_npruntime_npnsetexception.html]
|
||||
[test_painting.html]
|
||||
[test_plugin_scroll_painting.html]
|
||||
skip-if = true # Bug 596491
|
||||
|
@ -108,6 +108,7 @@ skip-if = toolkit != "cocoa"
|
|||
[test_secondPlugin.html]
|
||||
[test_src_url_change.html]
|
||||
[test_streamNotify.html]
|
||||
skip-if = e10s
|
||||
[test_streamatclose.html]
|
||||
[test_twostreams.html]
|
||||
[test_windowed_invalidate.html]
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче