This commit is contained in:
Ryan VanderMeulen 2014-10-29 16:55:11 -04:00
Родитель 33002c3689 6de5c1cb7e
Коммит 3e2bf940ce
235 изменённых файлов: 8802 добавлений и 2284 удалений

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

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

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

@ -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]

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше