зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
7f5236111a
|
@ -15,9 +15,9 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
<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="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8a1ba73572c713e298ae53821d000fc3a5087b5f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
<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="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8a1ba73572c713e298ae53821d000fc3a5087b5f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "8e28588496f82f8f069c171c65842d622b9d8d7d",
|
||||
"git_revision": "2dd89fef4fae4d86fd313037ef384086c2e0e8a5",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "ff36a42838b338d750be214ac110c5cc4369b180",
|
||||
"revision": "9b4f4ec031e567ece9b707841fa50d27d346cd83",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8a1ba73572c713e298ae53821d000fc3a5087b5f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e28588496f82f8f069c171c65842d622b9d8d7d"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2dd89fef4fae4d86fd313037ef384086c2e0e8a5"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="42b56ff9f40a572e61b63a660daddc72a7a7ffcb"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
|
|
@ -142,15 +142,13 @@ skip-if = os != "win" || e10s # The Fitts Law back button is only supported on W
|
|||
skip-if = e10s # bug 967873 means permitUnload doesn't work in e10s mode
|
||||
[browser_blob-channelname.js]
|
||||
[browser_bookmark_titles.js]
|
||||
skip-if = buildapp == 'mulet' || toolkit == "windows" || e10s # Disabled on Windows due to frequent failures (bugs 825739, 841341) / e10s - Bug 1094205 - places doesn't return the right thing in e10s mode, for some reason
|
||||
skip-if = buildapp == 'mulet' || toolkit == "windows" # Disabled on Windows due to frequent failures (bugs 825739, 841341)
|
||||
[browser_bug304198.js]
|
||||
skip-if = e10s
|
||||
[browser_bug321000.js]
|
||||
skip-if = true # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
|
||||
[browser_bug329212.js]
|
||||
skip-if = e10s
|
||||
[browser_bug331772_xul_tooltiptext_in_html.js]
|
||||
skip-if = e10s
|
||||
[browser_bug356571.js]
|
||||
[browser_bug380960.js]
|
||||
[browser_bug386835.js]
|
||||
|
@ -159,7 +157,6 @@ skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
|
|||
[browser_bug406216.js]
|
||||
[browser_bug409481.js]
|
||||
[browser_bug409624.js]
|
||||
skip-if = e10s
|
||||
[browser_bug413915.js]
|
||||
[browser_bug416661.js]
|
||||
skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
|
||||
|
@ -181,7 +178,6 @@ skip-if = buildapp == 'mulet' || e10s # Bug 1099156 - test directly manipulates
|
|||
[browser_bug441778.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
|
||||
[browser_bug455852.js]
|
||||
skip-if = e10s
|
||||
[browser_bug460146.js]
|
||||
skip-if = e10s # Bug 866413 - PageInfo doesn't work in e10s
|
||||
[browser_bug462289.js]
|
||||
|
@ -192,7 +188,6 @@ skip-if = toolkit == "cocoa" || e10s # Bug 1102017 - middle-button mousedown on
|
|||
skip-if = buildapp == 'mulet'
|
||||
[browser_bug481560.js]
|
||||
[browser_bug484315.js]
|
||||
skip-if = e10s
|
||||
[browser_bug491431.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_bug495058.js]
|
||||
|
@ -216,7 +211,6 @@ skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory
|
|||
[browser_bug556061.js]
|
||||
[browser_bug559991.js]
|
||||
[browser_bug561623.js]
|
||||
skip-if = e10s
|
||||
[browser_bug561636.js]
|
||||
[browser_bug562649.js]
|
||||
[browser_bug563588.js]
|
||||
|
@ -237,7 +231,6 @@ skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
|
|||
[browser_bug581253.js]
|
||||
skip-if = e10s # Bug 1093756 - can't bookmark the data: url in e10s somehow
|
||||
[browser_bug581947.js]
|
||||
skip-if = e10s
|
||||
[browser_bug585558.js]
|
||||
[browser_bug585785.js]
|
||||
[browser_bug585830.js]
|
||||
|
@ -272,7 +265,6 @@ skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and
|
|||
[browser_bug735471.js]
|
||||
[browser_bug749738.js]
|
||||
[browser_bug763468_perwindowpb.js]
|
||||
skip-if = e10s
|
||||
[browser_bug767836_perwindowpb.js]
|
||||
[browser_bug771331.js]
|
||||
[browser_bug783614.js]
|
||||
|
@ -296,7 +288,6 @@ skip-if = os == 'win' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and
|
|||
[browser_canonizeURL.js]
|
||||
skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only
|
||||
[browser_contentAreaClick.js]
|
||||
skip-if = e10s
|
||||
[browser_contextSearchTabPosition.js]
|
||||
skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash
|
||||
[browser_ctrlTab.js]
|
||||
|
@ -316,7 +307,6 @@ skip-if = e10s
|
|||
[browser_drag.js]
|
||||
skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
|
||||
[browser_favicon_change.js]
|
||||
skip-if = e10s
|
||||
[browser_favicon_change_not_in_document.js]
|
||||
skip-if = e10s
|
||||
[browser_findbarClose.js]
|
||||
|
@ -368,7 +358,7 @@ skip-if = asan # Disabled because it takes a long time (see test for more inform
|
|||
[browser_plainTextLinks.js]
|
||||
skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
|
||||
[browser_popupUI.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1100707 - test fails in e10s because it can't get accel-w to close the popup (?)
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_popup_blocker.js]
|
||||
skip-if = e10s && debug # Frequent bug 1125520 failures
|
||||
[browser_printpreview.js]
|
||||
|
@ -383,7 +373,6 @@ support-files =
|
|||
test_remoteTroubleshoot.html
|
||||
[browser_removeTabsToTheEnd.js]
|
||||
[browser_removeUnsafeProtocolsFromURLBarPaste.js]
|
||||
skip-if = e10s
|
||||
[browser_restore_isAppTab.js]
|
||||
[browser_sanitize-passwordDisabledHosts.js]
|
||||
[browser_sanitize-sitepermissions.js]
|
||||
|
@ -457,7 +446,6 @@ skip-if = e10s # Bug 1093941 - used to cause obscure non-windows child process c
|
|||
[browser_urlbarEnterAfterMouseOver.js]
|
||||
skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
|
||||
[browser_urlbarRevert.js]
|
||||
skip-if = e10s # Bug 1093941 - ESC reverted the location bar value - Got foobar, expected example.com
|
||||
[browser_urlbarSearchSingleWordNotification.js]
|
||||
[browser_urlbarStop.js]
|
||||
[browser_urlbarTrimURLs.js]
|
||||
|
@ -483,9 +471,7 @@ skip-if = e10s # Bug 1094240 - has findbar-related failures
|
|||
skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHandler doesn't work in e10s
|
||||
[browser_no_mcb_on_http_site.js]
|
||||
[browser_bug1003461-switchtab-override.js]
|
||||
skip-if = e10s
|
||||
[browser_bug1024133-switchtab-override-keynav.js]
|
||||
skip-if = e10s
|
||||
[browser_bug1025195_switchToTabHavingURI_aOpenParams.js]
|
||||
[browser_addCertException.js]
|
||||
skip-if = e10s # Bug 1100687 - test directly manipulates content (content.document.getElementById)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
. $topsrcdir/build/macosx/mozconfig.common
|
||||
|
||||
ac_add_options --enable-signmar
|
||||
ac_add_options --with-google-oauth-api-keyfile=/builds/google-oauth-api.key
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then
|
||||
ac_add_options --with-macbundlename-prefix=Firefox
|
||||
fi
|
||||
|
||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||
ac_add_options --enable-warnings-as-errors
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
|
@ -79,6 +79,11 @@ private:
|
|||
virtual void run(const MatchFinder::MatchResult &Result);
|
||||
};
|
||||
|
||||
class RefCountedInsideLambdaChecker : public MatchFinder::MatchCallback {
|
||||
public:
|
||||
virtual void run(const MatchFinder::MatchResult &Result);
|
||||
};
|
||||
|
||||
ScopeChecker stackClassChecker;
|
||||
ScopeChecker globalClassChecker;
|
||||
NonHeapClassChecker nonheapClassChecker;
|
||||
|
@ -86,6 +91,7 @@ private:
|
|||
TrivialCtorDtorChecker trivialCtorDtorChecker;
|
||||
NaNExprChecker nanExprChecker;
|
||||
NoAddRefReleaseOnReturnChecker noAddRefReleaseOnReturnChecker;
|
||||
RefCountedInsideLambdaChecker refCountedInsideLambdaChecker;
|
||||
MatchFinder astMatcher;
|
||||
};
|
||||
|
||||
|
@ -354,6 +360,62 @@ ClassAllocationNature getClassAttrs(QualType T) {
|
|||
return clazz ? getClassAttrs(clazz) : RegularClass;
|
||||
}
|
||||
|
||||
/// A cached data of whether classes are refcounted or not.
|
||||
typedef DenseMap<const CXXRecordDecl *,
|
||||
std::pair<const Decl *, bool> > RefCountedMap;
|
||||
RefCountedMap refCountedClasses;
|
||||
|
||||
bool classHasAddRefRelease(const CXXRecordDecl *D) {
|
||||
const RefCountedMap::iterator& it = refCountedClasses.find(D);
|
||||
if (it != refCountedClasses.end()) {
|
||||
return it->second.second;
|
||||
}
|
||||
|
||||
bool seenAddRef = false;
|
||||
bool seenRelease = false;
|
||||
for (CXXRecordDecl::method_iterator method = D->method_begin();
|
||||
method != D->method_end(); ++method) {
|
||||
std::string name = method->getNameAsString();
|
||||
if (name == "AddRef") {
|
||||
seenAddRef = true;
|
||||
} else if (name == "Release") {
|
||||
seenRelease = true;
|
||||
}
|
||||
}
|
||||
refCountedClasses[D] = std::make_pair(D, seenAddRef && seenRelease);
|
||||
return seenAddRef && seenRelease;
|
||||
}
|
||||
|
||||
bool isClassRefCounted(QualType T);
|
||||
|
||||
bool isClassRefCounted(const CXXRecordDecl *D) {
|
||||
// Normalize so that D points to the definition if it exists.
|
||||
if (!D->hasDefinition())
|
||||
return false;
|
||||
D = D->getDefinition();
|
||||
// Base class: anyone with AddRef/Release is obviously a refcounted class.
|
||||
if (classHasAddRefRelease(D))
|
||||
return true;
|
||||
|
||||
// Look through all base cases to figure out if the parent is a refcounted class.
|
||||
for (CXXRecordDecl::base_class_const_iterator base = D->bases_begin();
|
||||
base != D->bases_end(); ++base) {
|
||||
bool super = isClassRefCounted(base->getType());
|
||||
if (super) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isClassRefCounted(QualType T) {
|
||||
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
|
||||
T = arrTy->getElementType();
|
||||
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
|
||||
return clazz ? isClassRefCounted(clazz) : RegularClass;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
@ -481,6 +543,11 @@ AST_MATCHER(MemberExpr, isAddRefOrRelease) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// This matcher will select classes which are refcounted.
|
||||
AST_MATCHER(QualType, isRefCounted) {
|
||||
return isClassRefCounted(Node);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,6 +644,11 @@ DiagnosticsMatcher::DiagnosticsMatcher()
|
|||
hasParent(callExpr())).bind("member")
|
||||
)).bind("node"),
|
||||
&noAddRefReleaseOnReturnChecker);
|
||||
|
||||
astMatcher.addMatcher(lambdaExpr(
|
||||
hasDescendant(declRefExpr(hasType(pointerType(pointee(isRefCounted())))).bind("node"))
|
||||
),
|
||||
&refCountedInsideLambdaChecker);
|
||||
}
|
||||
|
||||
void DiagnosticsMatcher::ScopeChecker::run(
|
||||
|
@ -775,6 +847,20 @@ void DiagnosticsMatcher::NoAddRefReleaseOnReturnChecker::run(
|
|||
Diag.Report(node->getLocStart(), errorID) << func << method;
|
||||
}
|
||||
|
||||
void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
|
||||
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Error, "Refcounted variable %0 of type %1 cannot be used inside a lambda");
|
||||
unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Note, "Please consider using a smart pointer");
|
||||
const DeclRefExpr *node = Result.Nodes.getNodeAs<DeclRefExpr>("node");
|
||||
|
||||
Diag.Report(node->getLocStart(), errorID) << node->getFoundDecl() <<
|
||||
node->getType()->getPointeeType();
|
||||
Diag.Report(node->getLocStart(), noteID);
|
||||
}
|
||||
|
||||
class MozCheckAction : public PluginASTAction {
|
||||
public:
|
||||
ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, StringRef fileName) override {
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
#define MOZ_STRONG_REF __attribute__((annotate("moz_strong_ref")))
|
||||
|
||||
struct RefCountedBase {
|
||||
void AddRef();
|
||||
void Release();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SmartPtr {
|
||||
T* MOZ_STRONG_REF t;
|
||||
T* operator->() const;
|
||||
};
|
||||
|
||||
struct R : RefCountedBase {
|
||||
void method();
|
||||
};
|
||||
|
||||
void take(...);
|
||||
void foo() {
|
||||
R* ptr;
|
||||
SmartPtr<R> sp;
|
||||
take([&]() {
|
||||
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be used inside a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
});
|
||||
take([&]() {
|
||||
sp->method();
|
||||
});
|
||||
take([&]() {
|
||||
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be used inside a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
});
|
||||
take([&]() {
|
||||
take(sp);
|
||||
});
|
||||
take([=]() {
|
||||
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be used inside a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
});
|
||||
take([=]() {
|
||||
sp->method();
|
||||
});
|
||||
take([=]() {
|
||||
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be used inside a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
});
|
||||
take([=]() {
|
||||
take(sp);
|
||||
});
|
||||
take([ptr]() {
|
||||
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be used inside a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
});
|
||||
take([sp]() {
|
||||
sp->method();
|
||||
});
|
||||
take([ptr]() {
|
||||
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be used inside a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
});
|
||||
take([sp]() {
|
||||
take(sp);
|
||||
});
|
||||
}
|
|
@ -14,6 +14,7 @@ SOURCES += [
|
|||
'TestNoAddRefReleaseOnReturn.cpp',
|
||||
'TestNoArithmeticExprInArgument.cpp',
|
||||
'TestNonHeapClass.cpp',
|
||||
'TestNoRefcountedInsideLambdas.cpp',
|
||||
'TestStackClass.cpp',
|
||||
'TestTrivialCtorDtor.cpp',
|
||||
]
|
||||
|
|
|
@ -23,7 +23,14 @@ make $make_flags || exit 1
|
|||
make install $make_flags DESTDIR=$root_dir || exit 1
|
||||
cd ..
|
||||
|
||||
case "$gcc_version" in
|
||||
*-*)
|
||||
wget -c -P $TMPDIR ftp://gcc.gnu.org/pub/gcc/snapshots/$gcc_version/gcc-$gcc_version.tar.bz2 || exit 1
|
||||
;;
|
||||
*)
|
||||
wget -c -P $TMPDIR ftp://ftp.gnu.org/gnu/gcc/gcc-$gcc_version/gcc-$gcc_version.tar.bz2 || exit 1
|
||||
;;
|
||||
esac
|
||||
tar xjf $TMPDIR/gcc-$gcc_version.tar.bz2
|
||||
cd gcc-$gcc_version
|
||||
|
||||
|
|
|
@ -163,5 +163,8 @@ endif
|
|||
ifdef MOZ_CRT
|
||||
mozglue/crt/target: mozglue/build/target
|
||||
endif
|
||||
|
||||
# js/src/target can end up invoking js/src/host rules (through object files
|
||||
# depending on jsautokw.h, which depends on host_jskwgen, and that can't
|
||||
# happen at the same time (bug #1146738)
|
||||
js/src/target: js/src/host
|
||||
endif
|
||||
|
|
|
@ -73,7 +73,7 @@ GNOMEUI_VERSION=2.2.0
|
|||
GCONF_VERSION=1.2.1
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.8.8.2
|
||||
SQLITE_VERSION=3.8.9
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
|
||||
|
@ -6948,12 +6948,15 @@ elif test "$GNU_CC"; then
|
|||
# -Wdeprecated-declarations - we don't want our builds held hostage when a
|
||||
# platform-specific API becomes deprecated.
|
||||
# -Wfree-nonheap-object - false positives during PGO
|
||||
# -Warray-bounds - false positives depending on optimization
|
||||
MOZ_C_SUPPORTS_WARNING(-W, no-error=uninitialized, ac_c_has_noerror_uninitialized)
|
||||
MOZ_CXX_SUPPORTS_WARNING(-W, no-error=uninitialized, ac_cxx_has_noerror_uninitialized)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, no-error=maybe-uninitialized, ac_c_has_noerror_maybe_uninitialized)
|
||||
MOZ_CXX_SUPPORTS_WARNING(-W, no-error=maybe-uninitialized, ac_cxx_has_noerror_maybe_uninitialized)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, no-error=deprecated-declarations, ac_c_has_noerror_deprecated_declarations)
|
||||
MOZ_CXX_SUPPORTS_WARNING(-W, no-error=deprecated-declarations, ac_cxx_has_noerror_deprecated_declarations)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, no-error=array-bounds, ac_c_has_noerror_array_bounds)
|
||||
MOZ_CXX_SUPPORTS_WARNING(-W, no-error=array-bounds, ac_cxx_has_noerror_array_bounds)
|
||||
|
||||
if test -n "$MOZ_PGO"; then
|
||||
MOZ_C_SUPPORTS_WARNING(-W, no-error=coverage-mismatch, ac_c_has_noerror_coverage_mismatch)
|
||||
|
|
|
@ -10,5 +10,4 @@ To move to a new version:
|
|||
|
||||
Copy the sqlite3.h and sqlite3.c files from the amalgamation of sqlite.
|
||||
|
||||
Be sure to update SQLITE_VERSION accordingly in $(topsrcdir)/configure.in as
|
||||
well as the version number at the top of this file.
|
||||
Be sure to update SQLITE_VERSION accordingly in $(topsrcdir)/configure.in.
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,24 +0,0 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/AnimationEffect.h"
|
||||
#include "mozilla/dom/AnimationEffectBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationEffect, mAnimation)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationEffect, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationEffect, Release)
|
||||
|
||||
JSObject*
|
||||
AnimationEffect::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return AnimationEffectBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,46 +0,0 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_AnimationEffect_h
|
||||
#define mozilla_dom_AnimationEffect_h
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AnimationEffect final : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit AnimationEffect(Animation* aAnimation)
|
||||
: mAnimation(aAnimation)
|
||||
{
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEffect)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationEffect)
|
||||
|
||||
Animation* GetParentObject() const { return mAnimation; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// AnimationEffect interface
|
||||
void GetName(nsString& aRetVal) const {
|
||||
aRetVal = mAnimation->Name();
|
||||
}
|
||||
|
||||
private:
|
||||
~AnimationEffect() { }
|
||||
|
||||
nsRefPtr<Animation> mAnimation;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AnimationEffect_h
|
|
@ -0,0 +1,23 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/AnimationEffectReadonly.h"
|
||||
#include "mozilla/dom/AnimationEffectReadonlyBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationEffectReadonly, mParent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationEffectReadonly)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationEffectReadonly)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationEffectReadonly)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,42 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_AnimationEffect_h
|
||||
#define mozilla_dom_AnimationEffect_h
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AnimationEffectReadonly
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
protected:
|
||||
virtual ~AnimationEffectReadonly() { }
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationEffectReadonly)
|
||||
|
||||
explicit AnimationEffectReadonly(nsISupports* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const { return mParent; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AnimationEffect_h
|
|
@ -18,7 +18,7 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationPlayer, mTimeline,
|
||||
mSource, mReady, mFinished)
|
||||
mEffect, mReady, mFinished)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationPlayer)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationPlayer)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationPlayer)
|
||||
|
@ -127,7 +127,7 @@ AnimationPlayer::SetCurrentTime(const TimeDuration& aSeekTime)
|
|||
}
|
||||
|
||||
UpdateFinishedState(true);
|
||||
UpdateSourceContent();
|
||||
UpdateEffect();
|
||||
PostUpdate();
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ AnimationPlayer::PlayState() const
|
|||
return AnimationPlayState::Paused;
|
||||
}
|
||||
|
||||
if ((mPlaybackRate > 0.0 && currentTime.Value() >= SourceContentEnd()) ||
|
||||
if ((mPlaybackRate > 0.0 && currentTime.Value() >= EffectEnd()) ||
|
||||
(mPlaybackRate < 0.0 && currentTime.Value().ToMilliseconds() <= 0.0)) {
|
||||
return AnimationPlayState::Finished;
|
||||
}
|
||||
|
@ -266,14 +266,14 @@ AnimationPlayer::SetCurrentTimeAsDouble(const Nullable<double>& aCurrentTime,
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SetSource(Animation* aSource)
|
||||
AnimationPlayer::SetEffect(KeyframeEffectReadonly* aEffect)
|
||||
{
|
||||
if (mSource) {
|
||||
mSource->SetParentTime(Nullable<TimeDuration>());
|
||||
if (mEffect) {
|
||||
mEffect->SetParentTime(Nullable<TimeDuration>());
|
||||
}
|
||||
mSource = aSource;
|
||||
if (mSource) {
|
||||
mSource->SetParentTime(GetCurrentTime());
|
||||
mEffect = aEffect;
|
||||
if (mEffect) {
|
||||
mEffect->SetParentTime(GetCurrentTime());
|
||||
}
|
||||
UpdateRelevance();
|
||||
}
|
||||
|
@ -367,14 +367,14 @@ AnimationPlayer::Cancel()
|
|||
mHoldTime.SetNull();
|
||||
mStartTime.SetNull();
|
||||
|
||||
UpdateSourceContent();
|
||||
UpdateEffect();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::UpdateRelevance()
|
||||
{
|
||||
bool wasRelevant = mIsRelevant;
|
||||
mIsRelevant = HasCurrentSource() || HasInEffectSource();
|
||||
mIsRelevant = HasCurrentEffect() || IsInEffect();
|
||||
|
||||
// Notify animation observers.
|
||||
if (wasRelevant && !mIsRelevant) {
|
||||
|
@ -387,9 +387,9 @@ AnimationPlayer::UpdateRelevance()
|
|||
bool
|
||||
AnimationPlayer::CanThrottle() const
|
||||
{
|
||||
if (!mSource ||
|
||||
mSource->IsFinishedTransition() ||
|
||||
mSource->Properties().IsEmpty()) {
|
||||
if (!mEffect ||
|
||||
mEffect->IsFinishedTransition() ||
|
||||
mEffect->Properties().IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -414,7 +414,7 @@ AnimationPlayer::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
|||
nsCSSPropertySet& aSetProperties,
|
||||
bool& aNeedsRefreshes)
|
||||
{
|
||||
if (!mSource || mSource->IsFinishedTransition()) {
|
||||
if (!mEffect || mEffect->IsFinishedTransition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -476,13 +476,13 @@ AnimationPlayer::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
|||
if (!timeToUse.IsNull()) {
|
||||
mHoldTime.SetValue((timeToUse.Value() - mStartTime.Value())
|
||||
.MultDouble(mPlaybackRate));
|
||||
// Push the change down to the source content
|
||||
UpdateSourceContent();
|
||||
// Push the change down to the effect
|
||||
UpdateEffect();
|
||||
updatedHoldTime = true;
|
||||
}
|
||||
}
|
||||
|
||||
mSource->ComposeStyle(aStyleRule, aSetProperties);
|
||||
mEffect->ComposeStyle(aStyleRule, aSetProperties);
|
||||
|
||||
if (updatedHoldTime) {
|
||||
UpdateTiming();
|
||||
|
@ -508,14 +508,14 @@ AnimationPlayer::DoPlay(LimitBehavior aLimitBehavior)
|
|||
(currentTime.IsNull() ||
|
||||
(aLimitBehavior == LimitBehavior::AutoRewind &&
|
||||
(currentTime.Value().ToMilliseconds() < 0.0 ||
|
||||
currentTime.Value() >= SourceContentEnd())))) {
|
||||
currentTime.Value() >= EffectEnd())))) {
|
||||
mHoldTime.SetValue(TimeDuration(0));
|
||||
} else if (mPlaybackRate < 0.0 &&
|
||||
(currentTime.IsNull() ||
|
||||
(aLimitBehavior == LimitBehavior::AutoRewind &&
|
||||
(currentTime.Value().ToMilliseconds() <= 0.0 ||
|
||||
currentTime.Value() > SourceContentEnd())))) {
|
||||
mHoldTime.SetValue(TimeDuration(SourceContentEnd()));
|
||||
currentTime.Value() > EffectEnd())))) {
|
||||
mHoldTime.SetValue(TimeDuration(EffectEnd()));
|
||||
} else if (mPlaybackRate == 0.0 && currentTime.IsNull()) {
|
||||
mHoldTime.SetValue(TimeDuration(0));
|
||||
}
|
||||
|
@ -647,30 +647,29 @@ AnimationPlayer::PauseAt(const TimeDuration& aReadyTime)
|
|||
void
|
||||
AnimationPlayer::UpdateTiming()
|
||||
{
|
||||
// We call UpdateFinishedState before UpdateSourceContent because the former
|
||||
// We call UpdateFinishedState before UpdateEffect because the former
|
||||
// can change the current time, which is used by the latter.
|
||||
UpdateFinishedState();
|
||||
UpdateSourceContent();
|
||||
UpdateEffect();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::UpdateFinishedState(bool aSeekFlag)
|
||||
{
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
||||
TimeDuration targetEffectEnd = TimeDuration(SourceContentEnd());
|
||||
TimeDuration effectEnd = TimeDuration(EffectEnd());
|
||||
|
||||
if (!mStartTime.IsNull() &&
|
||||
mPendingState == PendingState::NotPending) {
|
||||
if (mPlaybackRate > 0.0 &&
|
||||
!currentTime.IsNull() &&
|
||||
currentTime.Value() >= targetEffectEnd) {
|
||||
currentTime.Value() >= effectEnd) {
|
||||
if (aSeekFlag) {
|
||||
mHoldTime = currentTime;
|
||||
} else if (!mPreviousCurrentTime.IsNull()) {
|
||||
mHoldTime.SetValue(std::max(mPreviousCurrentTime.Value(),
|
||||
targetEffectEnd));
|
||||
mHoldTime.SetValue(std::max(mPreviousCurrentTime.Value(), effectEnd));
|
||||
} else {
|
||||
mHoldTime.SetValue(targetEffectEnd);
|
||||
mHoldTime.SetValue(effectEnd);
|
||||
}
|
||||
} else if (mPlaybackRate < 0.0 &&
|
||||
!currentTime.IsNull() &&
|
||||
|
@ -706,10 +705,10 @@ AnimationPlayer::UpdateFinishedState(bool aSeekFlag)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::UpdateSourceContent()
|
||||
AnimationPlayer::UpdateEffect()
|
||||
{
|
||||
if (mSource) {
|
||||
mSource->SetParentTime(GetCurrentTime());
|
||||
if (mEffect) {
|
||||
mEffect->SetParentTime(GetCurrentTime());
|
||||
UpdateRelevance();
|
||||
}
|
||||
}
|
||||
|
@ -764,7 +763,7 @@ AnimationPlayer::IsFinished() const
|
|||
// and we need this much more messy check to see if we're finished.
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
||||
return !currentTime.IsNull() &&
|
||||
((mPlaybackRate > 0.0 && currentTime.Value() >= SourceContentEnd()) ||
|
||||
((mPlaybackRate > 0.0 && currentTime.Value() >= EffectEnd()) ||
|
||||
(mPlaybackRate < 0.0 && currentTime.Value().ToMilliseconds() <= 0.0));
|
||||
}
|
||||
|
||||
|
@ -776,15 +775,15 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
|||
//
|
||||
// This covers the following cases:
|
||||
//
|
||||
// * We started playing but our source content's target element was orphaned
|
||||
// * We started playing but our effect's target element was orphaned
|
||||
// or bound to a different document.
|
||||
// (note that for the case of our source content changing we should handle
|
||||
// that in SetSource)
|
||||
// (note that for the case of our effect changing we should handle
|
||||
// that in SetEffect)
|
||||
// * We started playing but our timeline became inactive.
|
||||
// In this case the pending player tracker will drop us from its hashmap
|
||||
// when we have been painted.
|
||||
// * When we started playing we couldn't find a PendingPlayerTracker to
|
||||
// register with (perhaps the source content had no document) so we simply
|
||||
// register with (perhaps the effect had no document) so we simply
|
||||
// set mPendingState in DoPlay and relied on this method to catch us on the
|
||||
// next tick.
|
||||
|
||||
|
@ -823,26 +822,26 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
|||
}
|
||||
|
||||
StickyTimeDuration
|
||||
AnimationPlayer::SourceContentEnd() const
|
||||
AnimationPlayer::EffectEnd() const
|
||||
{
|
||||
if (!mSource) {
|
||||
if (!mEffect) {
|
||||
return StickyTimeDuration(0);
|
||||
}
|
||||
|
||||
return mSource->Timing().mDelay
|
||||
+ mSource->GetComputedTiming().mActiveDuration;
|
||||
return mEffect->Timing().mDelay
|
||||
+ mEffect->GetComputedTiming().mActiveDuration;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
AnimationPlayer::GetRenderedDocument() const
|
||||
{
|
||||
if (!mSource) {
|
||||
if (!mEffect) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
mSource->GetTarget(targetElement, pseudoType);
|
||||
mEffect->GetTarget(targetElement, pseudoType);
|
||||
if (!targetElement) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -871,11 +870,11 @@ AnimationPlayer::GetCollection() const
|
|||
if (!manager) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(mSource, "A player with an animation manager must have a source");
|
||||
MOZ_ASSERT(mEffect, "A player with an animation manager must have an effect");
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type targetPseudoType;
|
||||
mSource->GetTarget(targetElement, targetPseudoType);
|
||||
mEffect->GetTarget(targetElement, targetPseudoType);
|
||||
MOZ_ASSERT(targetElement,
|
||||
"A player with an animation manager must have a target");
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
|
||||
#include "mozilla/dom/Animation.h" // for Animation
|
||||
#include "mozilla/dom/AnimationPlayerBinding.h" // for AnimationPlayState
|
||||
#include "mozilla/dom/DocumentTimeline.h" // for DocumentTimeline
|
||||
#include "mozilla/dom/KeyframeEffect.h" // for KeyframeEffectReadonly
|
||||
#include "mozilla/dom/Promise.h" // for Promise
|
||||
#include "nsCSSProperty.h" // for nsCSSProperty
|
||||
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
};
|
||||
|
||||
// AnimationPlayer methods
|
||||
Animation* GetSource() const { return mSource; }
|
||||
KeyframeEffectReadonly* GetEffect() const { return mEffect; }
|
||||
DocumentTimeline* Timeline() const { return mTimeline; }
|
||||
Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
|
||||
void SetStartTime(const Nullable<TimeDuration>& aNewStartTime);
|
||||
|
@ -113,14 +113,14 @@ public:
|
|||
// CSSAnimationPlayer::PauseFromJS so we leave it for now.
|
||||
void PauseFromJS() { Pause(); }
|
||||
|
||||
void SetSource(Animation* aSource);
|
||||
void SetEffect(KeyframeEffectReadonly* aEffect);
|
||||
void Tick();
|
||||
|
||||
/**
|
||||
* Set the time to use for starting or pausing a pending player.
|
||||
*
|
||||
* Typically, when a player is played, it does not start immediately but is
|
||||
* added to a table of pending players on the document of its source content.
|
||||
* added to a table of pending players on the document of its effect.
|
||||
* In the meantime it sets its hold time to the time from which playback
|
||||
* should begin.
|
||||
*
|
||||
|
@ -203,7 +203,7 @@ public:
|
|||
|
||||
const nsString& Name() const
|
||||
{
|
||||
return mSource ? mSource->Name() : EmptyString();
|
||||
return mEffect ? mEffect->Name() : EmptyString();
|
||||
}
|
||||
|
||||
bool IsPausedOrPausing() const
|
||||
|
@ -212,17 +212,17 @@ public:
|
|||
mPendingState == PendingState::PausePending;
|
||||
}
|
||||
|
||||
bool HasInPlaySource() const
|
||||
bool HasInPlayEffect() const
|
||||
{
|
||||
return GetSource() && GetSource()->IsInPlay(*this);
|
||||
return GetEffect() && GetEffect()->IsInPlay(*this);
|
||||
}
|
||||
bool HasCurrentSource() const
|
||||
bool HasCurrentEffect() const
|
||||
{
|
||||
return GetSource() && GetSource()->IsCurrent(*this);
|
||||
return GetEffect() && GetEffect()->IsCurrent(*this);
|
||||
}
|
||||
bool HasInEffectSource() const
|
||||
bool IsInEffect() const
|
||||
{
|
||||
return GetSource() && GetSource()->IsInEffect();
|
||||
return GetEffect() && GetEffect()->IsInEffect();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,9 +235,9 @@ public:
|
|||
*/
|
||||
bool IsPlaying() const
|
||||
{
|
||||
// We need to have a source animation in its active interval, and
|
||||
// We need to have an effect in its active interval, and
|
||||
// be either running or waiting to run.
|
||||
return HasInPlaySource() &&
|
||||
return HasInPlayEffect() &&
|
||||
(PlayState() == AnimationPlayState::Running ||
|
||||
mPendingState == PendingState::PlayPending);
|
||||
}
|
||||
|
@ -253,13 +253,13 @@ public:
|
|||
// running on the compositor).
|
||||
bool CanThrottle() const;
|
||||
|
||||
// Updates |aStyleRule| with the animation values of this player's source
|
||||
// content, if any.
|
||||
// Updates |aStyleRule| with the animation values of this player's effect,
|
||||
// if any.
|
||||
// Any properties already contained in |aSetProperties| are not changed. Any
|
||||
// properties that are changed are added to |aSetProperties|.
|
||||
// |aNeedsRefreshes| will be set to true if this player expects to update
|
||||
// the style rule on the next refresh driver tick as well (because it
|
||||
// is running and has source content to sample).
|
||||
// is running and has an effect to sample).
|
||||
void ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties,
|
||||
bool& aNeedsRefreshes);
|
||||
|
@ -282,7 +282,7 @@ protected:
|
|||
|
||||
void UpdateTiming();
|
||||
void UpdateFinishedState(bool aSeekFlag = false);
|
||||
void UpdateSourceContent();
|
||||
void UpdateEffect();
|
||||
void FlushStyle() const;
|
||||
void PostUpdate();
|
||||
/**
|
||||
|
@ -295,7 +295,7 @@ protected:
|
|||
bool IsFinished() const;
|
||||
|
||||
bool IsPossiblyOrphanedPendingPlayer() const;
|
||||
StickyTimeDuration SourceContentEnd() const;
|
||||
StickyTimeDuration EffectEnd() const;
|
||||
|
||||
nsIDocument* GetRenderedDocument() const;
|
||||
nsPresContext* GetPresContext() const;
|
||||
|
@ -303,7 +303,7 @@ protected:
|
|||
AnimationPlayerCollection* GetCollection() const;
|
||||
|
||||
nsRefPtr<DocumentTimeline> mTimeline;
|
||||
nsRefPtr<Animation> mSource;
|
||||
nsRefPtr<KeyframeEffectReadonly> mEffect;
|
||||
// The beginning of the delay period.
|
||||
Nullable<TimeDuration> mStartTime; // Timeline timescale
|
||||
Nullable<TimeDuration> mHoldTime; // Player timescale
|
||||
|
@ -317,7 +317,7 @@ protected:
|
|||
// See http://w3c.github.io/web-animations/#current-ready-promise
|
||||
nsRefPtr<Promise> mReady;
|
||||
|
||||
// A Promise that is resolved when we reach the end of the source content, or
|
||||
// A Promise that is resolved when we reach the end of the effect, or
|
||||
// 0 when playing backwards. The Promise is replaced if the animation is
|
||||
// finished but then a state change makes it not finished.
|
||||
// This object is lazily created by GetFinished.
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
* 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/. */
|
||||
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/AnimationBinding.h"
|
||||
#include "mozilla/dom/AnimationEffect.h"
|
||||
#include "mozilla/dom/KeyframeEffect.h"
|
||||
#include "mozilla/dom/KeyframeEffectBinding.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "AnimationCommon.h"
|
||||
#include "nsCSSPropertySet.h"
|
||||
|
@ -60,33 +59,37 @@ const double ComputedTiming::kNullTimeFraction = PositiveInfinity<double>();
|
|||
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Animation, mDocument, mTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(KeyframeEffectReadonly,
|
||||
AnimationEffectReadonly,
|
||||
mTarget)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Animation, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Animation, Release)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(KeyframeEffectReadonly,
|
||||
AnimationEffectReadonly)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(KeyframeEffectReadonly)
|
||||
NS_INTERFACE_MAP_END_INHERITING(AnimationEffectReadonly)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(KeyframeEffectReadonly, AnimationEffectReadonly)
|
||||
NS_IMPL_RELEASE_INHERITED(KeyframeEffectReadonly, AnimationEffectReadonly)
|
||||
|
||||
JSObject*
|
||||
Animation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
KeyframeEffectReadonly::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return AnimationBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
already_AddRefed<AnimationEffect>
|
||||
Animation::GetEffect()
|
||||
{
|
||||
nsRefPtr<AnimationEffect> effect = new AnimationEffect(this);
|
||||
return effect.forget();
|
||||
return KeyframeEffectReadonlyBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
Animation::SetParentTime(Nullable<TimeDuration> aParentTime)
|
||||
KeyframeEffectReadonly::SetParentTime(Nullable<TimeDuration> aParentTime)
|
||||
{
|
||||
mParentTime = aParentTime;
|
||||
}
|
||||
|
||||
ComputedTiming
|
||||
Animation::GetComputedTimingAt(const Nullable<TimeDuration>& aLocalTime,
|
||||
const AnimationTiming& aTiming)
|
||||
KeyframeEffectReadonly::GetComputedTimingAt(
|
||||
const Nullable<TimeDuration>& aLocalTime,
|
||||
const AnimationTiming& aTiming)
|
||||
{
|
||||
const TimeDuration zeroDuration;
|
||||
|
||||
|
@ -214,7 +217,7 @@ Animation::GetComputedTimingAt(const Nullable<TimeDuration>& aLocalTime,
|
|||
}
|
||||
|
||||
StickyTimeDuration
|
||||
Animation::ActiveDuration(const AnimationTiming& aTiming)
|
||||
KeyframeEffectReadonly::ActiveDuration(const AnimationTiming& aTiming)
|
||||
{
|
||||
if (aTiming.mIterationCount == mozilla::PositiveInfinity<float>()) {
|
||||
// An animation that repeats forever has an infinite active duration
|
||||
|
@ -231,7 +234,7 @@ Animation::ActiveDuration(const AnimationTiming& aTiming)
|
|||
|
||||
// http://w3c.github.io/web-animations/#in-play
|
||||
bool
|
||||
Animation::IsInPlay(const AnimationPlayer& aPlayer) const
|
||||
KeyframeEffectReadonly::IsInPlay(const AnimationPlayer& aPlayer) const
|
||||
{
|
||||
if (IsFinishedTransition() ||
|
||||
aPlayer.PlayState() == AnimationPlayState::Finished) {
|
||||
|
@ -243,7 +246,7 @@ Animation::IsInPlay(const AnimationPlayer& aPlayer) const
|
|||
|
||||
// http://w3c.github.io/web-animations/#current
|
||||
bool
|
||||
Animation::IsCurrent(const AnimationPlayer& aPlayer) const
|
||||
KeyframeEffectReadonly::IsCurrent(const AnimationPlayer& aPlayer) const
|
||||
{
|
||||
if (IsFinishedTransition() ||
|
||||
aPlayer.PlayState() == AnimationPlayState::Finished) {
|
||||
|
@ -256,7 +259,7 @@ Animation::IsCurrent(const AnimationPlayer& aPlayer) const
|
|||
}
|
||||
|
||||
bool
|
||||
Animation::IsInEffect() const
|
||||
KeyframeEffectReadonly::IsInEffect() const
|
||||
{
|
||||
if (IsFinishedTransition()) {
|
||||
return false;
|
||||
|
@ -267,7 +270,7 @@ Animation::IsInEffect() const
|
|||
}
|
||||
|
||||
const AnimationProperty*
|
||||
Animation::GetAnimationOfProperty(nsCSSProperty aProperty) const
|
||||
KeyframeEffectReadonly::GetAnimationOfProperty(nsCSSProperty aProperty) const
|
||||
{
|
||||
for (size_t propIdx = 0, propEnd = mProperties.Length();
|
||||
propIdx != propEnd; ++propIdx) {
|
||||
|
@ -283,8 +286,9 @@ Animation::GetAnimationOfProperty(nsCSSProperty aProperty) const
|
|||
}
|
||||
|
||||
bool
|
||||
Animation::HasAnimationOfProperties(const nsCSSProperty* aProperties,
|
||||
size_t aPropertyCount) const
|
||||
KeyframeEffectReadonly::HasAnimationOfProperties(
|
||||
const nsCSSProperty* aProperties,
|
||||
size_t aPropertyCount) const
|
||||
{
|
||||
for (size_t i = 0; i < aPropertyCount; i++) {
|
||||
if (HasAnimationOfProperty(aProperties[i])) {
|
||||
|
@ -295,8 +299,9 @@ Animation::HasAnimationOfProperties(const nsCSSProperty* aProperties,
|
|||
}
|
||||
|
||||
void
|
||||
Animation::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties)
|
||||
KeyframeEffectReadonly::ComposeStyle(
|
||||
nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties)
|
||||
{
|
||||
ComputedTiming computedTiming = GetComputedTiming();
|
||||
|
|
@ -3,8 +3,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_Animation_h
|
||||
#define mozilla_dom_Animation_h
|
||||
#ifndef mozilla_dom_KeyframeEffect_h
|
||||
#define mozilla_dom_KeyframeEffect_h
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/StickyTimeDuration.h"
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/AnimationEffectReadonly.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "nsSMILKeySpline.h"
|
||||
|
@ -117,8 +118,8 @@ public:
|
|||
bool operator==(const ComputedTimingFunction& aOther) const {
|
||||
return mType == aOther.mType &&
|
||||
(mType == nsTimingFunction::Function ?
|
||||
mTimingFunction == aOther.mTimingFunction :
|
||||
mSteps == aOther.mSteps);
|
||||
mTimingFunction == aOther.mTimingFunction :
|
||||
mSteps == aOther.mSteps);
|
||||
}
|
||||
bool operator!=(const ComputedTimingFunction& aOther) const {
|
||||
return !(*this == aOther);
|
||||
|
@ -184,17 +185,15 @@ struct ElementPropertyTransition;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class AnimationEffect;
|
||||
|
||||
class Animation : public nsWrapperCache
|
||||
class KeyframeEffectReadonly : public AnimationEffectReadonly
|
||||
{
|
||||
public:
|
||||
Animation(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
const AnimationTiming &aTiming,
|
||||
const nsSubstring& aName)
|
||||
: mDocument(aDocument)
|
||||
KeyframeEffectReadonly(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
const AnimationTiming &aTiming,
|
||||
const nsSubstring& aName)
|
||||
: AnimationEffectReadonly(aDocument)
|
||||
, mTarget(aTarget)
|
||||
, mTiming(aTiming)
|
||||
, mName(aName)
|
||||
|
@ -204,33 +203,32 @@ public:
|
|||
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Animation)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Animation)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffectReadonly,
|
||||
AnimationEffectReadonly)
|
||||
|
||||
nsIDocument* GetParentObject() const { return mDocument; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// FIXME: If we succeed in moving transition-specific code to a type of
|
||||
// AnimationEffect (as per the Web Animations API) we should remove these
|
||||
// virtual methods.
|
||||
virtual ElementPropertyTransition* AsTransition() { return nullptr; }
|
||||
virtual const ElementPropertyTransition* AsTransition() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Animation interface
|
||||
// This currently returns a new object each time when used from C++ but is
|
||||
// cached when used from JS.
|
||||
already_AddRefed<AnimationEffect> GetEffect();
|
||||
// KeyframeEffectReadonly interface
|
||||
Element* GetTarget() const {
|
||||
// Currently we only implement Element.getAnimations() which only
|
||||
// returns animations targetting Elements so this should never
|
||||
// be called for an animation that targets a pseudo-element.
|
||||
MOZ_ASSERT(mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
"Requesting the target of an Animation that targets a"
|
||||
"Requesting the target of a KeyframeEffect that targets a"
|
||||
" pseudo-element is not yet supported.");
|
||||
return mTarget;
|
||||
}
|
||||
void GetName(nsString& aRetVal) const
|
||||
{
|
||||
aRetVal = Name();
|
||||
}
|
||||
|
||||
// Temporary workaround to return both the target element and pseudo-type
|
||||
// until we implement PseudoElement.
|
||||
|
@ -239,6 +237,12 @@ public:
|
|||
aTarget = mTarget;
|
||||
aPseudoType = mPseudoType;
|
||||
}
|
||||
// Alternative to GetName that returns a reference to the member for
|
||||
// more efficient internal usage.
|
||||
virtual const nsString& Name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
void SetParentTime(Nullable<TimeDuration> aParentTime);
|
||||
|
||||
|
@ -249,10 +253,6 @@ public:
|
|||
return mTiming;
|
||||
}
|
||||
|
||||
virtual const nsString& Name() const {
|
||||
return mName;
|
||||
}
|
||||
|
||||
// Return the duration from the start the active interval to the point where
|
||||
// the animation begins playback. This is zero unless the animation has
|
||||
// a negative delay in which case it is the absolute value of the delay.
|
||||
|
@ -332,11 +332,8 @@ public:
|
|||
nsCSSPropertySet& aSetProperties);
|
||||
|
||||
protected:
|
||||
virtual ~Animation() { }
|
||||
virtual ~KeyframeEffectReadonly() { }
|
||||
|
||||
// We use a document for a parent object since the other likely candidate,
|
||||
// the target element, can be empty.
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<Element> mTarget;
|
||||
Nullable<TimeDuration> mParentTime;
|
||||
|
||||
|
@ -353,4 +350,4 @@ protected:
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_Animation_h
|
||||
#endif // mozilla_dom_KeyframeEffect_h
|
|
@ -8,11 +8,11 @@ MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
|||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Animation.h',
|
||||
'AnimationEffect.h',
|
||||
'AnimationEffectReadonly.h',
|
||||
'AnimationPlayer.h',
|
||||
'AnimationTimeline.h',
|
||||
'DocumentTimeline.h',
|
||||
'KeyframeEffect.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
|
@ -21,11 +21,11 @@ EXPORTS.mozilla += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Animation.cpp',
|
||||
'AnimationEffect.cpp',
|
||||
'AnimationEffectReadonly.cpp',
|
||||
'AnimationPlayer.cpp',
|
||||
'AnimationTimeline.cpp',
|
||||
'DocumentTimeline.cpp',
|
||||
'KeyframeEffect.cpp',
|
||||
'PendingPlayerTracker.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -208,11 +208,11 @@ function checkStateOnSettingCurrentTimeToZero(animation)
|
|||
'Animation.playState should be "running" at the start of ' +
|
||||
'the start delay');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, 'running',
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, 'running',
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"running" at the start of the start delay');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, UNANIMATED_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
@ -233,11 +233,11 @@ function checkStateOnReadyPromiseResolved(animation)
|
|||
'Animation.playState should be "running" on the first paint ' +
|
||||
'tick after animation creation');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, 'running',
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, 'running',
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"running" on the first paint tick after animation creation');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, UNANIMATED_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
@ -253,11 +253,11 @@ function checkStateAtActiveIntervalStartTime(animation)
|
|||
'Animation.playState should be "running" at the start of ' +
|
||||
'the active interval');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, 'running',
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, 'running',
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"running" at the start of the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
|
||||
'the computed value of margin-left should be close to the value at the ' +
|
||||
|
@ -268,7 +268,7 @@ function checkStateAtFiftyPctOfActiveInterval(animation)
|
|||
{
|
||||
// We don't test animation.currentTime since our caller just set it.
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, FIFTY_PCT_POSITION,
|
||||
'the computed value of margin-left should be half way through the ' +
|
||||
|
@ -284,11 +284,11 @@ function checkStateAtActiveIntervalEndTime(animation)
|
|||
'Animation.playState should be "finished" at the end of ' +
|
||||
'the active interval');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, "running",
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, "running",
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"finished" at the end of the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, UNANIMATED_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
@ -314,8 +314,8 @@ test(function(t)
|
|||
'Animation.playState should be "pending" when an animation ' +
|
||||
'is initially created');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, 'running',
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, 'running',
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"running" when an animation is initially created');
|
||||
|
||||
// XXX Ideally we would have a test to check the ready Promise is initially
|
||||
|
|
|
@ -210,11 +210,11 @@ function checkStateOnReadyPromiseResolved(animation)
|
|||
'Animation.playState should be "running" on the first paint ' +
|
||||
'tick after animation creation');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, 'running',
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, 'running',
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"running" on the first paint tick after animation creation');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, UNANIMATED_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
@ -230,11 +230,11 @@ function checkStateAtActiveIntervalStartTime(animation)
|
|||
'Animation.playState should be "running" at the start of ' +
|
||||
'the active interval');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, 'running',
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, 'running',
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"running" at the start of the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
|
||||
'the computed value of margin-left should be close to the value at the ' +
|
||||
|
@ -245,7 +245,7 @@ function checkStateAtFiftyPctOfActiveInterval(animation)
|
|||
{
|
||||
// We don't test animation.startTime since our caller just set it.
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, FIFTY_PCT_POSITION,
|
||||
'the computed value of margin-left should be half way through the ' +
|
||||
|
@ -261,11 +261,11 @@ function checkStateAtActiveIntervalEndTime(animation)
|
|||
'Animation.playState should be "finished" at the end of ' +
|
||||
'the active interval');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, "running",
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, "running",
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"finished" at the end of the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, UNANIMATED_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
|
|
@ -15,22 +15,22 @@
|
|||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = 'xyz 100s';
|
||||
assert_equals(div.getAnimations()[0].source.effect.name, 'xyz',
|
||||
assert_equals(div.getAnimations()[0].effect.name, 'xyz',
|
||||
'Animation effect name matches keyframes rule name');
|
||||
}, 'Effect name makes keyframe rule');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = 'x\\yz 100s';
|
||||
assert_equals(div.getAnimations()[0].source.effect.name, 'xyz',
|
||||
assert_equals(div.getAnimations()[0].effect.name, 'xyz',
|
||||
'Escaped animation effect name matches keyframes rule name');
|
||||
}, 'Escaped animation name');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = 'x\\79 z 100s';
|
||||
assert_equals(div.getAnimations()[0].source.effect.name, 'xyz',
|
||||
'Hex-escaped animation effect name matches keyframes rule'
|
||||
assert_equals(div.getAnimations()[0].effect.name, 'xyz',
|
||||
'Hex-escaped animation name matches keyframes rule'
|
||||
+ ' name');
|
||||
}, 'Animation name with hex-escape');
|
||||
|
|
@ -14,7 +14,7 @@ test(function(t) {
|
|||
var div = addDiv(t);
|
||||
div.style.animation = 'anim 100s';
|
||||
var animation = div.getAnimations()[0];
|
||||
assert_equals(animation.source.target, div,
|
||||
assert_equals(animation.effect.target, div,
|
||||
'Animation.target is the animatable div');
|
||||
}, 'Returned CSS animations have the correct Animation.target');
|
||||
|
|
@ -243,7 +243,7 @@ test(function(t) {
|
|||
// Update duration (an Animation change)
|
||||
div.style.animationDuration = '200s';
|
||||
var extendedAnimation = div.getAnimations()[0];
|
||||
// FIXME: Check extendedAnimation.source.timing.duration has changed once the
|
||||
// FIXME: Check extendedAnimation.effect.timing.duration has changed once the
|
||||
// API is available
|
||||
assert_equals(originalAnimation, extendedAnimation,
|
||||
'getAnimations returns the same objects even when their'
|
||||
|
|
|
@ -194,11 +194,11 @@ function checkStateOnSettingCurrentTimeToZero(animation)
|
|||
'Animation.playState should be "running" at the start of ' +
|
||||
'the start delay');
|
||||
|
||||
assert_equals(animation.source.target.style.animationPlayState, 'running',
|
||||
'Animation.source.target.style.animationPlayState should be ' +
|
||||
assert_equals(animation.effect.target.style.animationPlayState, 'running',
|
||||
'Animation.effect.target.style.animationPlayState should be ' +
|
||||
'"running" at the start of the start delay');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, UNANIMATED_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
@ -219,7 +219,7 @@ function checkStateOnReadyPromiseResolved(animation)
|
|||
'Animation.playState should be "running" on the first paint ' +
|
||||
'tick after animation creation');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, INITIAL_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
@ -235,7 +235,7 @@ function checkStateAtActiveIntervalStartTime(animation)
|
|||
'Animation.playState should be "running" at the start of ' +
|
||||
'the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
|
||||
'the computed value of margin-left should be close to the value at the ' +
|
||||
|
@ -246,7 +246,7 @@ function checkStateAtFiftyPctOfActiveInterval(animation)
|
|||
{
|
||||
// We don't test animation.currentTime since our caller just set it.
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, FIFTY_PCT_POSITION,
|
||||
'the computed value of margin-left should be half way through the ' +
|
||||
|
@ -262,7 +262,7 @@ function checkStateAtActiveIntervalEndTime(animation)
|
|||
'Animation.playState should be "finished" at the end of ' +
|
||||
'the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, END_POSITION,
|
||||
'the computed value of margin-left should be the final transitioned-to ' +
|
||||
|
|
|
@ -200,7 +200,7 @@ function checkStateOnReadyPromiseResolved(animation)
|
|||
'Animation.playState should be "running" on the first paint ' +
|
||||
'tick after animation creation');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, INITIAL_POSITION,
|
||||
'the computed value of margin-left should be unaffected ' +
|
||||
|
@ -216,7 +216,7 @@ function checkStateAtActiveIntervalStartTime(animation)
|
|||
'Animation.playState should be "running" at the start of ' +
|
||||
'the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
|
||||
'the computed value of margin-left should be close to the value at the ' +
|
||||
|
@ -227,7 +227,7 @@ function checkStateAtFiftyPctOfActiveInterval(animation)
|
|||
{
|
||||
// We don't test animation.startTime since our caller just set it.
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, FIFTY_PCT_POSITION,
|
||||
'the computed value of margin-left should be half way through the ' +
|
||||
|
@ -243,7 +243,7 @@ function checkStateAtActiveIntervalEndTime(animation)
|
|||
'Animation.playState should be "finished" at the end of ' +
|
||||
'the active interval');
|
||||
|
||||
var div = animation.source.target;
|
||||
var div = animation.effect.target;
|
||||
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, END_POSITION,
|
||||
'the computed value of margin-left should be the final transitioned-to ' +
|
||||
|
|
|
@ -16,7 +16,7 @@ test(function(t) {
|
|||
div.style.transition = 'all 100s';
|
||||
div.style.left = '100px';
|
||||
|
||||
assert_equals(div.getAnimations()[0].source.effect.name, 'left',
|
||||
assert_equals(div.getAnimations()[0].effect.name, 'left',
|
||||
'The name for the transitions corresponds to the property ' +
|
||||
'being transitioned');
|
||||
}, 'Effect name for transitions');
|
|
@ -16,7 +16,7 @@ test(function(t) {
|
|||
div.style.left = '100px';
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
assert_equals(animation.source.target, div,
|
||||
assert_equals(animation.effect.target, div,
|
||||
'Animation.target is the animatable div');
|
||||
}, 'Returned CSS transitions have the correct Animation.target');
|
||||
|
|
@ -3,22 +3,22 @@ support-files =
|
|||
testcommon.js
|
||||
|
||||
[css-animations/test_animations-dynamic-changes.html]
|
||||
[css-animations/test_animation-effect-name.html]
|
||||
[css-animations/test_animation-pausing.html]
|
||||
[css-animations/test_animation-player-currenttime.html]
|
||||
[css-animations/test_animation-player-finished.html]
|
||||
[css-animations/test_animation-player-playstate.html]
|
||||
[css-animations/test_animation-player-ready.html]
|
||||
[css-animations/test_animation-player-starttime.html]
|
||||
[css-animations/test_animation-target.html]
|
||||
[css-animations/test_effect-name.html]
|
||||
[css-animations/test_effect-target.html]
|
||||
[css-animations/test_element-get-animation-players.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[css-transitions/test_animation-effect-name.html]
|
||||
[css-transitions/test_animation-pausing.html]
|
||||
[css-transitions/test_animation-player-currenttime.html]
|
||||
[css-transitions/test_animation-player-ready.html]
|
||||
[css-transitions/test_animation-target.html]
|
||||
[css-transitions/test_animation-player-starttime.html]
|
||||
[css-transitions/test_effect-name.html]
|
||||
[css-transitions/test_effect-target.html]
|
||||
[css-transitions/test_element-get-animation-players.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[document-timeline/test_document-timeline.html]
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SameProcessMessageQueue.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
SameProcessMessageQueue* SameProcessMessageQueue::sSingleton;
|
||||
|
||||
SameProcessMessageQueue::SameProcessMessageQueue()
|
||||
{
|
||||
}
|
||||
|
||||
SameProcessMessageQueue::~SameProcessMessageQueue()
|
||||
{
|
||||
// This code should run during shutdown, and we should already have pumped the
|
||||
// event loop. So we should only see messages here if someone is sending
|
||||
// messages pretty late in shutdown.
|
||||
NS_WARN_IF_FALSE(mQueue.IsEmpty(), "Shouldn't send messages during shutdown");
|
||||
sSingleton = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SameProcessMessageQueue::Push(Runnable* aRunnable)
|
||||
{
|
||||
mQueue.AppendElement(aRunnable);
|
||||
NS_DispatchToCurrentThread(aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
SameProcessMessageQueue::Flush()
|
||||
{
|
||||
nsTArray<nsRefPtr<Runnable>> queue;
|
||||
mQueue.SwapElements(queue);
|
||||
for (size_t i = 0; i < queue.Length(); i++) {
|
||||
queue[i]->Run();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ SameProcessMessageQueue*
|
||||
SameProcessMessageQueue::Get()
|
||||
{
|
||||
if (!sSingleton) {
|
||||
sSingleton = new SameProcessMessageQueue();
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
SameProcessMessageQueue::Runnable::Runnable()
|
||||
: mDispatched(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(SameProcessMessageQueue::Runnable, nsIRunnable)
|
||||
|
||||
nsresult
|
||||
SameProcessMessageQueue::Runnable::Run()
|
||||
{
|
||||
if (mDispatched) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
|
||||
queue->mQueue.RemoveElement(this);
|
||||
|
||||
mDispatched = true;
|
||||
return HandleMessage();
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_SameProcessMessageQueue_h
|
||||
#define mozilla_dom_SameProcessMessageQueue_h
|
||||
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class CancelableRunnable;
|
||||
|
||||
class SameProcessMessageQueue
|
||||
{
|
||||
public:
|
||||
SameProcessMessageQueue();
|
||||
virtual ~SameProcessMessageQueue();
|
||||
|
||||
class Runnable : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
explicit Runnable();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
virtual nsresult HandleMessage() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Runnable() {}
|
||||
|
||||
private:
|
||||
bool mDispatched;
|
||||
};
|
||||
|
||||
void Push(Runnable* aRunnable);
|
||||
void Flush();
|
||||
|
||||
static SameProcessMessageQueue* Get();
|
||||
|
||||
private:
|
||||
friend class CancelableRunnable;
|
||||
|
||||
nsTArray<nsRefPtr<Runnable>> mQueue;
|
||||
static SameProcessMessageQueue* sSingleton;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_SameProcessMessageQueue_h
|
|
@ -191,6 +191,7 @@ EXPORTS.mozilla.dom += [
|
|||
'PerformanceResourceTiming.h',
|
||||
'ProcessGlobal.h',
|
||||
'ResponsiveImageSelector.h',
|
||||
'SameProcessMessageQueue.h',
|
||||
'ScreenOrientation.h',
|
||||
'ScriptSettings.h',
|
||||
'ShadowRoot.h',
|
||||
|
@ -328,6 +329,7 @@ UNIFIED_SOURCES += [
|
|||
'PerformanceResourceTiming.cpp',
|
||||
'ProcessGlobal.cpp',
|
||||
'ResponsiveImageSelector.cpp',
|
||||
'SameProcessMessageQueue.cpp',
|
||||
'ScriptSettings.cpp',
|
||||
'ShadowRoot.cpp',
|
||||
'StyleSheetList.cpp',
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "mozilla/dom/KeyframeEffect.h"
|
||||
|
||||
nsAutoTArray<nsRefPtr<nsDOMMutationObserver>, 4>*
|
||||
nsDOMMutationObserver::sScheduledMutationObservers = nullptr;
|
||||
|
@ -326,12 +328,12 @@ void
|
|||
nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer,
|
||||
AnimationMutation aMutationType)
|
||||
{
|
||||
Animation* source = aPlayer->GetSource();
|
||||
if (!source) {
|
||||
KeyframeEffectReadonly* effect = aPlayer->GetEffect();
|
||||
if (!effect) {
|
||||
return;
|
||||
}
|
||||
|
||||
Element* animationTarget = source->GetTarget();
|
||||
Element* animationTarget = effect->GetTarget();
|
||||
if (!animationTarget) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -973,6 +973,8 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
|
|||
return rv;
|
||||
}
|
||||
|
||||
mRemoteBrowser->SwapLayerTreeObservers(aOther->mRemoteBrowser);
|
||||
|
||||
nsCOMPtr<nsIBrowserDOMWindow> otherBrowserDOMWindow =
|
||||
aOther->mRemoteBrowser->GetBrowserDOMWindow();
|
||||
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWindow =
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mozilla/dom/nsIContentParent.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
#include "mozilla/dom/SameProcessMessageQueue.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
|
@ -1749,7 +1750,6 @@ NS_IMPL_ISUPPORTS(nsScriptCacheCleaner, nsIObserver)
|
|||
nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr;
|
||||
nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr;
|
||||
nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr;
|
||||
nsTArray<nsCOMPtr<nsIRunnable> >* nsFrameMessageManager::sPendingSameProcessAsyncMessages = nullptr;
|
||||
|
||||
class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase,
|
||||
public nsRunnable
|
||||
|
@ -1907,7 +1907,7 @@ public:
|
|||
|
||||
|
||||
class nsAsyncMessageToSameProcessParent : public nsSameProcessAsyncMessageBase,
|
||||
public nsRunnable
|
||||
public SameProcessMessageQueue::Runnable
|
||||
{
|
||||
public:
|
||||
nsAsyncMessageToSameProcessParent(JSContext* aCx,
|
||||
|
@ -1916,25 +1916,15 @@ public:
|
|||
JS::Handle<JSObject *> aCpows,
|
||||
nsIPrincipal* aPrincipal)
|
||||
: nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal)
|
||||
, mDelivered(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
virtual nsresult HandleMessage() override
|
||||
{
|
||||
if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
|
||||
nsFrameMessageManager::sPendingSameProcessAsyncMessages->RemoveElement(this);
|
||||
}
|
||||
if (!mDelivered) {
|
||||
mDelivered = true;
|
||||
nsFrameMessageManager* ppm = nsFrameMessageManager::sSameProcessParentManager;
|
||||
ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm), ppm);
|
||||
}
|
||||
nsFrameMessageManager* ppm = nsFrameMessageManager::sSameProcessParentManager;
|
||||
ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm), ppm);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mDelivered;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1960,15 +1950,9 @@ public:
|
|||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
bool aIsSync) override
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
|
||||
if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
|
||||
asyncMessages.SwapElements(*nsFrameMessageManager::sPendingSameProcessAsyncMessages);
|
||||
uint32_t len = asyncMessages.Length();
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
nsCOMPtr<nsIRunnable> async = asyncMessages[i];
|
||||
async->Run();
|
||||
}
|
||||
}
|
||||
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
|
||||
queue->Flush();
|
||||
|
||||
if (nsFrameMessageManager::sSameProcessParentManager) {
|
||||
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
|
||||
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
|
||||
|
@ -1984,13 +1968,10 @@ public:
|
|||
JS::Handle<JSObject *> aCpows,
|
||||
nsIPrincipal* aPrincipal) override
|
||||
{
|
||||
if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
|
||||
nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray<nsCOMPtr<nsIRunnable> >;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
|
||||
nsRefPtr<nsAsyncMessageToSameProcessParent> ev =
|
||||
new nsAsyncMessageToSameProcessParent(aCx, aMessage, aData, aCpows, aPrincipal);
|
||||
nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
queue->Push(ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "mozilla/dom/SameProcessMessageQueue.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
#include "mozilla/jsipc/CpowHolder.h"
|
||||
|
||||
|
@ -203,8 +204,7 @@ private:
|
|||
}
|
||||
if (this == sChildProcessManager) {
|
||||
sChildProcessManager = nullptr;
|
||||
delete sPendingSameProcessAsyncMessages;
|
||||
sPendingSameProcessAsyncMessages = nullptr;
|
||||
delete mozilla::dom::SameProcessMessageQueue::Get();
|
||||
}
|
||||
if (this == sSameProcessParentManager) {
|
||||
sSameProcessParentManager = nullptr;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/SameProcessMessageQueue.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
#include "js/StructuredClone.h"
|
||||
|
||||
|
@ -35,13 +36,9 @@ nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx,
|
|||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
bool aIsSync)
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
|
||||
asyncMessages.SwapElements(mASyncMessages);
|
||||
uint32_t len = asyncMessages.Length();
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
nsCOMPtr<nsIRunnable> async = asyncMessages[i];
|
||||
async->Run();
|
||||
}
|
||||
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
|
||||
queue->Flush();
|
||||
|
||||
if (mChromeMessageManager) {
|
||||
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
|
||||
nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
|
||||
|
@ -52,7 +49,7 @@ nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx,
|
|||
}
|
||||
|
||||
class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
|
||||
public nsRunnable
|
||||
public SameProcessMessageQueue::Runnable
|
||||
{
|
||||
public:
|
||||
nsAsyncMessageToParent(JSContext* aCx,
|
||||
|
@ -62,25 +59,16 @@ public:
|
|||
JS::Handle<JSObject *> aCpows,
|
||||
nsIPrincipal* aPrincipal)
|
||||
: nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal),
|
||||
mTabChild(aTabChild), mRun(false)
|
||||
mTabChild(aTabChild)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
virtual nsresult HandleMessage() override
|
||||
{
|
||||
if (mRun) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mRun = true;
|
||||
mTabChild->mASyncMessages.RemoveElement(this);
|
||||
ReceiveMessage(mTabChild->mOwner, mTabChild->mChromeMessageManager);
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
|
||||
// True if this runnable has already been called. This can happen if DoSendSyncMessage
|
||||
// is called while waiting for an asynchronous message send.
|
||||
bool mRun;
|
||||
};
|
||||
|
||||
bool
|
||||
|
@ -90,10 +78,10 @@ nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
|
|||
JS::Handle<JSObject *> aCpows,
|
||||
nsIPrincipal* aPrincipal)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
|
||||
nsRefPtr<nsAsyncMessageToParent> ev =
|
||||
new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows, aPrincipal);
|
||||
mASyncMessages.AppendElement(ev);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
queue->Push(ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,6 @@ protected:
|
|||
public:
|
||||
nsIContent* mOwner;
|
||||
nsFrameMessageManager* mChromeMessageManager;
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > mASyncMessages;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
#include "nsBindingManager.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "mozilla/dom/HTMLImageElement.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/KeyframeEffect.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
#include "nsDOMMutationObserver.h"
|
||||
|
@ -216,14 +218,14 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer,
|
|||
static inline Element*
|
||||
GetTarget(AnimationPlayer* aPlayer)
|
||||
{
|
||||
Animation* source = aPlayer->GetSource();
|
||||
if (!source) {
|
||||
KeyframeEffectReadonly* effect = aPlayer->GetEffect();
|
||||
if (!effect) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Element* target;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
source->GetTarget(target, pseudoType);
|
||||
effect->GetTarget(target, pseudoType);
|
||||
|
||||
// If the animation targets a pseudo-element, we don't dispatch
|
||||
// notifications for it. (In the future we will have PseudoElement
|
||||
|
@ -232,7 +234,7 @@ GetTarget(AnimationPlayer* aPlayer)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return source->GetTarget();
|
||||
return effect->GetTarget();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -545,6 +545,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
|||
[test_bug558726.html]
|
||||
[test_bug559526.html]
|
||||
[test_bug560780.html]
|
||||
skip-if = android_version == '18' # Android 4.3 intermittent, Bug 1154497
|
||||
[test_bug562137.html]
|
||||
[test_bug562169-1.html]
|
||||
[test_bug562169-2.html]
|
||||
|
|
|
@ -88,6 +88,10 @@ DOMInterfaces = {
|
|||
'concrete': False
|
||||
},
|
||||
|
||||
'AnimationEffectReadonly': {
|
||||
'concrete': False
|
||||
},
|
||||
|
||||
'AnimationTimeline': {
|
||||
'concrete': False
|
||||
},
|
||||
|
|
|
@ -977,7 +977,6 @@ nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate,
|
|||
|
||||
nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement)
|
||||
: mTextCtrlElement(aOwningElement),
|
||||
mRestoringSelection(nullptr),
|
||||
mBoundFrame(nullptr),
|
||||
mEverInited(false),
|
||||
mEditorInitialized(false),
|
||||
|
@ -1452,6 +1451,12 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextEditorState::FinishedRestoringSelection()
|
||||
{
|
||||
mRestoringSelection = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextEditorState::IsSelectionCached() const
|
||||
{
|
||||
|
|
|
@ -239,7 +239,7 @@ private:
|
|||
|
||||
nsresult InitializeRootNode();
|
||||
|
||||
void FinishedRestoringSelection() { mRestoringSelection = nullptr; }
|
||||
void FinishedRestoringSelection();
|
||||
|
||||
mozilla::dom::HTMLInputElement* GetParentNumberControl(nsFrame* aFrame) const;
|
||||
|
||||
|
@ -271,7 +271,7 @@ private:
|
|||
|
||||
nsITextControlElement* const mTextCtrlElement;
|
||||
nsRefPtr<nsTextInputSelectionImpl> mSelCon;
|
||||
RestoreSelectionState* mRestoringSelection;
|
||||
nsRefPtr<RestoreSelectionState> mRestoringSelection;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
nsCOMPtr<mozilla::dom::Element> mRootNode;
|
||||
nsCOMPtr<mozilla::dom::Element> mPlaceholderDiv;
|
||||
|
|
|
@ -483,7 +483,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
|
|||
[test_iframe_sandbox_popups.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
[test_iframe_sandbox_popups_inheritance.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage) android(bug 939642)
|
||||
[test_iframe_sandbox_redirect.html]
|
||||
[test_iframe_sandbox_same_origin.html]
|
||||
[test_iframe_sandbox_workers.html]
|
||||
|
|
|
@ -6591,6 +6591,11 @@ class OpenDatabaseOp final
|
|||
|
||||
nsRefPtr<DatabaseOfflineStorage> mOfflineStorage;
|
||||
|
||||
// This is only set while a VersionChangeOp is live. It holds a strong
|
||||
// reference to its OpenDatabaseOp object so this is a weak pointer to avoid
|
||||
// cycles.
|
||||
VersionChangeOp* mVersionChangeOp;
|
||||
|
||||
public:
|
||||
OpenDatabaseOp(Factory* aFactory,
|
||||
already_AddRefed<ContentParent> aContentParent,
|
||||
|
@ -6607,7 +6612,9 @@ public:
|
|||
|
||||
private:
|
||||
~OpenDatabaseOp()
|
||||
{ }
|
||||
{
|
||||
MOZ_ASSERT(!mVersionChangeOp);
|
||||
}
|
||||
|
||||
nsresult
|
||||
LoadDatabaseInformation(mozIStorageConnection* aConnection);
|
||||
|
@ -6635,6 +6642,9 @@ private:
|
|||
void
|
||||
ConnectionClosedCallback();
|
||||
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
virtual nsresult
|
||||
QuotaManagerOpen() override;
|
||||
|
||||
|
@ -6655,9 +6665,6 @@ private:
|
|||
|
||||
virtual void
|
||||
SendResults() override;
|
||||
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
};
|
||||
|
||||
class OpenDatabaseOp::VersionChangeOp final
|
||||
|
@ -6684,7 +6691,9 @@ private:
|
|||
}
|
||||
|
||||
~VersionChangeOp()
|
||||
{ }
|
||||
{
|
||||
MOZ_ASSERT(!mOpenDatabaseOp);
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
DoDatabaseWork(DatabaseConnection* aConnection) override;
|
||||
|
@ -7908,7 +7917,7 @@ class DatabaseOfflineStorage final
|
|||
bool mInvalidatedOnMainThread;
|
||||
bool mInvalidatedOnOwningThread;
|
||||
|
||||
DebugOnly<bool> mRegisteredWithQuotaManager;
|
||||
bool mRegisteredWithQuotaManager;
|
||||
|
||||
public:
|
||||
DatabaseOfflineStorage(QuotaClient* aQuotaClient,
|
||||
|
@ -7964,7 +7973,7 @@ private:
|
|||
~DatabaseOfflineStorage()
|
||||
{
|
||||
MOZ_ASSERT(!mDatabase);
|
||||
MOZ_ASSERT(!mRegisteredWithQuotaManager);
|
||||
MOZ_RELEASE_ASSERT(!mRegisteredWithQuotaManager);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -8454,10 +8463,11 @@ DatabaseConnection::FinishWriteTransaction()
|
|||
{
|
||||
AssertIsOnConnectionThread();
|
||||
MOZ_ASSERT(mStorageConnection);
|
||||
MOZ_ASSERT(mUpdateRefcountFunction);
|
||||
MOZ_ASSERT(mDEBUGInWriteTransaction);
|
||||
|
||||
mUpdateRefcountFunction->Reset();
|
||||
if (mUpdateRefcountFunction) {
|
||||
mUpdateRefcountFunction->Reset();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
mDEBUGInWriteTransaction = false;
|
||||
|
@ -17095,6 +17105,7 @@ OpenDatabaseOp::OpenDatabaseOp(Factory* aFactory,
|
|||
: FactoryOp(aFactory, Move(aContentParent), aParams, /* aDeleting */ false)
|
||||
, mMetadata(new FullDatabaseMetadata(aParams.metadata()))
|
||||
, mRequestedVersion(aParams.metadata().version())
|
||||
, mVersionChangeOp(nullptr)
|
||||
{
|
||||
auto& optionalContentParentId =
|
||||
const_cast<OptionalContentId&>(mOptionalContentParentId);
|
||||
|
@ -17108,6 +17119,22 @@ OpenDatabaseOp::OpenDatabaseOp(Factory* aFactory,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenDatabaseOp::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mDatabase && aWhy != Deletion) {
|
||||
mDatabase->Invalidate();
|
||||
}
|
||||
|
||||
if (mVersionChangeOp) {
|
||||
mVersionChangeOp->NoteActorDestroyed();
|
||||
}
|
||||
|
||||
FactoryOp::ActorDestroy(aWhy);
|
||||
}
|
||||
|
||||
nsresult
|
||||
OpenDatabaseOp::QuotaManagerOpen()
|
||||
{
|
||||
|
@ -17751,6 +17778,10 @@ OpenDatabaseOp::DispatchToWorkThread()
|
|||
const nsID& backgroundChildLoggingId =
|
||||
mVersionChangeTransaction->GetLoggingInfo()->Id();
|
||||
|
||||
if (NS_WARN_IF(!mDatabase->RegisterTransaction(mVersionChangeTransaction))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsRefPtr<VersionChangeOp> versionChangeOp = new VersionChangeOp(this);
|
||||
|
||||
uint64_t transactionId =
|
||||
|
@ -17761,13 +17792,10 @@ OpenDatabaseOp::DispatchToWorkThread()
|
|||
/* aIsWriteTransaction */ true,
|
||||
versionChangeOp);
|
||||
|
||||
mVersionChangeTransaction->SetActive(transactionId);
|
||||
mVersionChangeOp = versionChangeOp;
|
||||
|
||||
mVersionChangeTransaction->NoteActiveRequest();
|
||||
|
||||
if (NS_WARN_IF(!mDatabase->RegisterTransaction(mVersionChangeTransaction))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mVersionChangeTransaction->SetActive(transactionId);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -17897,18 +17925,6 @@ OpenDatabaseOp::SendResults()
|
|||
FinishSendResults();
|
||||
}
|
||||
|
||||
void
|
||||
OpenDatabaseOp::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
NoteActorDestroyed();
|
||||
|
||||
if (mDatabase && aWhy != Deletion) {
|
||||
mDatabase->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenDatabaseOp::ConnectionClosedCallback()
|
||||
{
|
||||
|
@ -18222,6 +18238,7 @@ VersionChangeOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
|||
{
|
||||
MOZ_ASSERT(aConnection);
|
||||
aConnection->AssertIsOnConnectionThread();
|
||||
MOZ_ASSERT(mOpenDatabaseOp);
|
||||
MOZ_ASSERT(mOpenDatabaseOp->mState == State_DatabaseWorkVersionChange);
|
||||
|
||||
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread()) ||
|
||||
|
@ -18276,6 +18293,7 @@ VersionChangeOp::SendSuccessResult()
|
|||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mOpenDatabaseOp);
|
||||
MOZ_ASSERT(mOpenDatabaseOp->mState == State_DatabaseWorkVersionChange);
|
||||
MOZ_ASSERT(mOpenDatabaseOp->mVersionChangeOp == this);
|
||||
|
||||
nsresult rv = mOpenDatabaseOp->SendUpgradeNeeded();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -18292,6 +18310,7 @@ VersionChangeOp::SendFailureResult(nsresult aResultCode)
|
|||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mOpenDatabaseOp);
|
||||
MOZ_ASSERT(mOpenDatabaseOp->mState == State_DatabaseWorkVersionChange);
|
||||
MOZ_ASSERT(mOpenDatabaseOp->mVersionChangeOp == this);
|
||||
|
||||
mOpenDatabaseOp->SetFailureCode(aResultCode);
|
||||
mOpenDatabaseOp->mState = State_SendingResults;
|
||||
|
@ -18306,7 +18325,10 @@ OpenDatabaseOp::
|
|||
VersionChangeOp::Cleanup()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mOpenDatabaseOp);
|
||||
MOZ_ASSERT(mOpenDatabaseOp->mVersionChangeOp == this);
|
||||
|
||||
mOpenDatabaseOp->mVersionChangeOp = nullptr;
|
||||
mOpenDatabaseOp = nullptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -19343,13 +19365,15 @@ CommitOp::Run()
|
|||
MOZ_ASSERT(database);
|
||||
|
||||
if (DatabaseConnection* connection = database->GetConnection()) {
|
||||
// May be null if the VersionChangeOp was canceled.
|
||||
DatabaseConnection::UpdateRefcountFunction* fileRefcountFunction =
|
||||
connection->GetUpdateRefcountFunction();
|
||||
MOZ_ASSERT(fileRefcountFunction);
|
||||
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
mResultCode = fileRefcountFunction->WillCommit();
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(mResultCode), "WillCommit() failed!");
|
||||
if (fileRefcountFunction) {
|
||||
mResultCode = fileRefcountFunction->WillCommit();
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(mResultCode), "WillCommit() failed!");
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
mResultCode = WriteAutoIncrementCounts();
|
||||
|
@ -19373,7 +19397,7 @@ CommitOp::Run()
|
|||
mResultCode = connection->Checkpoint(/* aIdle */ false);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
if (NS_SUCCEEDED(mResultCode) && fileRefcountFunction) {
|
||||
fileRefcountFunction->DidCommit();
|
||||
}
|
||||
}
|
||||
|
@ -19382,7 +19406,9 @@ CommitOp::Run()
|
|||
}
|
||||
|
||||
if (NS_FAILED(mResultCode)) {
|
||||
fileRefcountFunction->DidAbort();
|
||||
if (fileRefcountFunction) {
|
||||
fileRefcountFunction->DidAbort();
|
||||
}
|
||||
|
||||
DatabaseConnection::CachedStatement stmt;
|
||||
if (NS_SUCCEEDED(connection->GetCachedStatement("ROLLBACK", &stmt))) {
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var disableWorkerTest =
|
||||
"This test requires a precise 'executeSoon()' to complete reliably. On a " +
|
||||
"worker 'executeSoon()' currently uses 'setTimeout()', and that switches " +
|
||||
"to the timer thread and back before completing. That gives the IndexedDB " +
|
||||
"transaction thread time to fully complete transactions and to place " +
|
||||
"'complete' events in the worker thread's queue before the timer event, " +
|
||||
"causing ordering problems in the spot marked 'Worker Fails Here' below.";
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function testSteps()
|
||||
|
@ -41,6 +49,8 @@ function testSteps()
|
|||
let wasAbleToGrabObjectStoreOutsideOfCallback = false;
|
||||
let wasAbleToGrabIndexOutsideOfCallback = false;
|
||||
executeSoon(function() {
|
||||
// Worker Fails Here! Due to the thread switching of 'executeSoon()' the
|
||||
// transaction can commit and fire a 'complete' event before we continue.
|
||||
ok(!requestComplete, "Ordering is correct.");
|
||||
wasAbleToGrabObjectStoreOutsideOfCallback = !!transaction.objectStore("foo");
|
||||
wasAbleToGrabIndexOutsideOfCallback =
|
||||
|
|
|
@ -895,7 +895,6 @@ ContentParent::SendAsyncUpdate(nsIWidget* aWidget)
|
|||
if (!aWidget || aWidget->Destroyed()) {
|
||||
return;
|
||||
}
|
||||
printf_stderr("TabParent::SendAsyncUpdate()\n");
|
||||
// Fire off an async request to the plugin to paint its window
|
||||
HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
NS_ASSERTION(hwnd, "Expected valid hwnd value.");
|
||||
|
@ -1881,6 +1880,11 @@ struct DelayedDeleteContentParentTask : public nsRunnable
|
|||
void
|
||||
ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ChildShutdownState"),
|
||||
NS_LITERAL_CSTRING("ActorDestroy"));
|
||||
#endif
|
||||
|
||||
if (mForceKillTimer) {
|
||||
mForceKillTimer->Cancel();
|
||||
mForceKillTimer = nullptr;
|
||||
|
@ -2042,6 +2046,12 @@ ContentParent::NotifyTabDestroying(PBrowserParent* aTab)
|
|||
StartForceKillTimer();
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ForceKillTimeout()
|
||||
{
|
||||
return Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::StartForceKillTimer()
|
||||
{
|
||||
|
@ -2049,8 +2059,7 @@ ContentParent::StartForceKillTimer()
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t timeoutSecs =
|
||||
Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
|
||||
int32_t timeoutSecs = ForceKillTimeout();
|
||||
if (timeoutSecs > 0) {
|
||||
mForceKillTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
MOZ_ASSERT(mForceKillTimer);
|
||||
|
@ -2882,13 +2891,27 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
{
|
||||
if (mSubprocess && (!strcmp(aTopic, "profile-before-change") ||
|
||||
!strcmp(aTopic, "xpcom-shutdown"))) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ChildShutdownState"),
|
||||
NS_LITERAL_CSTRING("Begin"));
|
||||
#endif
|
||||
|
||||
// Okay to call ShutDownProcess multiple times.
|
||||
ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
|
||||
|
||||
int32_t timeout = ForceKillTimeout();
|
||||
|
||||
// Make sure we have a KillHard timer before we start waiting.
|
||||
MOZ_RELEASE_ASSERT(!timeout || !mIPCOpen || mCalledKillHard || mForceKillTimer);
|
||||
|
||||
// Wait for shutdown to complete, so that we receive any shutdown
|
||||
// data (e.g. telemetry) from the child before we quit.
|
||||
// This loop terminate prematurely based on mForceKillTimer.
|
||||
while (mIPCOpen) {
|
||||
// If we clear the KillHard timer, it should only be because we
|
||||
// called KillHard. In that case, ActorDestroy should happen
|
||||
// momentarily.
|
||||
MOZ_RELEASE_ASSERT(!timeout || mCalledKillHard || mForceKillTimer);
|
||||
NS_ProcessNextEvent(nullptr, true);
|
||||
}
|
||||
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
|
||||
|
@ -3335,6 +3358,11 @@ ContentParent::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
|
|||
void
|
||||
ContentParent::KillHard(const char* aReason)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ChildShutdownState"),
|
||||
NS_LITERAL_CSTRING("KillHard"));
|
||||
#endif
|
||||
|
||||
// On Windows, calling KillHard multiple times causes problems - the
|
||||
// process handle becomes invalid on the first call, causing a second call
|
||||
// to crash our process - more details in bug 890840.
|
||||
|
|
|
@ -2906,6 +2906,23 @@ TabParent::LayerTreeUpdate(bool aActive)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::SwapLayerTreeObservers(TabParent* aOther)
|
||||
{
|
||||
if (IsDestroyed() || aOther->IsDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderFrameParent* rfp = GetRenderFrame();
|
||||
RenderFrameParent* otherRfp = aOther->GetRenderFrame();
|
||||
if(!rfp || !otherRfp) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompositorParent::SwapLayerTreeObservers(rfp->GetLayersId(),
|
||||
otherRfp->GetLayersId());
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvRemotePaintIsReady()
|
||||
{
|
||||
|
|
|
@ -399,6 +399,7 @@ public:
|
|||
bool RequestNotifyLayerTreeReady();
|
||||
bool RequestNotifyLayerTreeCleared();
|
||||
bool LayerTreeUpdate(bool aActive);
|
||||
void SwapLayerTreeObservers(TabParent* aOther);
|
||||
|
||||
virtual bool
|
||||
RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
|
||||
|
|
|
@ -101,14 +101,18 @@ ManifestProcessor.prototype = {
|
|||
// * manifestURL: the URL of the manifest, to resolve URLs.
|
||||
// * docURL: the URL of the owner doc, for security checks.
|
||||
process({
|
||||
jsonText, manifestURL, docURL
|
||||
jsonText: aJsonText,
|
||||
manifestURL: aManifestURL,
|
||||
docURL: aDocURL
|
||||
}) {
|
||||
const manifestURL = new URL(aManifestURL);
|
||||
const docURL = new URL(aDocURL);
|
||||
const console = new ConsoleAPI({
|
||||
prefix: 'Web Manifest: '
|
||||
});
|
||||
let rawManifest = {};
|
||||
try {
|
||||
rawManifest = JSON.parse(jsonText);
|
||||
rawManifest = JSON.parse(aJsonText);
|
||||
} catch (e) {}
|
||||
if (typeof rawManifest !== 'object' || rawManifest === null) {
|
||||
let msg = 'Manifest needs to be an object.';
|
||||
|
@ -124,7 +128,8 @@ ManifestProcessor.prototype = {
|
|||
short_name: processShortNameMember(rawManifest),
|
||||
};
|
||||
processedManifest.scope = processScopeMember(rawManifest, manifestURL,
|
||||
docURL, processedManifest.start_url);
|
||||
docURL, new URL(processedManifest.start_url));
|
||||
|
||||
return processedManifest;
|
||||
|
||||
function processNameMember(aManifest) {
|
||||
|
@ -188,8 +193,11 @@ ManifestProcessor.prototype = {
|
|||
expectedType: 'string',
|
||||
trim: false
|
||||
};
|
||||
const value = extractValue(spec, console);
|
||||
let scopeURL;
|
||||
const value = extractValue(spec, console);
|
||||
if (value === undefined || value === '') {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
scopeURL = new URL(value, aManifestURL);
|
||||
} catch (e) {
|
||||
|
@ -210,7 +218,7 @@ ManifestProcessor.prototype = {
|
|||
console.warn(msg);
|
||||
return undefined;
|
||||
}
|
||||
return scopeURL;
|
||||
return scopeURL.href;
|
||||
}
|
||||
|
||||
function processStartURLMember(aManifest, aManifestURL, aDocURL) {
|
||||
|
@ -221,7 +229,7 @@ ManifestProcessor.prototype = {
|
|||
expectedType: 'string',
|
||||
trim: false
|
||||
};
|
||||
let result = new URL(aDocURL);
|
||||
let result = new URL(aDocURL).href;
|
||||
const value = extractValue(spec, console);
|
||||
if (value === undefined || value === '') {
|
||||
return result;
|
||||
|
@ -237,7 +245,7 @@ ManifestProcessor.prototype = {
|
|||
let msg = 'start_url must be same origin as document.';
|
||||
console.warn(msg);
|
||||
} else {
|
||||
result = potentialResult;
|
||||
result = potentialResult.href;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -248,7 +256,7 @@ this.ManifestProcessor = ManifestProcessor;
|
|||
function IconsProcessor() {}
|
||||
|
||||
// Static getters
|
||||
Object.defineProperties(IconsProcessor,{
|
||||
Object.defineProperties(IconsProcessor, {
|
||||
'onlyDecimals': {
|
||||
get: function() {
|
||||
return /^\d+$/;
|
||||
|
@ -324,7 +332,7 @@ IconsProcessor.process = function(aManifest, aBaseURL, console) {
|
|||
let url;
|
||||
if (value && value.length) {
|
||||
try {
|
||||
url = new URL(value, aBaseURL);
|
||||
url = new URL(value, aBaseURL).href;
|
||||
} catch (e) {}
|
||||
}
|
||||
return url;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s
|
||||
|
||||
support-files =
|
||||
common.js
|
||||
|
|
|
@ -61,7 +61,7 @@ data.jsonText = JSON.stringify(noSrc);
|
|||
var result = processor.process(data);
|
||||
ise(result.icons.length, 0, expected);
|
||||
|
||||
var expected = `Expect icon's src to be an instance of URL.`;
|
||||
var expected = `Expect icon's src to be a string.`;
|
||||
var withSrc = {
|
||||
icons: [{
|
||||
src: 'pass'
|
||||
|
@ -69,7 +69,7 @@ var withSrc = {
|
|||
};
|
||||
data.jsonText = JSON.stringify(withSrc);
|
||||
var result = processor.process(data);
|
||||
ise(SpecialPowers.unwrap(result.icons[0].src) instanceof URL, true, expected);
|
||||
ise(typeof result.icons[0].src, "string", expected);
|
||||
|
||||
var expected = `Expect only icons with a src prop to be kept.`;
|
||||
var withSrc = {
|
||||
|
|
|
@ -20,7 +20,7 @@ invalidJson.forEach((testString) => {
|
|||
var expected = `Expect to recover from invalid JSON: ${testString}`;
|
||||
data.jsonText = testString;
|
||||
var result = processor.process(data);
|
||||
SimpleTest.ok(result.start_url.href === docURL.href, true, expected);
|
||||
SimpleTest.ise(result.start_url, docURL.href, expected);
|
||||
});
|
||||
|
||||
var validButUnhelpful = ["1", 1, "", "[{}]", "null"];
|
||||
|
@ -28,7 +28,7 @@ validButUnhelpful.forEach((testString) => {
|
|||
var expected = `Expect to recover from invalid JSON: ${testString}`;
|
||||
data.jsonText = testString;
|
||||
var result = processor.process(data);
|
||||
SimpleTest.ok(result.start_url.href === docURL.href, true, expected);
|
||||
SimpleTest.ise(result.start_url, docURL.href, expected);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -47,8 +47,7 @@ URLs.forEach((url) => {
|
|||
});
|
||||
var absURL = new URL(url, manifestURL).toString();
|
||||
var result = processor.process(data);
|
||||
console.log(result);
|
||||
ise(String(result.scope), absURL, expected);
|
||||
ise(result.scope, absURL, expected);
|
||||
});
|
||||
|
||||
var expected = 'If start URL is not in scope, return undefined.';
|
||||
|
|
|
@ -489,7 +489,7 @@ MediaRawData::MediaRawData()
|
|||
, mData(nullptr)
|
||||
, mSize(0)
|
||||
, mCrypto(mCryptoInternal)
|
||||
, mBuffer(new LargeDataBuffer(RAW_DATA_DEFAULT_SIZE))
|
||||
, mBuffer(new MediaLargeByteBuffer(RAW_DATA_DEFAULT_SIZE))
|
||||
, mPadding(0)
|
||||
{
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize)
|
|||
, mData(nullptr)
|
||||
, mSize(0)
|
||||
, mCrypto(mCryptoInternal)
|
||||
, mBuffer(new LargeDataBuffer(RAW_DATA_DEFAULT_SIZE))
|
||||
, mBuffer(new MediaLargeByteBuffer(RAW_DATA_DEFAULT_SIZE))
|
||||
, mPadding(0)
|
||||
{
|
||||
if (!EnsureCapacity(aSize)) {
|
||||
|
|
|
@ -22,8 +22,8 @@ class Image;
|
|||
class ImageContainer;
|
||||
}
|
||||
|
||||
class LargeDataBuffer;
|
||||
class DataBuffer;
|
||||
class MediaLargeByteBuffer;
|
||||
class MediaByteBuffer;
|
||||
|
||||
// Container that holds media samples.
|
||||
class MediaData {
|
||||
|
@ -369,7 +369,7 @@ private:
|
|||
explicit MediaRawDataWriter(MediaRawData* aMediaRawData);
|
||||
bool EnsureSize(size_t aSize);
|
||||
MediaRawData* mTarget;
|
||||
nsRefPtr<LargeDataBuffer> mBuffer;
|
||||
nsRefPtr<MediaLargeByteBuffer> mBuffer;
|
||||
};
|
||||
|
||||
class MediaRawData : public MediaData {
|
||||
|
@ -383,7 +383,7 @@ public:
|
|||
size_t mSize;
|
||||
|
||||
const CryptoSample& mCrypto;
|
||||
nsRefPtr<DataBuffer> mExtraData;
|
||||
nsRefPtr<MediaByteBuffer> mExtraData;
|
||||
|
||||
// Return a deep copy or nullptr if out of memory.
|
||||
virtual already_AddRefed<MediaRawData> Clone() const;
|
||||
|
@ -403,29 +403,29 @@ private:
|
|||
// read as required by some data decoders.
|
||||
// Returns false if memory couldn't be allocated.
|
||||
bool EnsureCapacity(size_t aSize);
|
||||
nsRefPtr<LargeDataBuffer> mBuffer;
|
||||
nsRefPtr<MediaLargeByteBuffer> mBuffer;
|
||||
CryptoSample mCryptoInternal;
|
||||
uint32_t mPadding;
|
||||
MediaRawData(const MediaRawData&); // Not implemented
|
||||
};
|
||||
|
||||
// LargeDataBuffer is a ref counted fallible TArray.
|
||||
// MediaLargeByteBuffer is a ref counted fallible TArray.
|
||||
// It is designed to share potentially big byte arrays.
|
||||
class LargeDataBuffer : public FallibleTArray<uint8_t> {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LargeDataBuffer);
|
||||
LargeDataBuffer() = default;
|
||||
explicit LargeDataBuffer(size_t aCapacity) : FallibleTArray<uint8_t>(aCapacity) {}
|
||||
class MediaLargeByteBuffer : public FallibleTArray<uint8_t> {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaLargeByteBuffer);
|
||||
MediaLargeByteBuffer() = default;
|
||||
explicit MediaLargeByteBuffer(size_t aCapacity) : FallibleTArray<uint8_t>(aCapacity) {}
|
||||
|
||||
private:
|
||||
~LargeDataBuffer() {}
|
||||
~MediaLargeByteBuffer() {}
|
||||
};
|
||||
|
||||
// DataBuffer is a ref counted infallible TArray.
|
||||
class DataBuffer : public nsTArray<uint8_t> {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataBuffer);
|
||||
// MediaByteBuffer is a ref counted infallible TArray.
|
||||
class MediaByteBuffer : public nsTArray<uint8_t> {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaByteBuffer);
|
||||
|
||||
private:
|
||||
~DataBuffer() {}
|
||||
~MediaByteBuffer() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
, mDisplay(nsIntSize(aWidth, aHeight))
|
||||
, mStereoMode(StereoMode::MONO)
|
||||
, mImage(nsIntSize(aWidth, aHeight))
|
||||
, mExtraData(new DataBuffer)
|
||||
, mExtraData(new MediaByteBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ public:
|
|||
// Size in pixels of decoded video's image.
|
||||
nsIntSize mImage;
|
||||
|
||||
nsRefPtr<DataBuffer> mExtraData;
|
||||
nsRefPtr<MediaByteBuffer> mExtraData;
|
||||
};
|
||||
|
||||
class AudioInfo : public TrackInfo {
|
||||
|
@ -144,8 +144,8 @@ public:
|
|||
, mBitDepth(0)
|
||||
, mProfile(0)
|
||||
, mExtendedProfile(0)
|
||||
, mCodecSpecificConfig(new DataBuffer)
|
||||
, mExtraData(new DataBuffer)
|
||||
, mCodecSpecificConfig(new MediaByteBuffer)
|
||||
, mExtraData(new MediaByteBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -164,8 +164,8 @@ public:
|
|||
// Extended codec profile.
|
||||
int8_t mExtendedProfile;
|
||||
|
||||
nsRefPtr<DataBuffer> mCodecSpecificConfig;
|
||||
nsRefPtr<DataBuffer> mExtraData;
|
||||
nsRefPtr<MediaByteBuffer> mCodecSpecificConfig;
|
||||
nsRefPtr<MediaByteBuffer> mExtraData;
|
||||
|
||||
virtual bool IsValid() const override
|
||||
{
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "MediaTrackConstraints.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "Latency.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
// For PR_snprintf
|
||||
#include "prprf.h"
|
||||
|
@ -332,6 +333,18 @@ public:
|
|||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
|
||||
~DeviceSuccessCallbackRunnable()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
// This can happen if the main thread processes the runnable before
|
||||
// GetUserMediaDevicesTask::Run returns.
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
|
||||
NS_ProxyRelease(mainThread, mOnSuccess);
|
||||
NS_ProxyRelease(mainThread, mOnFailure);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
AnonymizeId(nsAString& aId, const nsACString& aOriginKey)
|
||||
{
|
||||
|
@ -1498,10 +1511,7 @@ public:
|
|||
result->AppendElement(source);
|
||||
}
|
||||
}
|
||||
// In the case of failure with this newly allocated runnable, we
|
||||
// intentionally leak the runnable, because we've pawned mOnSuccess and
|
||||
// mOnFailure onto it which are main thread objects unsafe to release here.
|
||||
DeviceSuccessCallbackRunnable* runnable =
|
||||
nsRefPtr<DeviceSuccessCallbackRunnable> runnable =
|
||||
new DeviceSuccessCallbackRunnable(mWindowId, mOnSuccess, mOnFailure,
|
||||
result.forget());
|
||||
if (mPrivileged) {
|
||||
|
|
|
@ -124,6 +124,7 @@ private:
|
|||
|
||||
nsresult
|
||||
MediaTaskQueue::SyncDispatch(TemporaryRef<nsIRunnable> aRunnable) {
|
||||
NS_WARNING("MediaTaskQueue::SyncDispatch is dangerous and deprecated. Stop using this!");
|
||||
RefPtr<MediaTaskQueueSyncRunnable> task(new MediaTaskQueueSyncRunnable(aRunnable));
|
||||
nsresult rv = Dispatch(task);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -84,6 +84,8 @@ public:
|
|||
// flushed. Normal operations should use Dispatch.
|
||||
nsresult ForceDispatch(TemporaryRef<nsIRunnable> aRunnable);
|
||||
|
||||
// DEPRECATED! Do not us, if a flush happens at the same time, this function
|
||||
// can hang and block forever!
|
||||
nsresult SyncDispatch(TemporaryRef<nsIRunnable> aRunnable);
|
||||
|
||||
// Puts the queue in a shutdown state and returns immediately. The queue will
|
||||
|
|
|
@ -440,7 +440,7 @@ CDMProxy::gmp_Shutdown()
|
|||
// Abort any pending decrypt jobs, to awaken any clients waiting on a job.
|
||||
for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
|
||||
DecryptJob* job = mDecryptionJobs[i];
|
||||
job->mClient->Decrypted(GMPAbortedErr, nullptr);
|
||||
job->PostResult(GMPAbortedErr);
|
||||
}
|
||||
mDecryptionJobs.Clear();
|
||||
|
||||
|
@ -625,23 +625,22 @@ CDMProxy::Capabilites() {
|
|||
|
||||
void
|
||||
CDMProxy::Decrypt(MediaRawData* aSample,
|
||||
DecryptionClient* aClient)
|
||||
DecryptionClient* aClient,
|
||||
MediaTaskQueue* aTaskQueue)
|
||||
{
|
||||
nsAutoPtr<DecryptJob> job(new DecryptJob(aSample, aClient));
|
||||
nsRefPtr<DecryptJob> job(new DecryptJob(aSample, aClient, aTaskQueue));
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethodWithArg<nsAutoPtr<DecryptJob>>(this, &CDMProxy::gmp_Decrypt, job));
|
||||
NS_NewRunnableMethodWithArg<nsRefPtr<DecryptJob>>(this, &CDMProxy::gmp_Decrypt, job));
|
||||
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::gmp_Decrypt(nsAutoPtr<DecryptJob> aJob)
|
||||
CDMProxy::gmp_Decrypt(nsRefPtr<DecryptJob> aJob)
|
||||
{
|
||||
MOZ_ASSERT(IsOnGMPThread());
|
||||
MOZ_ASSERT(aJob->mClient);
|
||||
MOZ_ASSERT(aJob->mSample);
|
||||
|
||||
if (!mCDM) {
|
||||
aJob->mClient->Decrypted(GMPAbortedErr, nullptr);
|
||||
aJob->PostResult(GMPAbortedErr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -658,34 +657,64 @@ CDMProxy::gmp_Decrypted(uint32_t aId,
|
|||
const nsTArray<uint8_t>& aDecryptedData)
|
||||
{
|
||||
MOZ_ASSERT(IsOnGMPThread());
|
||||
#ifdef DEBUG
|
||||
bool jobIdFound = false;
|
||||
#endif
|
||||
for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
|
||||
DecryptJob* job = mDecryptionJobs[i];
|
||||
if (job->mId == aId) {
|
||||
if (aDecryptedData.Length() != job->mSample->mSize) {
|
||||
NS_WARNING("CDM returned incorrect number of decrypted bytes");
|
||||
}
|
||||
if (GMP_SUCCEEDED(aResult)) {
|
||||
nsAutoPtr<MediaRawDataWriter> writer(job->mSample->CreateWriter());
|
||||
PodCopy(writer->mData,
|
||||
aDecryptedData.Elements(),
|
||||
std::min<size_t>(aDecryptedData.Length(), job->mSample->mSize));
|
||||
job->mClient->Decrypted(GMPNoErr, job->mSample);
|
||||
} else if (aResult == GMPNoKeyErr) {
|
||||
NS_WARNING("CDM returned GMPNoKeyErr");
|
||||
// We still have the encrypted sample, so we can re-enqueue it to be
|
||||
// decrypted again once the key is usable again.
|
||||
job->mClient->Decrypted(GMPNoKeyErr, job->mSample);
|
||||
} else {
|
||||
nsAutoCString str("CDM returned decode failure GMPErr=");
|
||||
str.AppendInt(aResult);
|
||||
NS_WARNING(str.get());
|
||||
job->mClient->Decrypted(aResult, nullptr);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
jobIdFound = true;
|
||||
#endif
|
||||
job->PostResult(aResult, aDecryptedData);
|
||||
mDecryptionJobs.RemoveElementAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
NS_WARNING("GMPDecryptorChild returned incorrect job ID");
|
||||
#ifdef DEBUG
|
||||
if (!jobIdFound) {
|
||||
NS_WARNING("GMPDecryptorChild returned incorrect job ID");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::DecryptJob::PostResult(GMPErr aResult)
|
||||
{
|
||||
nsTArray<uint8_t> empty;
|
||||
PostResult(aResult, empty);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::DecryptJob::PostResult(GMPErr aResult, const nsTArray<uint8_t>& aDecryptedData)
|
||||
{
|
||||
if (aDecryptedData.Length() != mSample->mSize) {
|
||||
NS_WARNING("CDM returned incorrect number of decrypted bytes");
|
||||
}
|
||||
mResult = aResult;
|
||||
if (GMP_SUCCEEDED(aResult)) {
|
||||
nsAutoPtr<MediaRawDataWriter> writer(mSample->CreateWriter());
|
||||
PodCopy(writer->mData,
|
||||
aDecryptedData.Elements(),
|
||||
std::min<size_t>(aDecryptedData.Length(), mSample->mSize));
|
||||
} else if (aResult == GMPNoKeyErr) {
|
||||
NS_WARNING("CDM returned GMPNoKeyErr");
|
||||
// We still have the encrypted sample, so we can re-enqueue it to be
|
||||
// decrypted again once the key is usable again.
|
||||
} else {
|
||||
nsAutoCString str("CDM returned decode failure GMPErr=");
|
||||
str.AppendInt(aResult);
|
||||
NS_WARNING(str.get());
|
||||
mSample = nullptr;
|
||||
}
|
||||
mTaskQueue->Dispatch(RefPtr<nsIRunnable>(this).forget());
|
||||
}
|
||||
|
||||
nsresult
|
||||
CDMProxy::DecryptJob::Run()
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
mClient->Decrypted(mResult, mSample);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -141,7 +141,9 @@ public:
|
|||
const nsAString& aMsg);
|
||||
|
||||
// Threadsafe.
|
||||
void Decrypt(MediaRawData* aSample, DecryptionClient* aSink);
|
||||
void Decrypt(MediaRawData* aSample,
|
||||
DecryptionClient* aSink,
|
||||
MediaTaskQueue* aTaskQueue);
|
||||
|
||||
// Reject promise with DOMException corresponding to aExceptionCode.
|
||||
// Can be called from any thread.
|
||||
|
@ -234,18 +236,35 @@ private:
|
|||
// GMP thread only.
|
||||
void gmp_RemoveSession(nsAutoPtr<SessionOpData> aData);
|
||||
|
||||
struct DecryptJob {
|
||||
DecryptJob(MediaRawData* aSample, DecryptionClient* aClient)
|
||||
class DecryptJob : public nsRunnable {
|
||||
public:
|
||||
explicit DecryptJob(MediaRawData* aSample,
|
||||
DecryptionClient* aClient,
|
||||
MediaTaskQueue* aTaskQueue)
|
||||
: mId(0)
|
||||
, mSample(aSample)
|
||||
, mClient(aClient)
|
||||
{}
|
||||
, mResult(GMPGenericErr)
|
||||
, mTaskQueue(aTaskQueue)
|
||||
{
|
||||
MOZ_ASSERT(mClient);
|
||||
MOZ_ASSERT(mSample);
|
||||
}
|
||||
|
||||
NS_METHOD Run() override;
|
||||
void PostResult(GMPErr aResult, const nsTArray<uint8_t>& aDecryptedData);
|
||||
void PostResult(GMPErr aResult);
|
||||
|
||||
uint32_t mId;
|
||||
nsRefPtr<MediaRawData> mSample;
|
||||
private:
|
||||
~DecryptJob() {}
|
||||
nsAutoPtr<DecryptionClient> mClient;
|
||||
GMPErr mResult;
|
||||
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||
};
|
||||
// GMP thread only.
|
||||
void gmp_Decrypt(nsAutoPtr<DecryptJob> aJob);
|
||||
void gmp_Decrypt(nsRefPtr<DecryptJob> aJob);
|
||||
|
||||
class RejectPromiseTask : public nsRunnable {
|
||||
public:
|
||||
|
@ -316,7 +335,7 @@ private:
|
|||
|
||||
// Decryption jobs sent to CDM, awaiting result.
|
||||
// GMP thread only.
|
||||
nsTArray<nsAutoPtr<DecryptJob>> mDecryptionJobs;
|
||||
nsTArray<nsRefPtr<DecryptJob>> mDecryptionJobs;
|
||||
|
||||
// Number of buffers we've decrypted. Used to uniquely identify
|
||||
// decryption jobs sent to CDM. Note we can't just use the length of
|
||||
|
|
|
@ -71,7 +71,7 @@ TrackTypeToStr(TrackType aTrack)
|
|||
#endif
|
||||
|
||||
bool
|
||||
AccumulateSPSTelemetry(const DataBuffer* aExtradata)
|
||||
AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
|
||||
{
|
||||
SPSData spsdata;
|
||||
if (H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
|
||||
|
@ -781,7 +781,7 @@ MP4Reader::Update(TrackType aTrack)
|
|||
|
||||
// Collect telemetry from h264 Annex B SPS.
|
||||
if (!mFoundSPSForTelemetry && sample && AnnexB::HasSPS(sample)) {
|
||||
nsRefPtr<DataBuffer> extradata = AnnexB::ExtractExtraData(sample);
|
||||
nsRefPtr<MediaByteBuffer> extradata = AnnexB::ExtractExtraData(sample);
|
||||
mFoundSPSForTelemetry = AccumulateSPSTelemetry(extradata);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class TrackInfo;
|
|||
class AudioInfo;
|
||||
class VideoInfo;
|
||||
class MediaRawData;
|
||||
class DataBuffer;
|
||||
class MediaByteBuffer;
|
||||
|
||||
namespace layers {
|
||||
class ImageContainer;
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
void ClearReorderedFrames();
|
||||
CFDictionaryRef CreateOutputConfiguration();
|
||||
|
||||
nsRefPtr<DataBuffer> mExtraData;
|
||||
nsRefPtr<MediaByteBuffer> mExtraData;
|
||||
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
nsRefPtr<layers::ImageContainer> mImageContainer;
|
||||
|
|
|
@ -22,71 +22,38 @@ public:
|
|||
|
||||
EMEDecryptor(MediaDataDecoder* aDecoder,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
CDMProxy* aProxy)
|
||||
CDMProxy* aProxy,
|
||||
MediaTaskQueue* aDecodeTaskQueue)
|
||||
: mDecoder(aDecoder)
|
||||
, mCallback(aCallback)
|
||||
, mTaskQueue(CreateFlushableMediaDecodeTaskQueue())
|
||||
, mTaskQueue(aDecodeTaskQueue)
|
||||
, mProxy(aProxy)
|
||||
, mSamplesWaitingForKey(new SamplesWaitingForKey(this, mTaskQueue, mProxy))
|
||||
#ifdef DEBUG
|
||||
, mIsShutdown(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
virtual nsresult Init() override {
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
nsresult rv = mTaskQueue->SyncDispatch(
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDataDecoder::Init));
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
return mDecoder->Init();
|
||||
}
|
||||
|
||||
class DeliverDecrypted : public DecryptionClient {
|
||||
public:
|
||||
DeliverDecrypted(EMEDecryptor* aDecryptor, FlushableMediaTaskQueue* aTaskQueue)
|
||||
explicit DeliverDecrypted(EMEDecryptor* aDecryptor)
|
||||
: mDecryptor(aDecryptor)
|
||||
, mTaskQueue(aTaskQueue)
|
||||
{}
|
||||
virtual void Decrypted(GMPErr aResult,
|
||||
MediaRawData* aSample) override {
|
||||
if (aResult == GMPNoKeyErr) {
|
||||
RefPtr<nsIRunnable> task;
|
||||
task = NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
|
||||
mDecryptor,
|
||||
&EMEDecryptor::Input,
|
||||
nsRefPtr<MediaRawData>(aSample));
|
||||
mTaskQueue->Dispatch(task.forget());
|
||||
} else if (GMP_FAILED(aResult)) {
|
||||
if (mDecryptor->mCallback) {
|
||||
mDecryptor->mCallback->Error();
|
||||
}
|
||||
MOZ_ASSERT(!aSample);
|
||||
} else {
|
||||
RefPtr<nsIRunnable> task;
|
||||
task = NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
|
||||
mDecryptor,
|
||||
&EMEDecryptor::Decrypted,
|
||||
nsRefPtr<MediaRawData>(aSample));
|
||||
mTaskQueue->Dispatch(task.forget());
|
||||
}
|
||||
mTaskQueue = nullptr;
|
||||
{ }
|
||||
virtual void Decrypted(GMPErr aResult, MediaRawData* aSample) override {
|
||||
mDecryptor->Decrypted(aResult, aSample);
|
||||
mDecryptor = nullptr;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<EMEDecryptor> mDecryptor;
|
||||
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
|
||||
};
|
||||
|
||||
virtual nsresult Input(MediaRawData* aSample) override {
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
// We run the PDM on its own task queue. We can't run it on the decode
|
||||
// task queue, because that calls into Input() in a loop and waits until
|
||||
// output is delivered. We need to defer some Input() calls while we wait
|
||||
// for keys to become usable, and once they do we need to dispatch an event
|
||||
// to run the PDM on the same task queue, but since the decode task queue
|
||||
// is waiting in MP4Reader::Decode() for output our task would never run.
|
||||
// So we dispatch tasks to make all calls into the wrapped decoder.
|
||||
if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -95,57 +62,59 @@ public:
|
|||
mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId,
|
||||
writer->mCrypto.mSessionIds);
|
||||
|
||||
mProxy->Decrypt(aSample, new DeliverDecrypted(this, mTaskQueue));
|
||||
mProxy->Decrypt(aSample, new DeliverDecrypted(this), mTaskQueue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void Decrypted(MediaRawData* aSample) {
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
nsresult rv = mTaskQueue->Dispatch(
|
||||
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Input,
|
||||
nsRefPtr<MediaRawData>(aSample)));
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
void Decrypted(GMPErr aResult, MediaRawData* aSample) {
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
if (mIsShutdown) {
|
||||
NS_WARNING("EME decrypted sample arrived after shutdown");
|
||||
return;
|
||||
}
|
||||
if (aResult == GMPNoKeyErr) {
|
||||
// Key became unusable after we sent the sample to CDM to decrypt.
|
||||
// Call Input() again, so that the sample is enqueued for decryption
|
||||
// if the key becomes usable again.
|
||||
Input(aSample);
|
||||
} else if (GMP_FAILED(aResult)) {
|
||||
if (mCallback) {
|
||||
mCallback->Error();
|
||||
}
|
||||
MOZ_ASSERT(!aSample);
|
||||
} else {
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
nsresult rv = mDecoder->Input(aSample);
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
}
|
||||
|
||||
virtual nsresult Flush() override {
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
nsresult rv = mTaskQueue->SyncDispatch(
|
||||
NS_NewRunnableMethod(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Flush));
|
||||
nsresult rv = mDecoder->Flush();
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
mSamplesWaitingForKey->Flush();
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual nsresult Drain() override {
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
nsresult rv = mTaskQueue->Dispatch(
|
||||
NS_NewRunnableMethod(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Drain));
|
||||
nsresult rv = mDecoder->Drain();
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual nsresult Shutdown() override {
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
#ifdef DEBUG
|
||||
mIsShutdown = true;
|
||||
#endif
|
||||
nsresult rv = mTaskQueue->SyncDispatch(
|
||||
NS_NewRunnableMethod(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Shutdown));
|
||||
nsresult rv = mDecoder->Shutdown();
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
mSamplesWaitingForKey->BreakCycles();
|
||||
mSamplesWaitingForKey = nullptr;
|
||||
mDecoder = nullptr;
|
||||
mTaskQueue->BeginShutdown();
|
||||
mTaskQueue->AwaitShutdownAndIdle();
|
||||
mTaskQueue = nullptr;
|
||||
mProxy = nullptr;
|
||||
mCallback = nullptr;
|
||||
return rv;
|
||||
|
@ -155,12 +124,10 @@ private:
|
|||
|
||||
nsRefPtr<MediaDataDecoder> mDecoder;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
|
||||
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||
nsRefPtr<CDMProxy> mProxy;
|
||||
nsRefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
|
||||
#ifdef DEBUG
|
||||
bool mIsShutdown;
|
||||
#endif
|
||||
};
|
||||
|
||||
class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy {
|
||||
|
@ -273,7 +240,8 @@ EMEDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
|
|||
|
||||
nsRefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
|
||||
aCallback,
|
||||
mProxy));
|
||||
mProxy,
|
||||
MediaTaskQueue::GetCurrentQueue()));
|
||||
return emeDecoder.forget();
|
||||
}
|
||||
|
||||
|
@ -303,7 +271,8 @@ EMEDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
|
|||
|
||||
nsRefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
|
||||
aCallback,
|
||||
mProxy));
|
||||
mProxy,
|
||||
MediaTaskQueue::GetCurrentQueue()));
|
||||
return emeDecoder.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(
|
|||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_COUNT_CTOR(FFmpegAudioDecoder);
|
||||
// Use a new DataBuffer as the object will be modified during initialization.
|
||||
mExtraData = new DataBuffer;
|
||||
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
||||
mExtraData = new MediaByteBuffer;
|
||||
mExtraData->AppendElements(*aConfig.mCodecSpecificConfig);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ protected:
|
|||
FlushableMediaTaskQueue* mTaskQueue;
|
||||
AVCodecContext* mCodecContext;
|
||||
AVFrame* mFrame;
|
||||
nsRefPtr<DataBuffer> mExtraData;
|
||||
nsRefPtr<MediaByteBuffer> mExtraData;
|
||||
|
||||
private:
|
||||
static bool sFFmpegInitDone;
|
||||
|
|
|
@ -32,8 +32,8 @@ FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
|
|||
, mDisplayHeight(aConfig.mDisplay.height)
|
||||
{
|
||||
MOZ_COUNT_CTOR(FFmpegH264Decoder);
|
||||
// Use a new DataBuffer as the object will be modified during initialization.
|
||||
mExtraData = new DataBuffer;
|
||||
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
||||
mExtraData = new MediaByteBuffer;
|
||||
mExtraData->AppendElements(*aConfig.mExtraData);
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ H264Converter::CreateDecoder()
|
|||
nsresult
|
||||
H264Converter::CreateDecoderAndInit(MediaRawData* aSample)
|
||||
{
|
||||
nsRefPtr<DataBuffer> extra_data =
|
||||
nsRefPtr<MediaByteBuffer> extra_data =
|
||||
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
|
||||
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -165,7 +165,7 @@ H264Converter::CreateDecoderAndInit(MediaRawData* aSample)
|
|||
nsresult
|
||||
H264Converter::CheckForSPSChange(MediaRawData* aSample)
|
||||
{
|
||||
nsRefPtr<DataBuffer> extra_data =
|
||||
nsRefPtr<MediaByteBuffer> extra_data =
|
||||
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
|
||||
if (!mp4_demuxer::AnnexB::HasSPS(extra_data) ||
|
||||
mp4_demuxer::AnnexB::CompareExtraData(extra_data,
|
||||
|
@ -185,7 +185,7 @@ H264Converter::CheckForSPSChange(MediaRawData* aSample)
|
|||
}
|
||||
|
||||
void
|
||||
H264Converter::UpdateConfigFromExtraData(DataBuffer* aExtraData)
|
||||
H264Converter::UpdateConfigFromExtraData(MediaByteBuffer* aExtraData)
|
||||
{
|
||||
mp4_demuxer::SPSData spsdata;
|
||||
if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata) &&
|
||||
|
|
|
@ -47,7 +47,7 @@ private:
|
|||
nsresult CreateDecoder();
|
||||
nsresult CreateDecoderAndInit(MediaRawData* aSample);
|
||||
nsresult CheckForSPSChange(MediaRawData* aSample);
|
||||
void UpdateConfigFromExtraData(DataBuffer* aExtraData);
|
||||
void UpdateConfigFromExtraData(MediaByteBuffer* aExtraData);
|
||||
|
||||
nsRefPtr<PlatformDecoderModule> mPDM;
|
||||
VideoInfo mCurrentConfig;
|
||||
|
|
|
@ -40,7 +40,7 @@ ContainerParser::ContainerParser(const nsACString& aType)
|
|||
}
|
||||
|
||||
bool
|
||||
ContainerParser::IsInitSegmentPresent(LargeDataBuffer* aData)
|
||||
ContainerParser::IsInitSegmentPresent(MediaLargeByteBuffer* aData)
|
||||
{
|
||||
MSE_DEBUG(ContainerParser, "aLength=%u [%x%x%x%x]",
|
||||
aData->Length(),
|
||||
|
@ -52,7 +52,7 @@ return false;
|
|||
}
|
||||
|
||||
bool
|
||||
ContainerParser::IsMediaSegmentPresent(LargeDataBuffer* aData)
|
||||
ContainerParser::IsMediaSegmentPresent(MediaLargeByteBuffer* aData)
|
||||
{
|
||||
MSE_DEBUG(ContainerParser, "aLength=%u [%x%x%x%x]",
|
||||
aData->Length(),
|
||||
|
@ -64,7 +64,7 @@ ContainerParser::IsMediaSegmentPresent(LargeDataBuffer* aData)
|
|||
}
|
||||
|
||||
bool
|
||||
ContainerParser::ParseStartAndEndTimestamps(LargeDataBuffer* aData,
|
||||
ContainerParser::ParseStartAndEndTimestamps(MediaLargeByteBuffer* aData,
|
||||
int64_t& aStart, int64_t& aEnd)
|
||||
{
|
||||
return false;
|
||||
|
@ -89,7 +89,7 @@ ContainerParser::HasCompleteInitData()
|
|||
return mHasInitData && !!mInitData->Length();
|
||||
}
|
||||
|
||||
LargeDataBuffer*
|
||||
MediaLargeByteBuffer*
|
||||
ContainerParser::InitData()
|
||||
{
|
||||
return mInitData;
|
||||
|
@ -106,7 +106,7 @@ public:
|
|||
static const unsigned NS_PER_USEC = 1000;
|
||||
static const unsigned USEC_PER_SEC = 1000000;
|
||||
|
||||
bool IsInitSegmentPresent(LargeDataBuffer* aData)
|
||||
bool IsInitSegmentPresent(MediaLargeByteBuffer* aData)
|
||||
{
|
||||
ContainerParser::IsInitSegmentPresent(aData);
|
||||
// XXX: This is overly primitive, needs to collect data as it's appended
|
||||
|
@ -129,7 +129,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IsMediaSegmentPresent(LargeDataBuffer* aData)
|
||||
bool IsMediaSegmentPresent(MediaLargeByteBuffer* aData)
|
||||
{
|
||||
ContainerParser::IsMediaSegmentPresent(aData);
|
||||
// XXX: This is overly primitive, needs to collect data as it's appended
|
||||
|
@ -150,7 +150,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ParseStartAndEndTimestamps(LargeDataBuffer* aData,
|
||||
bool ParseStartAndEndTimestamps(MediaLargeByteBuffer* aData,
|
||||
int64_t& aStart, int64_t& aEnd)
|
||||
{
|
||||
bool initSegment = IsInitSegmentPresent(aData);
|
||||
|
@ -158,7 +158,7 @@ public:
|
|||
mOffset = 0;
|
||||
mParser = WebMBufferedParser(0);
|
||||
mOverlappedMapping.Clear();
|
||||
mInitData = new LargeDataBuffer();
|
||||
mInitData = new MediaLargeByteBuffer();
|
||||
mResource = new SourceBufferResource(NS_LITERAL_CSTRING("video/webm"));
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ public:
|
|||
, mMonitor("MP4ContainerParser Index Monitor")
|
||||
{}
|
||||
|
||||
bool IsInitSegmentPresent(LargeDataBuffer* aData)
|
||||
bool IsInitSegmentPresent(MediaLargeByteBuffer* aData)
|
||||
{
|
||||
ContainerParser::IsInitSegmentPresent(aData);
|
||||
// Each MP4 atom has a chunk size and chunk type. The root chunk in an MP4
|
||||
|
@ -262,7 +262,7 @@ public:
|
|||
(*aData)[7] == 'p';
|
||||
}
|
||||
|
||||
bool IsMediaSegmentPresent(LargeDataBuffer* aData)
|
||||
bool IsMediaSegmentPresent(MediaLargeByteBuffer* aData)
|
||||
{
|
||||
ContainerParser::IsMediaSegmentPresent(aData);
|
||||
if (aData->Length() < 8) {
|
||||
|
@ -280,7 +280,7 @@ public:
|
|||
(*aData)[7] == 'p');
|
||||
}
|
||||
|
||||
bool ParseStartAndEndTimestamps(LargeDataBuffer* aData,
|
||||
bool ParseStartAndEndTimestamps(MediaLargeByteBuffer* aData,
|
||||
int64_t& aStart, int64_t& aEnd)
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor); // We're not actually racing against anything,
|
||||
|
@ -294,7 +294,7 @@ public:
|
|||
// manually. This allows the ContainerParser to be shared across different
|
||||
// timestampOffsets.
|
||||
mParser = new mp4_demuxer::MoofParser(mStream, 0, /* aIsAudio = */ false, &mMonitor);
|
||||
mInitData = new LargeDataBuffer();
|
||||
mInitData = new MediaLargeByteBuffer();
|
||||
} else if (!mStream || !mParser) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class LargeDataBuffer;
|
||||
class MediaLargeByteBuffer;
|
||||
class SourceBufferResource;
|
||||
|
||||
class ContainerParser {
|
||||
|
@ -23,17 +23,17 @@ public:
|
|||
// Return true if aData starts with an initialization segment.
|
||||
// The base implementation exists only for debug logging and is expected
|
||||
// to be called first from the overriding implementation.
|
||||
virtual bool IsInitSegmentPresent(LargeDataBuffer* aData);
|
||||
virtual bool IsInitSegmentPresent(MediaLargeByteBuffer* aData);
|
||||
|
||||
// Return true if aData starts with a media segment.
|
||||
// The base implementation exists only for debug logging and is expected
|
||||
// to be called first from the overriding implementation.
|
||||
virtual bool IsMediaSegmentPresent(LargeDataBuffer* aData);
|
||||
virtual bool IsMediaSegmentPresent(MediaLargeByteBuffer* aData);
|
||||
|
||||
// Parse aData to extract the start and end frame times from the media
|
||||
// segment. aData may not start on a parser sync boundary. Return true
|
||||
// if aStart and aEnd have been updated.
|
||||
virtual bool ParseStartAndEndTimestamps(LargeDataBuffer* aData,
|
||||
virtual bool ParseStartAndEndTimestamps(MediaLargeByteBuffer* aData,
|
||||
int64_t& aStart, int64_t& aEnd);
|
||||
|
||||
// Compare aLhs and rHs, considering any error that may exist in the
|
||||
|
@ -43,7 +43,7 @@ public:
|
|||
|
||||
virtual int64_t GetRoundingError();
|
||||
|
||||
LargeDataBuffer* InitData();
|
||||
MediaLargeByteBuffer* InitData();
|
||||
|
||||
bool HasInitData()
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ public:
|
|||
static ContainerParser* CreateForMIMEType(const nsACString& aType);
|
||||
|
||||
protected:
|
||||
nsRefPtr<LargeDataBuffer> mInitData;
|
||||
nsRefPtr<MediaLargeByteBuffer> mInitData;
|
||||
nsRefPtr<SourceBufferResource> mResource;
|
||||
bool mHasInitData;
|
||||
const nsCString mType;
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace mozilla {
|
|||
// timepoint.
|
||||
|
||||
struct ResourceItem {
|
||||
explicit ResourceItem(LargeDataBuffer* aData)
|
||||
explicit ResourceItem(MediaLargeByteBuffer* aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ struct ResourceItem {
|
|||
return size;
|
||||
}
|
||||
|
||||
nsRefPtr<LargeDataBuffer> mData;
|
||||
nsRefPtr<MediaLargeByteBuffer> mData;
|
||||
};
|
||||
|
||||
class ResourceQueueDeallocator : public nsDequeFunctor {
|
||||
|
@ -103,7 +103,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void AppendItem(LargeDataBuffer* aData) {
|
||||
void AppendItem(MediaLargeByteBuffer* aData) {
|
||||
mLogicalLength += aData->Length();
|
||||
Push(new ResourceItem(aData));
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ public:
|
|||
uint32_t offset = aOffset - mOffset;
|
||||
mOffset += offset;
|
||||
evicted += offset;
|
||||
nsRefPtr<LargeDataBuffer> data = new LargeDataBuffer;
|
||||
nsRefPtr<MediaLargeByteBuffer> data = new MediaLargeByteBuffer;
|
||||
data->AppendElements(item->mData->Elements() + offset,
|
||||
item->mData->Length() - offset);
|
||||
item->mData = data;
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace dom {
|
|||
class AppendDataRunnable : public nsRunnable {
|
||||
public:
|
||||
AppendDataRunnable(SourceBuffer* aSourceBuffer,
|
||||
LargeDataBuffer* aData,
|
||||
MediaLargeByteBuffer* aData,
|
||||
double aTimestampOffset,
|
||||
uint32_t aUpdateID)
|
||||
: mSourceBuffer(aSourceBuffer)
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
|
||||
private:
|
||||
nsRefPtr<SourceBuffer> mSourceBuffer;
|
||||
nsRefPtr<LargeDataBuffer> mData;
|
||||
nsRefPtr<MediaLargeByteBuffer> mData;
|
||||
double mTimestampOffset;
|
||||
uint32_t mUpdateID;
|
||||
};
|
||||
|
@ -425,7 +425,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
|||
{
|
||||
MSE_DEBUG("AppendData(aLength=%u)", aLength);
|
||||
|
||||
nsRefPtr<LargeDataBuffer> data = PrepareAppend(aData, aLength, aRv);
|
||||
nsRefPtr<MediaLargeByteBuffer> data = PrepareAppend(aData, aLength, aRv);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
|||
}
|
||||
|
||||
void
|
||||
SourceBuffer::AppendData(LargeDataBuffer* aData, double aTimestampOffset,
|
||||
SourceBuffer::AppendData(MediaLargeByteBuffer* aData, double aTimestampOffset,
|
||||
uint32_t aUpdateID)
|
||||
{
|
||||
if (!mUpdating || aUpdateID != mUpdateID) {
|
||||
|
@ -528,7 +528,7 @@ SourceBuffer::AppendError(bool aDecoderError)
|
|||
}
|
||||
}
|
||||
|
||||
already_AddRefed<LargeDataBuffer>
|
||||
already_AddRefed<MediaLargeByteBuffer>
|
||||
SourceBuffer::PrepareAppend(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
|
||||
{
|
||||
if (!IsAttached() || mUpdating) {
|
||||
|
@ -574,7 +574,7 @@ SourceBuffer::PrepareAppend(const uint8_t* aData, uint32_t aLength, ErrorResult&
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<LargeDataBuffer> data = new LargeDataBuffer();
|
||||
nsRefPtr<MediaLargeByteBuffer> data = new MediaLargeByteBuffer();
|
||||
if (!data->AppendElements(aData, aLength)) {
|
||||
aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
|
||||
return nullptr;
|
||||
|
|
|
@ -30,7 +30,7 @@ struct JSContext;
|
|||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
class LargeDataBuffer;
|
||||
class MediaLargeByteBuffer;
|
||||
class TrackBuffer;
|
||||
template <typename T> class AsyncEventRunner;
|
||||
typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> TrackBufferAppendPromise;
|
||||
|
@ -147,7 +147,7 @@ private:
|
|||
|
||||
// Shared implementation of AppendBuffer overloads.
|
||||
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
|
||||
void AppendData(LargeDataBuffer* aData, double aTimestampOffset,
|
||||
void AppendData(MediaLargeByteBuffer* aData, double aTimestampOffset,
|
||||
uint32_t aAppendID);
|
||||
|
||||
// Implement the "Append Error Algorithm".
|
||||
|
@ -156,11 +156,11 @@ private:
|
|||
// http://w3c.github.io/media-source/#sourcebuffer-append-error
|
||||
void AppendError(bool aDecoderError);
|
||||
|
||||
// Implements the "Prepare Append Algorithm". Returns LargeDataBuffer object
|
||||
// Implements the "Prepare Append Algorithm". Returns MediaLargeByteBuffer object
|
||||
// on success or nullptr (with aRv set) on error.
|
||||
already_AddRefed<LargeDataBuffer> PrepareAppend(const uint8_t* aData,
|
||||
uint32_t aLength,
|
||||
ErrorResult& aRv);
|
||||
already_AddRefed<MediaLargeByteBuffer> PrepareAppend(const uint8_t* aData,
|
||||
uint32_t aLength,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void AppendDataCompletedWithSuccess(bool aValue);
|
||||
void AppendDataErrored(nsresult aError);
|
||||
|
|
|
@ -216,7 +216,7 @@ SourceBufferResource::EvictAll()
|
|||
}
|
||||
|
||||
void
|
||||
SourceBufferResource::AppendData(LargeDataBuffer* aData)
|
||||
SourceBufferResource::AppendData(MediaLargeByteBuffer* aData)
|
||||
{
|
||||
SBR_DEBUG("AppendData(aData=%p, aLength=%u)",
|
||||
aData->Elements(), aData->Length());
|
||||
|
|
|
@ -27,7 +27,7 @@ class nsIStreamListener;
|
|||
namespace mozilla {
|
||||
|
||||
class MediaDecoder;
|
||||
class LargeDataBuffer;
|
||||
class MediaLargeByteBuffer;
|
||||
|
||||
namespace dom {
|
||||
|
||||
|
@ -103,7 +103,7 @@ public:
|
|||
}
|
||||
|
||||
// Used by SourceBuffer.
|
||||
void AppendData(LargeDataBuffer* aData);
|
||||
void AppendData(MediaLargeByteBuffer* aData);
|
||||
void Ended();
|
||||
bool IsEnded()
|
||||
{
|
||||
|
|
|
@ -142,7 +142,7 @@ TrackBuffer::ContinueShutdown()
|
|||
}
|
||||
|
||||
nsRefPtr<TrackBufferAppendPromise>
|
||||
TrackBuffer::AppendData(LargeDataBuffer* aData, int64_t aTimestampOffset)
|
||||
TrackBuffer::AppendData(MediaLargeByteBuffer* aData, int64_t aTimestampOffset)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mInitializationPromise.IsEmpty());
|
||||
|
@ -151,7 +151,7 @@ TrackBuffer::AppendData(LargeDataBuffer* aData, int64_t aTimestampOffset)
|
|||
nsRefPtr<TrackBufferAppendPromise> p = mInitializationPromise.Ensure(__func__);
|
||||
bool hadInitData = mParser->HasInitData();
|
||||
bool hadCompleteInitData = mParser->HasCompleteInitData();
|
||||
nsRefPtr<LargeDataBuffer> oldInit = mParser->InitData();
|
||||
nsRefPtr<MediaLargeByteBuffer> oldInit = mParser->InitData();
|
||||
bool newInitData = mParser->IsInitSegmentPresent(aData);
|
||||
|
||||
// TODO: Run more of the buffer append algorithm asynchronously.
|
||||
|
@ -249,7 +249,7 @@ TrackBuffer::AppendData(LargeDataBuffer* aData, int64_t aTimestampOffset)
|
|||
}
|
||||
|
||||
bool
|
||||
TrackBuffer::AppendDataToCurrentResource(LargeDataBuffer* aData, uint32_t aDuration)
|
||||
TrackBuffer::AppendDataToCurrentResource(MediaLargeByteBuffer* aData, uint32_t aDuration)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mCurrentDecoder) {
|
||||
|
@ -631,7 +631,7 @@ TrackBuffer::InitializeDecoder(SourceBufferDecoder* aDecoder)
|
|||
}
|
||||
if (!wasEnded) {
|
||||
// Adding an empty buffer will reopen the SourceBufferResource
|
||||
nsRefPtr<LargeDataBuffer> emptyBuffer = new LargeDataBuffer;
|
||||
nsRefPtr<MediaLargeByteBuffer> emptyBuffer = new MediaLargeByteBuffer;
|
||||
aDecoder->GetResource()->AppendData(emptyBuffer);
|
||||
}
|
||||
// HACK END.
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace mozilla {
|
|||
|
||||
class ContainerParser;
|
||||
class MediaSourceDecoder;
|
||||
class LargeDataBuffer;
|
||||
class MediaLargeByteBuffer;
|
||||
|
||||
namespace dom {
|
||||
|
||||
|
@ -41,7 +41,7 @@ public:
|
|||
// Append data to the current decoder. Also responsible for calling
|
||||
// NotifyDataArrived on the decoder to keep buffered range computation up
|
||||
// to date. Returns false if the append failed.
|
||||
nsRefPtr<TrackBufferAppendPromise> AppendData(LargeDataBuffer* aData,
|
||||
nsRefPtr<TrackBufferAppendPromise> AppendData(MediaLargeByteBuffer* aData,
|
||||
int64_t aTimestampOffset /* microseconds */);
|
||||
|
||||
// Evicts data held in the current decoders SourceBufferResource from the
|
||||
|
@ -133,7 +133,7 @@ private:
|
|||
|
||||
// Helper for AppendData, ensures NotifyDataArrived is called whenever
|
||||
// data is appended to the current decoder's SourceBufferResource.
|
||||
bool AppendDataToCurrentResource(LargeDataBuffer* aData,
|
||||
bool AppendDataToCurrentResource(MediaLargeByteBuffer* aData,
|
||||
uint32_t aDuration /* microseconds */);
|
||||
|
||||
// Queue execution of InitializeDecoder on mTaskQueue.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
Двоичный файл не отображается.
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче