mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 21:18:35 +00:00
Merge mozilla-central to fx-team
This commit is contained in:
commit
3009130936
@ -562,7 +562,12 @@ setUpdateTrackingId();
|
||||
enabled = Services.prefs.getBoolPref('layers.composer2d.enabled');
|
||||
} else {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
enabled = (libcutils.property_get('ro.display.colorfill') === '1');
|
||||
let androidVersion = libcutils.property_get("ro.build.version.sdk");
|
||||
if (androidVersion >= 17 ) {
|
||||
enabled = true;
|
||||
} else {
|
||||
enabled = (libcutils.property_get('ro.display.colorfill') === '1');
|
||||
}
|
||||
#endif
|
||||
}
|
||||
navigator.mozSettings.createLock().set({'layers.composer2d.enabled': enabled });
|
||||
|
@ -19,13 +19,13 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d5800c36b2d5822fc3fe1899b9280401de466e1e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
@ -17,10 +17,10 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -15,14 +15,14 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
||||
|
@ -19,13 +19,13 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d5800c36b2d5822fc3fe1899b9280401de466e1e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
@ -18,10 +18,10 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "95766b5f4b8108d3524431422ccf744e11797497",
|
||||
"revision": "3207323b68e65e12f8281ccb22e88fb3a59bb391",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -17,12 +17,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
@ -19,12 +19,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
<project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
|
||||
|
@ -17,12 +17,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
|
@ -17,10 +17,10 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -17,12 +17,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c1a8cbaac1d921cfb50e3a2600720b75cf5afabd"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e8a1eedb848382323254edbd234baecebc5dc5ca"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3512d982f336887a73283bb8d1147a8f7b822077"/>
|
||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
|
@ -6053,7 +6053,7 @@ function GetSearchFieldBookmarkData(node) {
|
||||
|
||||
|
||||
function AddKeywordForSearchField() {
|
||||
bookmarkData = GetSearchFieldBookmarkData(document.popupNode);
|
||||
bookmarkData = GetSearchFieldBookmarkData(gContextMenu.target);
|
||||
|
||||
PlacesUIUtils.showBookmarkDialog({ action: "add"
|
||||
, type: "bookmark"
|
||||
|
@ -814,7 +814,7 @@ class Automation(object):
|
||||
xrePath = None, certPath = None,
|
||||
debuggerInfo = None, symbolsPath = None,
|
||||
timeout = -1, maxTime = None, onLaunch = None,
|
||||
webapprtChrome = False, hide_subtests=None, screenshotOnFail=False):
|
||||
webapprtChrome = False, screenshotOnFail=False):
|
||||
"""
|
||||
Run the app, log the duration it took to execute, return the status code.
|
||||
Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
class nsIDocShell;
|
||||
class nsString;
|
||||
class nsCString;
|
||||
class nsIClassInfo;
|
||||
class nsIIOService;
|
||||
class nsIStringBundle;
|
||||
@ -139,9 +139,13 @@ private:
|
||||
inline void
|
||||
ScriptSecurityPrefChanged();
|
||||
|
||||
inline void
|
||||
AddSitesToFileURIWhitelist(const nsCString& aSiteList);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
|
||||
bool mPrefInitialized;
|
||||
bool mIsJavaScriptEnabled;
|
||||
nsTArray<nsCOMPtr<nsIURI>> mFileURIWhitelist;
|
||||
|
||||
// This machinery controls new-style domain policies. The old-style
|
||||
// policy machinery will be removed soon.
|
||||
|
@ -722,6 +722,14 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
&hasFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (hasFlags) {
|
||||
// Allow domains that were whitelisted in the prefs. In 99.9% of cases,
|
||||
// this array is empty.
|
||||
for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) {
|
||||
if (SecurityCompareURIs(mFileURIWhitelist[i], sourceURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// resource: and chrome: are equivalent, securitywise
|
||||
// That's bogus!! Fix this. But watch out for
|
||||
// the view-source stylesheet?
|
||||
@ -1142,6 +1150,7 @@ const char sFileOriginPolicyPrefName[] =
|
||||
static const char* kObservedPrefs[] = {
|
||||
sJSEnabledPrefName,
|
||||
sFileOriginPolicyPrefName,
|
||||
"capability.policy.",
|
||||
nullptr
|
||||
};
|
||||
|
||||
@ -1150,18 +1159,8 @@ NS_IMETHODIMP
|
||||
nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aTopic,
|
||||
const char16_t* aMessage)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
NS_ConvertUTF16toUTF8 messageStr(aMessage);
|
||||
const char *message = messageStr.get();
|
||||
|
||||
static const char jsPrefix[] = "javascript.";
|
||||
static const char securityPrefix[] = "security.";
|
||||
if ((PL_strncmp(message, jsPrefix, sizeof(jsPrefix)-1) == 0) ||
|
||||
(PL_strncmp(message, securityPrefix, sizeof(securityPrefix)-1) == 0) )
|
||||
{
|
||||
ScriptSecurityPrefChanged();
|
||||
}
|
||||
return rv;
|
||||
ScriptSecurityPrefChanged();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
@ -1270,26 +1269,98 @@ nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
|
||||
return static_cast<nsSystemPrincipal*>(sysprin);
|
||||
}
|
||||
|
||||
struct IsWhitespace {
|
||||
static bool Test(char aChar) { return NS_IsAsciiWhitespace(aChar); };
|
||||
};
|
||||
struct IsWhitespaceOrComma {
|
||||
static bool Test(char aChar) { return aChar == ',' || NS_IsAsciiWhitespace(aChar); };
|
||||
};
|
||||
|
||||
template <typename Predicate>
|
||||
uint32_t SkipPast(const nsCString& str, uint32_t base)
|
||||
{
|
||||
while (base < str.Length() && Predicate::Test(str[base])) {
|
||||
++base;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
template <typename Predicate>
|
||||
uint32_t SkipUntil(const nsCString& str, uint32_t base)
|
||||
{
|
||||
while (base < str.Length() && !Predicate::Test(str[base])) {
|
||||
++base;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
inline void
|
||||
nsScriptSecurityManager::ScriptSecurityPrefChanged()
|
||||
{
|
||||
// JavaScript defaults to enabled in failure cases.
|
||||
mIsJavaScriptEnabled = true;
|
||||
|
||||
sStrictFileOriginPolicy = true;
|
||||
|
||||
nsresult rv;
|
||||
if (!mPrefInitialized) {
|
||||
rv = InitPrefs();
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPrefInitialized);
|
||||
mIsJavaScriptEnabled =
|
||||
Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled);
|
||||
|
||||
sStrictFileOriginPolicy =
|
||||
Preferences::GetBool(sFileOriginPolicyPrefName, false);
|
||||
|
||||
//
|
||||
// Rebuild the set of principals for which we allow file:// URI loads. This
|
||||
// implements a small subset of an old pref-based CAPS people that people
|
||||
// have come to depend on. See bug 995943.
|
||||
//
|
||||
|
||||
mFileURIWhitelist.Clear();
|
||||
auto policies = mozilla::Preferences::GetCString("capability.policy.policynames");
|
||||
for (uint32_t base = SkipPast<IsWhitespaceOrComma>(policies, 0), bound = 0;
|
||||
base < policies.Length();
|
||||
base = SkipPast<IsWhitespaceOrComma>(policies, bound))
|
||||
{
|
||||
// Grab the current policy name.
|
||||
bound = SkipUntil<IsWhitespaceOrComma>(policies, base);
|
||||
auto policyName = Substring(policies, base, bound - base);
|
||||
|
||||
// Figure out if this policy allows loading file:// URIs. If not, we can skip it.
|
||||
nsCString checkLoadURIPrefName = NS_LITERAL_CSTRING("capability.policy.") +
|
||||
policyName +
|
||||
NS_LITERAL_CSTRING(".checkloaduri.enabled");
|
||||
if (!Preferences::GetString(checkLoadURIPrefName.get()).LowerCaseEqualsLiteral("allaccess")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Grab the list of domains associated with this policy.
|
||||
nsCString domainPrefName = NS_LITERAL_CSTRING("capability.policy.") +
|
||||
policyName +
|
||||
NS_LITERAL_CSTRING(".sites");
|
||||
auto siteList = Preferences::GetCString(domainPrefName.get());
|
||||
AddSitesToFileURIWhitelist(siteList);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList)
|
||||
{
|
||||
for (uint32_t base = SkipPast<IsWhitespace>(aSiteList, 0), bound = 0;
|
||||
base < aSiteList.Length();
|
||||
base = SkipPast<IsWhitespace>(aSiteList, bound))
|
||||
{
|
||||
// Grab the current site.
|
||||
bound = SkipUntil<IsWhitespace>(aSiteList, base);
|
||||
auto site = Substring(aSiteList, base, bound - base);
|
||||
|
||||
// Convert it to a URI and add it to our list.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), site, nullptr, nullptr, sIOService);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mFileURIWhitelist.AppendElement(uri);
|
||||
} else {
|
||||
nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1"));
|
||||
if (console) {
|
||||
nsAutoString msg = NS_LITERAL_STRING("Unable to to add site to file:// URI whitelist: ") +
|
||||
NS_ConvertASCIItoUTF16(site);
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -2,6 +2,7 @@
|
||||
support-files =
|
||||
file_disableScript.html
|
||||
|
||||
[test_bug995943.xul]
|
||||
[test_disableScript.xul]
|
||||
[test_principal_jarprefix_origin_appid_appstatus.html]
|
||||
# jarPrefix test doesn't work on Windows, see bug 776296.
|
||||
|
98
caps/tests/mochitest/test_bug995943.xul
Normal file
98
caps/tests/mochitest/test_bug995943.xul
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=995943
|
||||
-->
|
||||
<window title="Mozilla Bug 995943"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=995943"
|
||||
target="_blank">Mozilla Bug 995943</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
function debug(msg) { info(msg); }
|
||||
|
||||
/** Test for CAPS file:// URI prefs. **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var profileDir = "file://" + Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties)
|
||||
.get("ProfD", Ci.nsILocalFile).path;
|
||||
|
||||
function checkLoadFileURI(domain, shouldLoad) {
|
||||
debug("Invoking checkLoadFileURI with domain: " + domain + ", shouldLoad: " + shouldLoad);
|
||||
return new Promise(function(resolve, reject) {
|
||||
$('ifr').addEventListener('load', function l1() {
|
||||
$('ifr').removeEventListener('load', l1);
|
||||
function l2() {
|
||||
$('ifr').removeEventListener('load', l2);
|
||||
ok(shouldLoad, "Successfully loaded file:// URI for domain: " + domain);
|
||||
resolve();
|
||||
}
|
||||
$('ifr').addEventListener('load', l2);
|
||||
try {
|
||||
window[0].wrappedJSObject.location = profileDir;
|
||||
} catch (e) {
|
||||
ok(!shouldLoad && /denied|insecure/.test(e),
|
||||
"Prevented loading of file:// URI for domain: " + domain + " - " + e);
|
||||
$('ifr').removeEventListener('load', l2);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
let targetURI = domain + '/tests/js/xpconnect/tests/mochitest/file_empty.html';
|
||||
debug("Navigating iframe to " + targetURI);
|
||||
$('ifr').contentWindow.location = targetURI;
|
||||
});
|
||||
}
|
||||
|
||||
function pushPrefs(prefs) {
|
||||
return new Promise(function(resolve) { SpecialPowers.pushPrefEnv({ set: prefs }, resolve); });
|
||||
}
|
||||
|
||||
function popPrefs() {
|
||||
return new Promise(function(resolve) { SpecialPowers.popPrefEnv(resolve); });
|
||||
}
|
||||
|
||||
function go() {
|
||||
checkLoadFileURI('http://example.com', false).then(
|
||||
pushPrefs.bind(null, [['capability.policy.policynames', ' somepolicy '],
|
||||
['capability.policy.somepolicy.checkloaduri.enabled', 'AlLAcCeSs'],
|
||||
['capability.policy.somepolicy.sites', 'http://example.com']]))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.com', true))
|
||||
.then(popPrefs)
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.com', false))
|
||||
.then(
|
||||
pushPrefs.bind(null, [['capability.policy.policynames', ',somepolicy, someotherpolicy, '],
|
||||
['capability.policy.somepolicy.checkloaduri.enabled', 'allaccess'],
|
||||
['capability.policy.someotherpolicy.checkloaduri.enabled', 'nope'],
|
||||
['capability.policy.somepolicy.sites', ' http://example.org https://example.com'],
|
||||
['capability.policy.someotherpolicy.sites', 'http://example.net ']]))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.org', true))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.com', false))
|
||||
.then(checkLoadFileURI.bind(null, 'https://example.com', true))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.net', false))
|
||||
.then(pushPrefs.bind(null, [['capability.policy.someotherpolicy.checkloaduri.enabled', 'allAccess']]))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.net', true))
|
||||
.then(popPrefs)
|
||||
.then(popPrefs)
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.net', false))
|
||||
.then(SimpleTest.finish.bind(SimpleTest));
|
||||
|
||||
}
|
||||
addLoadEvent(go);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
<iframe id="ifr" type="content" />
|
||||
</window>
|
@ -21,11 +21,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=758258
|
||||
/** Test for Bug 758258 **/
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
if (navigator.platform.startsWith("Mac")) {
|
||||
SimpleTest.expectAssertions(2);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/*
|
||||
|
28
configure.in
28
configure.in
@ -5790,16 +5790,22 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
|
||||
if test -n "$WINDOWSSDKDIR"; then
|
||||
MOZ_D3DCOMPILER_VISTA_DLL_PATH="$WINDOWSSDKDIR/Redist/D3D/$MOZ_D3D_CPU_SUFFIX/$MOZ_D3DCOMPILER_VISTA_DLL"
|
||||
if test -f "$MOZ_D3DCOMPILER_VISTA_DLL_PATH"; then
|
||||
MOZ_HAS_WINSDK_WITH_D3D=1
|
||||
AC_MSG_RESULT([Found MOZ_D3DCOMPILER_VISTA_DLL_PATH: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
|
||||
MOZ_HAS_WINSDK_WITH_D3D=1
|
||||
else
|
||||
AC_MSG_RESULT([MOZ_D3DCOMPILER_VISTA_DLL_PATH doesn't exist: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
|
||||
AC_MSG_ERROR([Windows SDK at "$WINDOWSSDKDIR" appears broken. Try updating to MozillaBuild 1.9 final or higher.])
|
||||
MOZ_D3DCOMPILER_VISTA_DLL_PATH=
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([WINDOWSSDKDIR is missing.])
|
||||
AC_MSG_RESULT([Windows SDK not found.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$MOZ_D3DCOMPILER_VISTA_DLL_PATH"; then
|
||||
MOZ_D3DCOMPILER_VISTA_DLL=
|
||||
fi
|
||||
|
||||
######################################
|
||||
# Find _43 for use by XP.
|
||||
|
||||
@ -5816,7 +5822,7 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
|
||||
test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_D3D_CPU_SUFFIX/dxguid.lib ; then
|
||||
AC_MSG_RESULT([Found DirectX SDK via registry, using $MOZ_DIRECTX_SDK_PATH])
|
||||
else
|
||||
AC_MSG_RESULT([Couldn't find the DirectX SDK.])
|
||||
AC_MSG_RESULT([DirectX SDK not found.])
|
||||
MOZ_DIRECTX_SDK_PATH=
|
||||
fi
|
||||
|
||||
@ -5835,21 +5841,21 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
|
||||
|
||||
if test -n "$MOZ_D3DX9_VERSION" ; then
|
||||
MOZ_D3DCOMPILER_XP_CAB=`find "$MOZ_DIRECTX_SDK_PATH"/Redist -name *D3DCompiler_${MOZ_D3DX9_VERSION}_${MOZ_D3D_CPU_SUFFIX}.cab | head -n1`
|
||||
MOZ_D3DCOMPILER_XP_DLL=D3DCompiler_$MOZ_D3DX9_VERSION.dll
|
||||
|
||||
if test -n "$MOZ_D3DCOMPILER_XP_CAB"; then
|
||||
MOZ_D3DCOMPILER_XP_DLL=D3DCompiler_$MOZ_D3DX9_VERSION.dll
|
||||
else
|
||||
AC_MSG_RESULT([Couldn't find a CAB containing the D3D compiler DLL.])
|
||||
AC_MSG_ERROR([DirectX SDK at "$MOZ_DIRECTX_SDK_PATH" appears broken.])
|
||||
MOZ_DIRECTX_SDK_PATH=
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([Couldn't determine the D3DX9 version for the DirectX SDK.])
|
||||
fi
|
||||
|
||||
if test -z "$MOZ_D3DCOMPILER_XP_CAB"; then
|
||||
AC_MSG_RESULT([Couldn't find a CAB containing the D3D compiler DLL.])
|
||||
MOZ_DIRECTX_SDK_PATH=
|
||||
MOZ_D3DCOMPILER_XP_DLL=
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([Couldn't find an acceptable DirectX SDK for ANGLE, needed for d3dcompiler_43.])
|
||||
AC_MSG_RESULT([ Either ignore, install DirectX SDK (June 2010 version or newer), or reconfigure with --disable-webgl.])
|
||||
MOZ_DIRECTX_SDK_PATH=
|
||||
MOZ_D3DCOMPILER_XP_DLL=
|
||||
fi
|
||||
|
||||
######################################
|
||||
|
@ -49,6 +49,7 @@ class nsIScrollableFrame;
|
||||
class nsAttrValueOrString;
|
||||
class ContentUnbinder;
|
||||
class nsContentList;
|
||||
class nsDOMSettableTokenList;
|
||||
class nsDOMTokenList;
|
||||
struct nsRect;
|
||||
class nsFocusManager;
|
||||
@ -1164,6 +1165,10 @@ protected:
|
||||
*/
|
||||
virtual void GetLinkTarget(nsAString& aTarget);
|
||||
|
||||
nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom);
|
||||
void GetTokenList(nsIAtom* aAtom, nsIVariant** aResult);
|
||||
nsresult SetTokenList(nsIAtom* aAtom, nsIVariant* aValue);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get this element's client area rect in app units.
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "nsDOMCSSAttrDeclaration.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsDOMSettableTokenList.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsError.h"
|
||||
@ -2526,6 +2528,81 @@ Element::GetLinkTarget(nsAString& aTarget)
|
||||
aTarget.Truncate();
|
||||
}
|
||||
|
||||
static void
|
||||
nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
||||
void *aPropertyValue, void *aData)
|
||||
{
|
||||
nsDOMSettableTokenList* list =
|
||||
static_cast<nsDOMSettableTokenList*>(aPropertyValue);
|
||||
NS_RELEASE(list);
|
||||
}
|
||||
|
||||
static nsIAtom** sPropertiesToTraverseAndUnlink[] =
|
||||
{
|
||||
&nsGkAtoms::microdataProperties,
|
||||
&nsGkAtoms::itemtype,
|
||||
&nsGkAtoms::itemref,
|
||||
&nsGkAtoms::itemprop,
|
||||
&nsGkAtoms::sandbox,
|
||||
&nsGkAtoms::sizes,
|
||||
nullptr
|
||||
};
|
||||
|
||||
// static
|
||||
nsIAtom***
|
||||
nsGenericHTMLElement::PropertiesToTraverseAndUnlink()
|
||||
{
|
||||
return sPropertiesToTraverseAndUnlink;
|
||||
}
|
||||
|
||||
nsDOMSettableTokenList*
|
||||
Element::GetTokenList(nsIAtom* aAtom)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsIAtom*** props =
|
||||
nsGenericHTMLElement::PropertiesToTraverseAndUnlink();
|
||||
bool found = false;
|
||||
for (uint32_t i = 0; props[i]; ++i) {
|
||||
if (*props[i] == aAtom) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
|
||||
#endif
|
||||
|
||||
nsDOMSettableTokenList* list = nullptr;
|
||||
if (HasProperties()) {
|
||||
list = static_cast<nsDOMSettableTokenList*>(GetProperty(aAtom));
|
||||
}
|
||||
if (!list) {
|
||||
list = new nsDOMSettableTokenList(this, aAtom);
|
||||
NS_ADDREF(list);
|
||||
SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
Element::GetTokenList(nsIAtom* aAtom, nsIVariant** aResult)
|
||||
{
|
||||
nsISupports* itemType = GetTokenList(aAtom);
|
||||
nsCOMPtr<nsIWritableVariant> out = new nsVariant();
|
||||
out->SetAsInterface(NS_GET_IID(nsISupports), itemType);
|
||||
out.forget(aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Element::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue)
|
||||
{
|
||||
nsDOMSettableTokenList* itemType = GetTokenList(aAtom);
|
||||
nsAutoString string;
|
||||
aValue->GetAsAString(string);
|
||||
ErrorResult rv;
|
||||
itemType->SetValue(string, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
bool
|
||||
Element::MozMatchesSelector(const nsAString& aSelector,
|
||||
ErrorResult& aError)
|
||||
|
@ -16,6 +16,7 @@ EXPORTS += [
|
||||
'nsContentSink.h',
|
||||
'nsCrossSiteListenerProxy.h',
|
||||
'nsDOMAttributeMap.h',
|
||||
'nsElementFrameLoaderOwner.h',
|
||||
'nsFrameMessageManager.h',
|
||||
'nsGenericDOMDataNode.h',
|
||||
'nsGkAtomList.h',
|
||||
@ -121,6 +122,7 @@ UNIFIED_SOURCES += [
|
||||
'nsDOMSerializer.cpp',
|
||||
'nsDOMSettableTokenList.cpp',
|
||||
'nsDOMTokenList.cpp',
|
||||
'nsElementFrameLoaderOwner.cpp',
|
||||
'nsFormData.cpp',
|
||||
'nsFrameLoader.cpp',
|
||||
'nsFrameMessageManager.cpp',
|
||||
@ -130,7 +132,6 @@ UNIFIED_SOURCES += [
|
||||
'nsHostObjectProtocolHandler.cpp',
|
||||
'nsHostObjectURI.cpp',
|
||||
'nsHTMLContentSerializer.cpp',
|
||||
'nsImageLoadingContent.cpp',
|
||||
'nsINode.cpp',
|
||||
'nsInProcessTabChildGlobal.cpp',
|
||||
'nsLineBreaker.cpp',
|
||||
@ -169,6 +170,10 @@ UNIFIED_SOURCES += [
|
||||
'WebSocket.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'nsImageLoadingContent.cpp',
|
||||
]
|
||||
|
||||
# These files cannot be built in unified mode because they use FORCE_PR_LOG
|
||||
SOURCES += [
|
||||
'nsDocument.cpp',
|
||||
|
@ -315,6 +315,13 @@ struct FireChangeArgs {
|
||||
bool mHaveImageOverride;
|
||||
};
|
||||
|
||||
// XXX Workaround for bug 980560 to maintain the existing broken semantics
|
||||
template<>
|
||||
struct nsIStyleRule::COMTypeInfo<css::Rule, void> {
|
||||
static const nsIID kIID NS_HIDDEN;
|
||||
};
|
||||
const nsIID nsIStyleRule::COMTypeInfo<css::Rule, void>::kIID = NS_ISTYLE_RULE_IID;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
160
content/base/src/nsElementFrameLoaderOwner.cpp
Normal file
160
content/base/src/nsElementFrameLoaderOwner.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
|
||||
|
||||
/* 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 "nsElementFrameLoaderOwner.h"
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozIApplication.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
nsElementFrameLoaderOwner::~nsElementFrameLoaderOwner()
|
||||
{
|
||||
if (mFrameLoader) {
|
||||
mFrameLoader->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsElementFrameLoaderOwner::GetContentDocument(nsIDOMDocument** aContentDocument)
|
||||
{
|
||||
NS_PRECONDITION(aContentDocument, "Null out param");
|
||||
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetContentDocument());
|
||||
document.forget(aContentDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsElementFrameLoaderOwner::GetContentDocument()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetContentWindow();
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIDocument *doc = win->GetDoc();
|
||||
|
||||
// Return null for cross-origin contentDocument.
|
||||
if (!nsContentUtils::GetSubjectPrincipal()->
|
||||
SubsumesConsideringDomain(doc->NodePrincipal())) {
|
||||
return nullptr;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsElementFrameLoaderOwner::GetContentWindow(nsIDOMWindow** aContentWindow)
|
||||
{
|
||||
NS_PRECONDITION(aContentWindow, "Null out param");
|
||||
nsCOMPtr<nsPIDOMWindow> window = GetContentWindow();
|
||||
window.forget(aContentWindow);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsPIDOMWindow>
|
||||
nsElementFrameLoaderOwner::GetContentWindow()
|
||||
{
|
||||
EnsureFrameLoader();
|
||||
|
||||
if (!mFrameLoader) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool depthTooGreat = false;
|
||||
mFrameLoader->GetDepthTooGreat(&depthTooGreat);
|
||||
if (depthTooGreat) {
|
||||
// Claim to have no contentWindow
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> doc_shell;
|
||||
mFrameLoader->GetDocShell(getter_AddRefs(doc_shell));
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(doc_shell);
|
||||
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_ASSERTION(win->IsOuterWindow(),
|
||||
"Uh, this window should always be an outer window!");
|
||||
|
||||
return win.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsElementFrameLoaderOwner::EnsureFrameLoader()
|
||||
{
|
||||
Element* thisElement = ThisFrameElement();
|
||||
if (!thisElement->GetParent() ||
|
||||
!thisElement->IsInDoc() ||
|
||||
mFrameLoader ||
|
||||
mFrameLoaderCreationDisallowed) {
|
||||
// If frame loader is there, we just keep it around, cached
|
||||
return;
|
||||
}
|
||||
|
||||
// Strangely enough, this method doesn't actually ensure that the
|
||||
// frameloader exists. It's more of a best-effort kind of thing.
|
||||
mFrameLoader = nsFrameLoader::Create(thisElement, mNetworkCreated);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsElementFrameLoaderOwner::GetFrameLoader(nsIFrameLoader **aFrameLoader)
|
||||
{
|
||||
NS_IF_ADDREF(*aFrameLoader = mFrameLoader);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
|
||||
nsElementFrameLoaderOwner::GetFrameLoader()
|
||||
{
|
||||
nsRefPtr<nsFrameLoader> loader = mFrameLoader;
|
||||
return loader.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsElementFrameLoaderOwner::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
|
||||
{
|
||||
// We don't support this yet
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsElementFrameLoaderOwner::LoadSrc()
|
||||
{
|
||||
EnsureFrameLoader();
|
||||
|
||||
if (!mFrameLoader) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mFrameLoader->LoadFrame();
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to load URL");
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsElementFrameLoaderOwner::SwapFrameLoaders(nsXULElement& aOtherOwner,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
77
content/base/src/nsElementFrameLoaderOwner.h
Normal file
77
content/base/src/nsElementFrameLoaderOwner.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
|
||||
|
||||
/* 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 nsElementFrameLoaderOwner_h
|
||||
#define nsElementFrameLoaderOwner_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIFrameLoader.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "mozilla/dom/FromParser.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
#include "nsFrameLoader.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsXULElement;
|
||||
|
||||
/**
|
||||
* A helper class for frame elements
|
||||
*/
|
||||
class nsElementFrameLoaderOwner : public nsIFrameLoaderOwner
|
||||
{
|
||||
public:
|
||||
nsElementFrameLoaderOwner(mozilla::dom::FromParser aFromParser)
|
||||
: mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
|
||||
, mBrowserFrameListenersRegistered(false)
|
||||
, mFrameLoaderCreationDisallowed(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsElementFrameLoaderOwner();
|
||||
|
||||
NS_DECL_NSIFRAMELOADEROWNER
|
||||
|
||||
// nsIContent
|
||||
void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aError);
|
||||
|
||||
protected:
|
||||
// This doesn't really ensure a frame loader in all cases, only when
|
||||
// it makes sense.
|
||||
void EnsureFrameLoader();
|
||||
nsresult LoadSrc();
|
||||
nsIDocument* GetContentDocument();
|
||||
nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
|
||||
already_AddRefed<nsPIDOMWindow> GetContentWindow();
|
||||
nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
|
||||
|
||||
/**
|
||||
* Get element for this frame. Avoids diamond inheritance problem.
|
||||
* @return Element for this node
|
||||
*/
|
||||
virtual mozilla::dom::Element* ThisFrameElement() = 0;
|
||||
|
||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||
|
||||
/**
|
||||
* True when the element is created by the parser using the
|
||||
* NS_FROM_PARSER_NETWORK flag.
|
||||
* If the element is modified, it may lose the flag.
|
||||
*/
|
||||
bool mNetworkCreated;
|
||||
|
||||
bool mBrowserFrameListenersRegistered;
|
||||
bool mFrameLoaderCreationDisallowed;
|
||||
};
|
||||
|
||||
#endif // nsElementFrameLoaderOwner_h
|
@ -86,6 +86,7 @@
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/HTMLIFrameElement.h"
|
||||
#include "mozilla/dom/SVGIFrameElement.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "JavaScriptParent.h"
|
||||
|
||||
@ -318,7 +319,8 @@ nsFrameLoader::LoadFrame()
|
||||
|
||||
nsAutoString src;
|
||||
|
||||
bool isSrcdoc = mOwnerContent->IsHTML(nsGkAtoms::iframe) &&
|
||||
bool isSrcdoc = (mOwnerContent->IsHTML(nsGkAtoms::iframe) ||
|
||||
mOwnerContent->IsSVG(nsGkAtoms::iframe)) &&
|
||||
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
|
||||
if (isSrcdoc) {
|
||||
src.AssignLiteral("about:srcdoc");
|
||||
@ -518,7 +520,8 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
|
||||
nsAutoString srcdoc;
|
||||
bool isSrcdoc = mOwnerContent->IsHTML(nsGkAtoms::iframe) &&
|
||||
bool isSrcdoc = (mOwnerContent->IsHTML(nsGkAtoms::iframe) ||
|
||||
mOwnerContent->IsSVG(nsGkAtoms::iframe)) &&
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
|
||||
srcdoc);
|
||||
|
||||
@ -1603,8 +1606,13 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
// Apply sandbox flags even if our owner is not an iframe, as this copies
|
||||
// flags from our owning content's owning document.
|
||||
uint32_t sandboxFlags = 0;
|
||||
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
|
||||
if (iframe) {
|
||||
if (!mOwnerContent->IsSVG(nsGkAtoms::iframe)) {
|
||||
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
|
||||
if (iframe) {
|
||||
sandboxFlags = iframe->GetSandboxFlags();
|
||||
}
|
||||
} else {
|
||||
SVGIFrameElement* iframe = static_cast<SVGIFrameElement*>(mOwnerContent);
|
||||
sandboxFlags = iframe->GetSandboxFlags();
|
||||
}
|
||||
ApplySandboxFlags(sandboxFlags);
|
||||
@ -1620,7 +1628,8 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
nsAutoString frameName;
|
||||
|
||||
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
|
||||
if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
|
||||
if ((namespaceID == kNameSpaceID_XHTML || namespaceID == kNameSpaceID_SVG)
|
||||
&& !mOwnerContent->IsInHTMLDocument()) {
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
|
||||
} else {
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);
|
||||
|
@ -795,6 +795,7 @@ GK_ATOM(onreadystatechange, "onreadystatechange")
|
||||
GK_ATOM(onreceived, "onreceived")
|
||||
GK_ATOM(onremoteheld, "onremoteheld")
|
||||
GK_ATOM(onremoteresumed, "onremoteresumed")
|
||||
GK_ATOM(onresourcetimingbufferfull, "onresourcetimingbufferfull")
|
||||
GK_ATOM(onretrieving, "onretrieving")
|
||||
GK_ATOM(onRequest, "onRequest")
|
||||
GK_ATOM(onrequestmediaplaystatus, "onrequestmediaplaystatus")
|
||||
|
@ -174,7 +174,7 @@ int main(int argc, char *argv[])
|
||||
// us some comfort margin.
|
||||
int repeat = std::min(maxBufferSize, 64);
|
||||
for (int i = 0; i < repeat; i++) {
|
||||
size_t size = RandomInteger<size_t>(1, maxBufferSize);
|
||||
size_t size = RandomInteger<size_t>(0, maxBufferSize);
|
||||
MakeRandomVector(v, size);
|
||||
b.BufferData(v.Elements(), size);
|
||||
CheckValidate(b, 0, size);
|
||||
|
@ -124,21 +124,13 @@ UpdateUpperBound(uint32_t* out_upperBound, uint32_t newBound)
|
||||
* case where each element array buffer is only ever used with one type, this is also addressed
|
||||
* by having WebGLElementArrayCache lazily create trees for each type only upon first use.
|
||||
*
|
||||
* Another consequence of this constraint is that when invalidating the trees, we have to invalidate
|
||||
* Another consequence of this constraint is that when updating the trees, we have to update
|
||||
* all existing trees. So if trees for types uint8_t, uint16_t and uint32_t have ever been constructed for this buffer,
|
||||
* every subsequent invalidation will have to invalidate all trees even if one of the types is never
|
||||
* used again. This implies that it is important to minimize the cost of invalidation i.e.
|
||||
* do lazy updates upon use as opposed to immediately updating invalidated trees. This poses a problem:
|
||||
* it is nontrivial to keep track of the part of the tree that's invalidated. The current solution
|
||||
* can only keep track of an invalidated interval, from |mFirstInvalidatedLeaf| to |mLastInvalidatedLeaf|.
|
||||
* The problem is that if one does two small, far-apart partial buffer updates, the resulting invalidated
|
||||
* area is very large even though only a small part of the array really needed to be invalidated.
|
||||
* The real solution to this problem would be to use a smarter data structure to keep track of the
|
||||
* invalidated area, probably an interval tree. Meanwhile, we can probably live with the current situation
|
||||
* as the unfavorable case seems to be a small corner case: in order to run into performance issues,
|
||||
* the number of bufferSubData in between two consecutive draws must be small but greater than 1, and
|
||||
* the partial buffer updates must be small and far apart. Anything else than this corner case
|
||||
* should run fast in the current setting.
|
||||
* every subsequent update will have to update all trees even if one of the types is never
|
||||
* used again. That's inefficient, but content should not put indices of different types in the
|
||||
* same element array buffer anyways. Different index types can only be consumed in separate
|
||||
* drawElements calls, so nothing particular is to be achieved by lumping them in the same
|
||||
* buffer object.
|
||||
*/
|
||||
template<typename T>
|
||||
struct WebGLElementArrayCacheTree
|
||||
@ -154,23 +146,20 @@ private:
|
||||
WebGLElementArrayCache& mParent;
|
||||
FallibleTArray<T> mTreeData;
|
||||
size_t mNumLeaves;
|
||||
bool mInvalidated;
|
||||
size_t mFirstInvalidatedLeaf;
|
||||
size_t mLastInvalidatedLeaf;
|
||||
size_t mParentByteSize;
|
||||
|
||||
public:
|
||||
WebGLElementArrayCacheTree(WebGLElementArrayCache& p)
|
||||
: mParent(p)
|
||||
, mNumLeaves(0)
|
||||
, mInvalidated(false)
|
||||
, mFirstInvalidatedLeaf(0)
|
||||
, mLastInvalidatedLeaf(0)
|
||||
, mParentByteSize(0)
|
||||
{
|
||||
ResizeToParentSize();
|
||||
if (mParent.ByteSize()) {
|
||||
Update(0, mParent.ByteSize() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
T GlobalMaximum() const {
|
||||
MOZ_ASSERT(!mInvalidated);
|
||||
return mTreeData[1];
|
||||
}
|
||||
|
||||
@ -242,14 +231,13 @@ public:
|
||||
}
|
||||
|
||||
static size_t NextMultipleOfElementsPerLeaf(size_t numElements) {
|
||||
MOZ_ASSERT(numElements >= 1);
|
||||
return ((numElements - 1) | sElementsPerLeafMask) + 1;
|
||||
}
|
||||
|
||||
bool Validate(T maxAllowed, size_t firstLeaf, size_t lastLeaf,
|
||||
uint32_t* out_upperBound)
|
||||
{
|
||||
MOZ_ASSERT(!mInvalidated);
|
||||
|
||||
size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
|
||||
size_t lastTreeIndex = TreeIndexForLeaf(lastLeaf);
|
||||
|
||||
@ -310,28 +298,7 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ResizeToParentSize()
|
||||
{
|
||||
size_t numberOfElements = mParent.ByteSize() / sizeof(T);
|
||||
size_t requiredNumLeaves = (numberOfElements + sElementsPerLeaf - 1) / sElementsPerLeaf;
|
||||
|
||||
size_t oldNumLeaves = mNumLeaves;
|
||||
mNumLeaves = NextPowerOfTwo(requiredNumLeaves);
|
||||
Invalidate(0, mParent.ByteSize() - 1);
|
||||
|
||||
// see class comment for why we the tree storage size is 2 * mNumLeaves
|
||||
if (!mTreeData.SetLength(2 * mNumLeaves)) {
|
||||
return false;
|
||||
}
|
||||
if (mNumLeaves != oldNumLeaves) {
|
||||
memset(mTreeData.Elements(), 0, mTreeData.Length() * sizeof(mTreeData[0]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Invalidate(size_t firstByte, size_t lastByte);
|
||||
|
||||
void Update();
|
||||
bool Update(size_t firstByte, size_t lastByte);
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
@ -362,44 +329,53 @@ struct TreeForType<uint32_t>
|
||||
static WebGLElementArrayCacheTree<uint32_t>*& Run(WebGLElementArrayCache *b) { return b->mUint32Tree; }
|
||||
};
|
||||
|
||||
// When the buffer gets updated from firstByte to lastByte,
|
||||
// calling this method will notify the tree accordingly
|
||||
// Calling this method will 1) update the leaves in this interval
|
||||
// from the raw buffer data, and 2) propagate this update up the tree
|
||||
template<typename T>
|
||||
void WebGLElementArrayCacheTree<T>::Invalidate(size_t firstByte, size_t lastByte)
|
||||
bool WebGLElementArrayCacheTree<T>::Update(size_t firstByte, size_t lastByte)
|
||||
{
|
||||
MOZ_ASSERT(firstByte <= lastByte);
|
||||
MOZ_ASSERT(lastByte < mParent.ByteSize());
|
||||
|
||||
// Step #0: if needed, resize our tree data storage.
|
||||
if (mParentByteSize != mParent.ByteSize())
|
||||
{
|
||||
size_t numberOfElements = mParent.ByteSize() / sizeof(T);
|
||||
if (numberOfElements == 0) {
|
||||
mParentByteSize = mParent.ByteSize();
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t requiredNumLeaves = (numberOfElements + sElementsPerLeaf - 1) / sElementsPerLeaf;
|
||||
size_t oldNumLeaves = mNumLeaves;
|
||||
mNumLeaves = NextPowerOfTwo(requiredNumLeaves);
|
||||
if (mNumLeaves != oldNumLeaves) {
|
||||
// see class comment for why we the tree storage size is 2 * mNumLeaves
|
||||
if (!mTreeData.SetLength(2 * mNumLeaves)) {
|
||||
return false;
|
||||
}
|
||||
// when resizing, update the whole tree, not just the subset corresponding
|
||||
// to the part of the buffer being updated.
|
||||
memset(mTreeData.Elements(), 0, mTreeData.Length() * sizeof(T));
|
||||
firstByte = 0;
|
||||
lastByte = mParent.ByteSize() - 1;
|
||||
}
|
||||
|
||||
mParentByteSize = mParent.ByteSize();
|
||||
}
|
||||
|
||||
lastByte = std::min(lastByte, mNumLeaves * sElementsPerLeaf * sizeof(T) - 1);
|
||||
if (firstByte > lastByte) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t firstLeaf = LeafForByte(firstByte);
|
||||
size_t lastLeaf = LeafForByte(lastByte);
|
||||
|
||||
if (mInvalidated) {
|
||||
mFirstInvalidatedLeaf = std::min(firstLeaf, mFirstInvalidatedLeaf);
|
||||
mLastInvalidatedLeaf = std::max(lastLeaf, mLastInvalidatedLeaf);
|
||||
} else {
|
||||
mInvalidated = true;
|
||||
mFirstInvalidatedLeaf = firstLeaf;
|
||||
mLastInvalidatedLeaf = lastLeaf;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(firstLeaf <= lastLeaf && lastLeaf < mNumLeaves);
|
||||
|
||||
|
||||
// When tree has been partially invalidated, from mFirstInvalidatedLeaf to
|
||||
// mLastInvalidatedLeaf, calling this method will 1) update the leaves in this interval
|
||||
// from the raw buffer data, and 2) propagate this update up the tree
|
||||
template<typename T>
|
||||
void WebGLElementArrayCacheTree<T>::Update()
|
||||
{
|
||||
if (!mInvalidated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mLastInvalidatedLeaf < mNumLeaves);
|
||||
|
||||
size_t firstTreeIndex = TreeIndexForLeaf(mFirstInvalidatedLeaf);
|
||||
size_t lastTreeIndex = TreeIndexForLeaf(mLastInvalidatedLeaf);
|
||||
size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
|
||||
size_t lastTreeIndex = TreeIndexForLeaf(lastLeaf);
|
||||
|
||||
// Step #1: initialize the tree leaves from plain buffer data.
|
||||
// That is, each tree leaf must be set to the max of the |sElementsPerLeaf| corresponding
|
||||
@ -409,8 +385,8 @@ void WebGLElementArrayCacheTree<T>::Update()
|
||||
// treeIndex is the index of the tree leaf we're writing, i.e. the destination index
|
||||
size_t treeIndex = firstTreeIndex;
|
||||
// srcIndex is the index in the source buffer
|
||||
size_t srcIndex = mFirstInvalidatedLeaf * sElementsPerLeaf;
|
||||
size_t numberOfElements = mParent.ByteSize() / sizeof(T);
|
||||
size_t srcIndex = firstLeaf * sElementsPerLeaf;
|
||||
size_t numberOfElements = mParentByteSize / sizeof(T);
|
||||
while (treeIndex <= lastTreeIndex) {
|
||||
T m = 0;
|
||||
size_t a = srcIndex;
|
||||
@ -426,12 +402,11 @@ void WebGLElementArrayCacheTree<T>::Update()
|
||||
// Step #2: propagate the values up the tree. This is simply a matter of walking up
|
||||
// the tree and setting each node to the max of its two children.
|
||||
while (firstTreeIndex > 1) {
|
||||
|
||||
// move up 1 level
|
||||
firstTreeIndex = ParentNode(firstTreeIndex);
|
||||
lastTreeIndex = ParentNode(lastTreeIndex);
|
||||
|
||||
// fast-exit case where only one node is invalidated at the current level
|
||||
// fast-exit case where only one node is updated at the current level
|
||||
if (firstTreeIndex == lastTreeIndex) {
|
||||
mTreeData[firstTreeIndex] = std::max(mTreeData[LeftChildNode(firstTreeIndex)], mTreeData[RightChildNode(firstTreeIndex)]);
|
||||
continue;
|
||||
@ -468,7 +443,7 @@ void WebGLElementArrayCacheTree<T>::Update()
|
||||
}
|
||||
}
|
||||
|
||||
mInvalidated = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
WebGLElementArrayCache::~WebGLElementArrayCache() {
|
||||
@ -479,40 +454,43 @@ WebGLElementArrayCache::~WebGLElementArrayCache() {
|
||||
}
|
||||
|
||||
bool WebGLElementArrayCache::BufferData(const void* ptr, size_t byteSize) {
|
||||
mByteSize = byteSize;
|
||||
if (mUint8Tree)
|
||||
if (!mUint8Tree->ResizeToParentSize())
|
||||
if (byteSize == 0) {
|
||||
mByteSize = 0;
|
||||
free(mUntypedData);
|
||||
mUntypedData = nullptr;
|
||||
return true;
|
||||
}
|
||||
if (byteSize != mByteSize) {
|
||||
void* newUntypedData = realloc(mUntypedData, byteSize);
|
||||
if (!newUntypedData)
|
||||
return false;
|
||||
if (mUint16Tree)
|
||||
if (!mUint16Tree->ResizeToParentSize())
|
||||
return false;
|
||||
if (mUint32Tree)
|
||||
if (!mUint32Tree->ResizeToParentSize())
|
||||
return false;
|
||||
mUntypedData = realloc(mUntypedData, byteSize);
|
||||
if (!mUntypedData)
|
||||
return false;
|
||||
mByteSize = byteSize;
|
||||
mUntypedData = newUntypedData;
|
||||
}
|
||||
|
||||
BufferSubData(0, ptr, byteSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebGLElementArrayCache::BufferSubData(size_t pos, const void* ptr, size_t updateByteSize) {
|
||||
if (!updateByteSize) return;
|
||||
bool WebGLElementArrayCache::BufferSubData(size_t pos, const void* ptr, size_t updateByteSize) {
|
||||
if (!updateByteSize) return true;
|
||||
if (ptr)
|
||||
memcpy(static_cast<uint8_t*>(mUntypedData) + pos, ptr, updateByteSize);
|
||||
else
|
||||
memset(static_cast<uint8_t*>(mUntypedData) + pos, 0, updateByteSize);
|
||||
InvalidateTrees(pos, pos + updateByteSize - 1);
|
||||
return UpdateTrees(pos, pos + updateByteSize - 1);
|
||||
}
|
||||
|
||||
void WebGLElementArrayCache::InvalidateTrees(size_t firstByte, size_t lastByte)
|
||||
bool WebGLElementArrayCache::UpdateTrees(size_t firstByte, size_t lastByte)
|
||||
{
|
||||
bool result = true;
|
||||
if (mUint8Tree)
|
||||
mUint8Tree->Invalidate(firstByte, lastByte);
|
||||
result &= mUint8Tree->Update(firstByte, lastByte);
|
||||
if (mUint16Tree)
|
||||
mUint16Tree->Invalidate(firstByte, lastByte);
|
||||
result &= mUint16Tree->Update(firstByte, lastByte);
|
||||
if (mUint32Tree)
|
||||
mUint32Tree->Invalidate(firstByte, lastByte);
|
||||
result &= mUint32Tree->Update(firstByte, lastByte);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -545,8 +523,6 @@ WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement,
|
||||
|
||||
size_t lastElement = firstElement + countElements - 1;
|
||||
|
||||
tree->Update();
|
||||
|
||||
// fast exit path when the global maximum for the whole element array buffer
|
||||
// falls in the allowed range
|
||||
T globalMax = tree->GlobalMaximum();
|
||||
|
@ -31,7 +31,7 @@ class WebGLElementArrayCache {
|
||||
|
||||
public:
|
||||
bool BufferData(const void* ptr, size_t byteSize);
|
||||
void BufferSubData(size_t pos, const void* ptr, size_t updateByteSize);
|
||||
bool BufferSubData(size_t pos, const void* ptr, size_t updateByteSize);
|
||||
|
||||
bool Validate(GLenum type, uint32_t maxAllowed, size_t first, size_t count,
|
||||
uint32_t* out_upperBound = nullptr);
|
||||
@ -66,7 +66,7 @@ private:
|
||||
template<typename T>
|
||||
T* Elements() { return static_cast<T*>(mUntypedData); }
|
||||
|
||||
void InvalidateTrees(size_t firstByte, size_t lastByte);
|
||||
bool UpdateTrees(size_t firstByte, size_t lastByte);
|
||||
|
||||
template<typename T>
|
||||
friend struct WebGLElementArrayCacheTree;
|
||||
|
@ -3138,81 +3138,6 @@ nsGenericHTMLElement::SetItemValueText(const nsAString& text)
|
||||
SetTextContentInternal(text, rv);
|
||||
}
|
||||
|
||||
static void
|
||||
nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
||||
void *aPropertyValue, void *aData)
|
||||
{
|
||||
nsDOMSettableTokenList* list =
|
||||
static_cast<nsDOMSettableTokenList*>(aPropertyValue);
|
||||
NS_RELEASE(list);
|
||||
}
|
||||
|
||||
static nsIAtom** sPropertiesToTraverseAndUnlink[] =
|
||||
{
|
||||
&nsGkAtoms::microdataProperties,
|
||||
&nsGkAtoms::itemtype,
|
||||
&nsGkAtoms::itemref,
|
||||
&nsGkAtoms::itemprop,
|
||||
&nsGkAtoms::sandbox,
|
||||
&nsGkAtoms::sizes,
|
||||
nullptr
|
||||
};
|
||||
|
||||
// static
|
||||
nsIAtom***
|
||||
nsGenericHTMLElement::PropertiesToTraverseAndUnlink()
|
||||
{
|
||||
return sPropertiesToTraverseAndUnlink;
|
||||
}
|
||||
|
||||
nsDOMSettableTokenList*
|
||||
nsGenericHTMLElement::GetTokenList(nsIAtom* aAtom)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsIAtom*** props =
|
||||
nsGenericHTMLElement::PropertiesToTraverseAndUnlink();
|
||||
bool found = false;
|
||||
for (uint32_t i = 0; props[i]; ++i) {
|
||||
if (*props[i] == aAtom) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
|
||||
#endif
|
||||
|
||||
nsDOMSettableTokenList* list = nullptr;
|
||||
if (HasProperties()) {
|
||||
list = static_cast<nsDOMSettableTokenList*>(GetProperty(aAtom));
|
||||
}
|
||||
if (!list) {
|
||||
list = new nsDOMSettableTokenList(this, aAtom);
|
||||
NS_ADDREF(list);
|
||||
SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLElement::GetTokenList(nsIAtom* aAtom, nsIVariant** aResult)
|
||||
{
|
||||
nsISupports* itemType = GetTokenList(aAtom);
|
||||
nsCOMPtr<nsIWritableVariant> out = new nsVariant();
|
||||
out->SetAsInterface(NS_GET_IID(nsISupports), itemType);
|
||||
out.forget(aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue)
|
||||
{
|
||||
nsDOMSettableTokenList* itemType = GetTokenList(aAtom);
|
||||
nsAutoString string;
|
||||
aValue->GetAsAString(string);
|
||||
ErrorResult rv;
|
||||
itemType->SetValue(string, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
static void
|
||||
HTMLPropertiesCollectionDestructor(void *aObject, nsIAtom *aProperty,
|
||||
void *aPropertyValue, void *aData)
|
||||
|
@ -303,9 +303,6 @@ protected:
|
||||
// when an element has @itemprop but no @itemscope.
|
||||
virtual void GetItemValueText(nsAString& text);
|
||||
virtual void SetItemValueText(const nsAString& text);
|
||||
nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom);
|
||||
void GetTokenList(nsIAtom* aAtom, nsIVariant** aResult);
|
||||
nsresult SetTokenList(nsIAtom* aAtom, nsIVariant* aValue);
|
||||
public:
|
||||
virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager();
|
||||
virtual bool UndoScope() MOZ_OVERRIDE;
|
||||
|
@ -39,11 +39,10 @@ NS_IMPL_RELEASE_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement)
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsGenericHTMLFrameElement)
|
||||
NS_INTERFACE_TABLE_INHERITED(nsGenericHTMLFrameElement,
|
||||
nsIFrameLoaderOwner,
|
||||
nsIDOMMozBrowserFrame,
|
||||
nsIMozBrowserFrame)
|
||||
nsIMozBrowserFrame,
|
||||
nsIFrameLoaderOwner)
|
||||
NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
|
||||
|
||||
NS_IMPL_BOOL_ATTR(nsGenericHTMLFrameElement, Mozbrowser, mozbrowser)
|
||||
|
||||
int32_t
|
||||
@ -52,92 +51,6 @@ nsGenericHTMLFrameElement::TabIndexDefault()
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement()
|
||||
{
|
||||
if (mFrameLoader) {
|
||||
mFrameLoader->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
|
||||
{
|
||||
NS_PRECONDITION(aContentDocument, "Null out param");
|
||||
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetContentDocument());
|
||||
document.forget(aContentDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsGenericHTMLFrameElement::GetContentDocument()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetContentWindow();
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIDocument *doc = win->GetDoc();
|
||||
|
||||
// Return null for cross-origin contentDocument.
|
||||
if (!nsContentUtils::GetSubjectPrincipal()->SubsumesConsideringDomain(doc->NodePrincipal())) {
|
||||
return nullptr;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
|
||||
{
|
||||
NS_PRECONDITION(aContentWindow, "Null out param");
|
||||
nsCOMPtr<nsPIDOMWindow> window = GetContentWindow();
|
||||
window.forget(aContentWindow);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsPIDOMWindow>
|
||||
nsGenericHTMLFrameElement::GetContentWindow()
|
||||
{
|
||||
EnsureFrameLoader();
|
||||
|
||||
if (!mFrameLoader) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool depthTooGreat = false;
|
||||
mFrameLoader->GetDepthTooGreat(&depthTooGreat);
|
||||
if (depthTooGreat) {
|
||||
// Claim to have no contentWindow
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> doc_shell;
|
||||
mFrameLoader->GetDocShell(getter_AddRefs(doc_shell));
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(doc_shell);
|
||||
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_ASSERTION(win->IsOuterWindow(),
|
||||
"Uh, this window should always be an outer window!");
|
||||
|
||||
return win.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFrameElement::EnsureFrameLoader()
|
||||
{
|
||||
if (!GetParent() || !IsInDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) {
|
||||
// If frame loader is there, we just keep it around, cached
|
||||
return;
|
||||
}
|
||||
|
||||
// Strangely enough, this method doesn't actually ensure that the
|
||||
// frameloader exists. It's more of a best-effort kind of thing.
|
||||
mFrameLoader = nsFrameLoader::Create(this, mNetworkCreated);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLFrameElement::CreateRemoteFrameLoader(nsITabParent* aTabParent)
|
||||
{
|
||||
@ -148,46 +61,6 @@ nsGenericHTMLFrameElement::CreateRemoteFrameLoader(nsITabParent* aTabParent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericHTMLFrameElement::GetFrameLoader(nsIFrameLoader **aFrameLoader)
|
||||
{
|
||||
NS_IF_ADDREF(*aFrameLoader = mFrameLoader);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
|
||||
nsGenericHTMLFrameElement::GetFrameLoader()
|
||||
{
|
||||
nsRefPtr<nsFrameLoader> loader = mFrameLoader;
|
||||
return loader.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericHTMLFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
|
||||
{
|
||||
// We don't support this yet
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLFrameElement::LoadSrc()
|
||||
{
|
||||
EnsureFrameLoader();
|
||||
|
||||
if (!mFrameLoader) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mFrameLoader->LoadFrame();
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to load URL");
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLFrameElement::BindToTree(nsIDocument* aDocument,
|
||||
nsIContent* aParent,
|
||||
@ -511,11 +384,3 @@ nsGenericHTMLFrameElement::AllowCreateFrameLoader()
|
||||
mFrameLoaderCreationDisallowed = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFrameElement::SwapFrameLoaders(nsXULElement& aOtherOwner,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define nsGenericHTMLFrameElement_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsElementFrameLoaderOwner.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsIFrameLoader.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
@ -23,24 +24,19 @@ class nsXULElement;
|
||||
* A helper class for frame elements
|
||||
*/
|
||||
class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
|
||||
public nsIFrameLoaderOwner,
|
||||
public nsElementFrameLoaderOwner,
|
||||
public nsIMozBrowserFrame
|
||||
{
|
||||
public:
|
||||
nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
, mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
|
||||
, mBrowserFrameListenersRegistered(false)
|
||||
, mFrameLoaderCreationDisallowed(false)
|
||||
, nsElementFrameLoaderOwner(aFromParser)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsGenericHTMLFrameElement();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSIFRAMELOADEROWNER
|
||||
NS_DECL_NSIDOMMOZBROWSERFRAME
|
||||
NS_DECL_NSIMOZBROWSERFRAME
|
||||
|
||||
@ -73,8 +69,6 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement,
|
||||
nsGenericHTMLElement)
|
||||
|
||||
void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aError);
|
||||
|
||||
static bool BrowserFramesEnabled();
|
||||
|
||||
/**
|
||||
@ -88,24 +82,10 @@ public:
|
||||
static int32_t MapScrollingAttribute(const nsAttrValue* aValue);
|
||||
|
||||
protected:
|
||||
// This doesn't really ensure a frame loade in all cases, only when
|
||||
// it makes sense.
|
||||
void EnsureFrameLoader();
|
||||
nsresult LoadSrc();
|
||||
nsIDocument* GetContentDocument();
|
||||
nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
|
||||
already_AddRefed<nsPIDOMWindow> GetContentWindow();
|
||||
nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
|
||||
|
||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||
|
||||
// True when the element is created by the parser
|
||||
// using NS_FROM_PARSER_NETWORK flag.
|
||||
// If the element is modified, it may lose the flag.
|
||||
bool mNetworkCreated;
|
||||
|
||||
bool mBrowserFrameListenersRegistered;
|
||||
bool mFrameLoaderCreationDisallowed;
|
||||
virtual mozilla::dom::Element* ThisFrameElement() MOZ_OVERRIDE
|
||||
{
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // nsGenericHTMLFrameElement_h
|
||||
|
@ -245,14 +245,9 @@ MediaDecoderStateMachine::~MediaDecoderStateMachine()
|
||||
NS_ASSERTION(!mPendingWakeDecoder.get(),
|
||||
"WakeDecoder should have been revoked already");
|
||||
|
||||
if (mDecodeTaskQueue) {
|
||||
mDecodeTaskQueue->Shutdown();
|
||||
mDecodeTaskQueue = nullptr;
|
||||
}
|
||||
|
||||
// No need to cancel the timer here for we've done that in
|
||||
// TimeoutExpired() triggered by Shutdown()
|
||||
mTimer = nullptr;
|
||||
MOZ_ASSERT(!mDecodeTaskQueue, "Should be released in SHUTDOWN");
|
||||
// No need to cancel the timer here for we've done that in SHUTDOWN.
|
||||
MOZ_ASSERT(!mTimer, "Should be released in SHUTDOWN");
|
||||
mReader = nullptr;
|
||||
|
||||
#ifdef XP_WIN
|
||||
@ -1584,13 +1579,13 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
|
||||
return;
|
||||
}
|
||||
mIsReaderIdle = needIdle;
|
||||
nsRefPtr<nsIRunnable> event;
|
||||
RefPtr<nsIRunnable> event;
|
||||
if (mIsReaderIdle) {
|
||||
event = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::SetReaderIdle);
|
||||
} else {
|
||||
event = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::SetReaderActive);
|
||||
}
|
||||
if (NS_FAILED(mDecodeTaskQueue->Dispatch(event)) &&
|
||||
if (NS_FAILED(mDecodeTaskQueue->Dispatch(event.forget())) &&
|
||||
mState != DECODER_STATE_SHUTDOWN) {
|
||||
NS_WARNING("Failed to dispatch event to set decoder idle state");
|
||||
}
|
||||
@ -2149,6 +2144,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
// Wait for the thread decoding to exit.
|
||||
mDecodeTaskQueue->Shutdown();
|
||||
mDecodeTaskQueue = nullptr;
|
||||
mReader->ReleaseMediaResources();
|
||||
}
|
||||
// Now that those threads are stopped, there's no possibility of
|
||||
@ -2172,6 +2168,9 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
// state machine.
|
||||
GetStateMachineThread()->Dispatch(
|
||||
new nsDispatchDisposeEvent(mDecoder, this), NS_DISPATCH_NORMAL);
|
||||
|
||||
mTimer->Cancel();
|
||||
mTimer = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ MediaTaskQueue::~MediaTaskQueue()
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaTaskQueue::Dispatch(nsIRunnable* aRunnable)
|
||||
MediaTaskQueue::Dispatch(TemporaryRef<nsIRunnable> aRunnable)
|
||||
{
|
||||
MonitorAutoLock mon(mQueueMonitor);
|
||||
if (mIsShutdown) {
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
|
||||
MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool);
|
||||
|
||||
nsresult Dispatch(nsIRunnable* aRunnable);
|
||||
nsresult Dispatch(TemporaryRef<nsIRunnable> aRunnable);
|
||||
|
||||
// Removes all pending tasks from the task queue, and blocks until
|
||||
// the currently running task (if any) finishes.
|
||||
|
@ -40,7 +40,7 @@ namespace mozilla {
|
||||
// Uncomment to enable verbose per-sample logging.
|
||||
//#define LOG_SAMPLE_DECODE 1
|
||||
|
||||
class MP4Stream : public mp4_demuxer::Stream {
|
||||
class MP4Stream : public Stream {
|
||||
public:
|
||||
|
||||
MP4Stream(MediaResource* aResource)
|
||||
@ -265,7 +265,7 @@ MP4Reader::SampleQueue(TrackType aTrack)
|
||||
}
|
||||
|
||||
MediaDataDecoder*
|
||||
MP4Reader::Decoder(mp4_demuxer::TrackType aTrack)
|
||||
MP4Reader::Decoder(TrackType aTrack)
|
||||
{
|
||||
return GetDecoderData(aTrack).mDecoder;
|
||||
}
|
||||
@ -385,7 +385,7 @@ TrackTypeToStr(TrackType aTrack)
|
||||
#endif
|
||||
|
||||
void
|
||||
MP4Reader::Output(mp4_demuxer::TrackType aTrack, MediaData* aSample)
|
||||
MP4Reader::Output(TrackType aTrack, MediaData* aSample)
|
||||
{
|
||||
#ifdef LOG_SAMPLE_DECODE
|
||||
LOG("Decoded %s sample time=%lld dur=%lld",
|
||||
@ -420,7 +420,7 @@ MP4Reader::Output(mp4_demuxer::TrackType aTrack, MediaData* aSample)
|
||||
}
|
||||
|
||||
void
|
||||
MP4Reader::InputExhausted(mp4_demuxer::TrackType aTrack)
|
||||
MP4Reader::InputExhausted(TrackType aTrack)
|
||||
{
|
||||
DecoderData& data = GetDecoderData(aTrack);
|
||||
MonitorAutoLock mon(data.mMonitor);
|
||||
@ -429,7 +429,7 @@ MP4Reader::InputExhausted(mp4_demuxer::TrackType aTrack)
|
||||
}
|
||||
|
||||
void
|
||||
MP4Reader::Error(mp4_demuxer::TrackType aTrack)
|
||||
MP4Reader::Error(TrackType aTrack)
|
||||
{
|
||||
DecoderData& data = GetDecoderData(aTrack);
|
||||
MonitorAutoLock mon(data.mMonitor);
|
||||
@ -445,7 +445,7 @@ MP4Reader::DecodeAudioData()
|
||||
}
|
||||
|
||||
void
|
||||
MP4Reader::Flush(mp4_demuxer::TrackType aTrack)
|
||||
MP4Reader::Flush(TrackType aTrack)
|
||||
{
|
||||
DecoderData& data = GetDecoderData(aTrack);
|
||||
if (!data.mDecoder) {
|
||||
|
@ -23,10 +23,6 @@ using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
#define ENCODER_CONFIG_BITRATE 2000000 // bps
|
||||
// How many seconds between I-frames.
|
||||
#define ENCODER_CONFIG_I_FRAME_INTERVAL 1
|
||||
// Wait up to 5ms for input buffers.
|
||||
#define INPUT_BUFFER_TIMEOUT_US (5 * 1000ll)
|
||||
// AMR NB kbps
|
||||
#define AMRNB_BITRATE 12200
|
||||
@ -137,27 +133,20 @@ IsRunningOnEmulator()
|
||||
return strncmp(qemu, "1", 1) == 0;
|
||||
}
|
||||
|
||||
#define ENCODER_CONFIG_BITRATE 2000000 // bps
|
||||
// How many seconds between I-frames.
|
||||
#define ENCODER_CONFIG_I_FRAME_INTERVAL 1
|
||||
// Wait up to 5ms for input buffers.
|
||||
|
||||
nsresult
|
||||
OMXVideoEncoder::Configure(int aWidth, int aHeight, int aFrameRate,
|
||||
BlobFormat aBlobFormat)
|
||||
{
|
||||
MOZ_ASSERT(!mStarted, "Configure() was called already.");
|
||||
|
||||
NS_ENSURE_TRUE(aWidth > 0 && aHeight > 0 && aFrameRate > 0,
|
||||
NS_ERROR_INVALID_ARG);
|
||||
|
||||
OMX_VIDEO_AVCLEVELTYPE level = OMX_VIDEO_AVCLevel3;
|
||||
OMX_VIDEO_CONTROLRATETYPE bitrateMode = OMX_Video_ControlRateConstant;
|
||||
// Limitation of soft AVC/H.264 encoder running on emulator in stagefright.
|
||||
static bool emu = IsRunningOnEmulator();
|
||||
if (emu) {
|
||||
if (aWidth > 352 || aHeight > 288) {
|
||||
CODEC_ERROR("SoftAVCEncoder doesn't support resolution larger than CIF");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
level = OMX_VIDEO_AVCLevel2;
|
||||
bitrateMode = OMX_Video_ControlRateVariable;
|
||||
}
|
||||
|
||||
// Set up configuration parameters for AVC/H.264 encoder.
|
||||
sp<AMessage> format = new AMessage;
|
||||
@ -180,12 +169,42 @@ OMXVideoEncoder::Configure(int aWidth, int aHeight, int aFrameRate,
|
||||
format->setInt32("slice-height", aHeight);
|
||||
format->setInt32("frame-rate", aFrameRate);
|
||||
|
||||
status_t result = mCodec->configure(format, nullptr, nullptr,
|
||||
return ConfigureDirect(format, aBlobFormat);
|
||||
}
|
||||
|
||||
nsresult
|
||||
OMXVideoEncoder::ConfigureDirect(sp<AMessage>& aFormat,
|
||||
BlobFormat aBlobFormat)
|
||||
{
|
||||
MOZ_ASSERT(!mStarted, "Configure() was called already.");
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int frameRate = 0;
|
||||
aFormat->findInt32("width", &width);
|
||||
aFormat->findInt32("height", &height);
|
||||
aFormat->findInt32("frame-rate", &frameRate);
|
||||
NS_ENSURE_TRUE(width > 0 && height > 0 && frameRate > 0,
|
||||
NS_ERROR_INVALID_ARG);
|
||||
|
||||
// Limitation of soft AVC/H.264 encoder running on emulator in stagefright.
|
||||
static bool emu = IsRunningOnEmulator();
|
||||
if (emu) {
|
||||
if (width > 352 || height > 288) {
|
||||
CODEC_ERROR("SoftAVCEncoder doesn't support resolution larger than CIF");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
aFormat->setInt32("level", OMX_VIDEO_AVCLevel2);
|
||||
aFormat->setInt32("bitrate-mode", OMX_Video_ControlRateVariable);
|
||||
}
|
||||
|
||||
|
||||
status_t result = mCodec->configure(aFormat, nullptr, nullptr,
|
||||
MediaCodec::CONFIGURE_FLAG_ENCODE);
|
||||
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
|
||||
|
||||
mWidth = aWidth;
|
||||
mHeight = aHeight;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mBlobFormat = aBlobFormat;
|
||||
|
||||
result = Start();
|
||||
|
@ -254,9 +254,13 @@ public:
|
||||
* before calling Encode() and GetNextEncodedFrame().
|
||||
* aBlobFormat specifies output blob format provided by encoder. It can be
|
||||
* AVC_MP4 or AVC_NAL.
|
||||
* Configure sets up most format value to values appropriate for camera use.
|
||||
* ConfigureDirect lets the caller determine all the defaults.
|
||||
*/
|
||||
nsresult Configure(int aWidth, int aHeight, int aFrameRate,
|
||||
BlobFormat aBlobFormat = BlobFormat::AVC_MP4);
|
||||
nsresult ConfigureDirect(sp<AMessage>& aFormat,
|
||||
BlobFormat aBlobFormat = BlobFormat::AVC_MP4);
|
||||
|
||||
/**
|
||||
* Encode a aWidth pixels wide and aHeight pixels tall video frame of
|
||||
|
@ -144,9 +144,7 @@ bool MediaPluginReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
if (mLastVideoFrame) {
|
||||
int64_t durationUs;
|
||||
mPlugin->GetDuration(mPlugin, &durationUs);
|
||||
if (durationUs < mLastVideoFrame->mTime) {
|
||||
durationUs = 0;
|
||||
}
|
||||
durationUs = std::max<int64_t>(durationUs - mLastVideoFrame->mTime, 0);
|
||||
mVideoQueue.Push(VideoData::ShallowCopyUpdateDuration(mLastVideoFrame,
|
||||
durationUs));
|
||||
mLastVideoFrame = nullptr;
|
||||
|
344
content/svg/content/src/SVGIFrameElement.cpp
Normal file
344
content/svg/content/src/SVGIFrameElement.cpp
Normal file
@ -0,0 +1,344 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "SVGIFrameElement.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "mozilla/dom/SVGDocumentBinding.h"
|
||||
#include "mozilla/dom/SVGIFrameElementBinding.h"
|
||||
#include "mozilla/dom/SVGMatrix.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsStyleConsts.h"
|
||||
|
||||
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT_CHECK_PARSER(IFrame)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
JSObject*
|
||||
SVGIFrameElement::WrapNode(JSContext *aCx)
|
||||
{
|
||||
return SVGIFrameElementBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
//--------------------- IFrame ------------------------
|
||||
|
||||
nsSVGElement::LengthInfo SVGIFrameElement::sLengthInfo[4] =
|
||||
{
|
||||
{ &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
|
||||
{ &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
|
||||
{ &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
|
||||
{ &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISupports methods
|
||||
NS_IMPL_ISUPPORTS_INHERITED(SVGIFrameElement, SVGIFrameElementBase,
|
||||
nsIFrameLoaderOwner,
|
||||
nsIDOMNode, nsIDOMElement,
|
||||
nsIDOMSVGElement)
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
||||
SVGIFrameElement::SVGIFrameElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
|
||||
FromParser aFromParser)
|
||||
: SVGIFrameElementBase(aNodeInfo)
|
||||
, nsElementFrameLoaderOwner(aFromParser)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsSVGElement methods
|
||||
|
||||
/* virtual */ gfxMatrix
|
||||
SVGIFrameElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
|
||||
TransformTypes aWhich) const
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
|
||||
"Skipping eUserSpaceToParent transforms makes no sense");
|
||||
|
||||
// 'transform' attribute:
|
||||
gfxMatrix fromUserSpace =
|
||||
SVGGraphicsElement::PrependLocalTransformsTo(aMatrix, aWhich);
|
||||
if (aWhich == eUserSpaceToParent) {
|
||||
return fromUserSpace;
|
||||
}
|
||||
// our 'x' and 'y' attributes:
|
||||
float x, y;
|
||||
const_cast<SVGIFrameElement*>(this)->
|
||||
GetAnimatedLengthValues(&x, &y, nullptr);
|
||||
gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y));
|
||||
if (aWhich == eChildToUserSpace) {
|
||||
return toUserSpace;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
|
||||
return toUserSpace * fromUserSpace;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIDOMNode methods
|
||||
|
||||
nsresult
|
||||
SVGIFrameElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
|
||||
{
|
||||
*aResult = nullptr;
|
||||
already_AddRefed<nsINodeInfo> ni = nsCOMPtr<nsINodeInfo>(aNodeInfo).forget();
|
||||
SVGIFrameElement *it = new SVGIFrameElement(ni, NOT_FROM_PARSER);
|
||||
|
||||
nsCOMPtr<nsINode> kungFuDeathGrip = it;
|
||||
nsresult rv1 = it->Init();
|
||||
nsresult rv2 = const_cast<SVGIFrameElement*>(this)->CopyInnerTo(it);
|
||||
if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
|
||||
kungFuDeathGrip.swap(*aResult);
|
||||
}
|
||||
|
||||
return NS_FAILED(rv1) ? rv1 : rv2;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsSVGElement methods
|
||||
|
||||
nsSVGElement::LengthAttributesInfo
|
||||
SVGIFrameElement::GetLengthInfo()
|
||||
{
|
||||
return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
|
||||
ArrayLength(sLengthInfo));
|
||||
}
|
||||
|
||||
SVGAnimatedPreserveAspectRatio *
|
||||
SVGIFrameElement::GetPreserveAspectRatio()
|
||||
{
|
||||
return &mPreserveAspectRatio;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIDOMSVGIFrameElement methods:
|
||||
|
||||
already_AddRefed<SVGAnimatedLength>
|
||||
SVGIFrameElement::X()
|
||||
{
|
||||
return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
|
||||
}
|
||||
|
||||
already_AddRefed<SVGAnimatedLength>
|
||||
SVGIFrameElement::Y()
|
||||
{
|
||||
return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
|
||||
}
|
||||
|
||||
already_AddRefed<SVGAnimatedLength>
|
||||
SVGIFrameElement::Width()
|
||||
{
|
||||
return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
|
||||
}
|
||||
|
||||
already_AddRefed<SVGAnimatedLength>
|
||||
SVGIFrameElement::Height()
|
||||
{
|
||||
return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
|
||||
SVGIFrameElement::PreserveAspectRatio()
|
||||
{
|
||||
nsRefPtr<DOMSVGAnimatedPreserveAspectRatio> ratio;
|
||||
mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio),
|
||||
this);
|
||||
return ratio.forget();
|
||||
}
|
||||
|
||||
void
|
||||
SVGIFrameElement::GetName(DOMString& name)
|
||||
{
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||
}
|
||||
|
||||
void
|
||||
SVGIFrameElement::GetSrc(DOMString& src)
|
||||
{
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
|
||||
}
|
||||
|
||||
void
|
||||
SVGIFrameElement::GetSrcdoc(DOMString& srcdoc)
|
||||
{
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc, srcdoc);
|
||||
}
|
||||
|
||||
already_AddRefed<nsDOMSettableTokenList>
|
||||
SVGIFrameElement::Sandbox()
|
||||
{
|
||||
return GetTokenList(nsGkAtoms::sandbox);
|
||||
}
|
||||
|
||||
bool
|
||||
SVGIFrameElement::ParseAttribute(int32_t aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
if (aAttribute == nsGkAtoms::sandbox) {
|
||||
aResult.ParseAtomArray(aValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return SVGIFrameElementBase::ParseAttribute(aNamespaceID, aAttribute,
|
||||
aValue, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGIFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
bool aNotify)
|
||||
{
|
||||
nsresult rv = nsSVGElement::SetAttr(aNameSpaceID, aName, aPrefix,
|
||||
aValue, aNotify);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::src &&
|
||||
!HasAttr(kNameSpaceID_None,nsGkAtoms::srcdoc)) {
|
||||
// Don't propagate error here. The attribute was successfully set, that's
|
||||
// what we should reflect.
|
||||
LoadSrc();
|
||||
}
|
||||
if (aName == nsGkAtoms::srcdoc) {
|
||||
// Don't propagate error here. The attribute was successfully set, that's
|
||||
// what we should reflect.
|
||||
LoadSrc();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
bool aNotify)
|
||||
{
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::sandbox && mFrameLoader) {
|
||||
// If we have an nsFrameLoader, apply the new sandbox flags.
|
||||
// Since this is called after the setter, the sandbox flags have
|
||||
// alreay been updated.
|
||||
mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
|
||||
}
|
||||
}
|
||||
return nsSVGElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGIFrameElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
|
||||
bool aNotify)
|
||||
{
|
||||
// Invoke on the superclass.
|
||||
nsresult rv = nsSVGElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aAttribute == nsGkAtoms::srcdoc) {
|
||||
// Fall back to the src attribute, if any
|
||||
LoadSrc();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SVGIFrameElement::GetSandboxFlags()
|
||||
{
|
||||
const nsAttrValue* sandboxAttr = GetParsedAttr(nsGkAtoms::sandbox);
|
||||
return nsContentUtils::ParseSandboxAttributeToFlags(sandboxAttr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGIFrameElement::BindToTree(nsIDocument* aDocument,
|
||||
nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
bool aCompileEventHandlers)
|
||||
{
|
||||
nsresult rv = nsSVGElement::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aDocument) {
|
||||
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
|
||||
"Missing a script blocker!");
|
||||
|
||||
PROFILER_LABEL("SVGIFrameElement", "BindToTree");
|
||||
|
||||
// We're in a document now. Kick off the frame load.
|
||||
LoadSrc();
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::sandbox)) {
|
||||
if (mFrameLoader) {
|
||||
mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We're now in document and scripts may move us, so clear
|
||||
// the mNetworkCreated flag.
|
||||
mNetworkCreated = false;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
SVGIFrameElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
{
|
||||
if (mFrameLoader) {
|
||||
// This iframe is being taken out of the document, destroy the
|
||||
// iframe's frame loader (doing that will tear down the window in
|
||||
// this iframe).
|
||||
// XXXbz we really want to only partially destroy the frame
|
||||
// loader... we don't want to tear down the docshell. Food for
|
||||
// later bug.
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
|
||||
nsSVGElement::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
void
|
||||
SVGIFrameElement::DestroyContent()
|
||||
{
|
||||
if (mFrameLoader) {
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
|
||||
nsSVGElement::DestroyContent();
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGIFrameElement::CopyInnerTo(Element* aDest)
|
||||
{
|
||||
nsresult rv = nsSVGElement::CopyInnerTo(aDest);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIDocument* doc = aDest->OwnerDoc();
|
||||
if (doc->IsStaticDocument() && mFrameLoader) {
|
||||
SVGIFrameElement* dest =
|
||||
static_cast<SVGIFrameElement*>(aDest);
|
||||
nsFrameLoader* fl = nsFrameLoader::Create(dest, false);
|
||||
NS_ENSURE_STATE(fl);
|
||||
dest->mFrameLoader = fl;
|
||||
static_cast<nsFrameLoader*>(mFrameLoader.get())->CreateStaticClone(fl);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
110
content/svg/content/src/SVGIFrameElement.h
Normal file
110
content/svg/content/src/SVGIFrameElement.h
Normal file
@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/DOMString.h"
|
||||
#include "mozilla/dom/FromParser.h"
|
||||
#include "mozilla/dom/SVGGraphicsElement.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMSettableTokenList.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsElementFrameLoaderOwner.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIFrameLoader.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "nsSVGLength2.h"
|
||||
#include "SVGAnimatedPreserveAspectRatio.h"
|
||||
|
||||
nsresult NS_NewSVGIFrameElement(nsIContent **aResult,
|
||||
already_AddRefed<nsINodeInfo>&& aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser);
|
||||
|
||||
typedef mozilla::dom::SVGGraphicsElement SVGIFrameElementBase;
|
||||
|
||||
class nsSVGIFrameFrame;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class DOMSVGAnimatedPreserveAspectRatio;
|
||||
|
||||
class SVGIFrameElement MOZ_FINAL : public SVGIFrameElementBase,
|
||||
public nsElementFrameLoaderOwner
|
||||
{
|
||||
friend class ::nsSVGIFrameFrame;
|
||||
friend nsresult (::NS_NewSVGIFrameElement(nsIContent **aResult,
|
||||
already_AddRefed<nsINodeInfo>&& aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser));
|
||||
|
||||
SVGIFrameElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser);
|
||||
virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE;
|
||||
|
||||
public:
|
||||
// interface
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsSVGElement specializations:
|
||||
virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
|
||||
TransformTypes aWhich = eAllTransforms) const MOZ_OVERRIDE;
|
||||
|
||||
// nsIContent
|
||||
virtual bool ParseAttribute(int32_t aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
nsAttrValue& aResult) MOZ_OVERRIDE;
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
bool aCompileEventHandlers) MOZ_OVERRIDE;
|
||||
virtual void UnbindFromTree(bool aDeep = true,
|
||||
bool aNullParent = true) MOZ_OVERRIDE;
|
||||
virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
bool aNotify) MOZ_OVERRIDE;
|
||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
bool aNotify) MOZ_OVERRIDE;
|
||||
virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
|
||||
bool aNotify) MOZ_OVERRIDE;
|
||||
|
||||
virtual void DestroyContent() MOZ_OVERRIDE;
|
||||
nsresult CopyInnerTo(mozilla::dom::Element* aDest);
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
already_AddRefed<SVGAnimatedLength> X();
|
||||
already_AddRefed<SVGAnimatedLength> Y();
|
||||
already_AddRefed<SVGAnimatedLength> Width();
|
||||
already_AddRefed<SVGAnimatedLength> Height();
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
|
||||
void GetName(DOMString& name);
|
||||
void GetSrc(DOMString& src);
|
||||
void GetSrcdoc(DOMString& srcdoc);
|
||||
already_AddRefed<nsDOMSettableTokenList> Sandbox();
|
||||
using nsElementFrameLoaderOwner::GetContentDocument;
|
||||
using nsElementFrameLoaderOwner::GetContentWindow;
|
||||
|
||||
// Parses a sandbox attribute and converts it to the set of flags used internally.
|
||||
// Returns 0 if there isn't the attribute.
|
||||
uint32_t GetSandboxFlags();
|
||||
|
||||
private:
|
||||
virtual LengthAttributesInfo GetLengthInfo();
|
||||
virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
|
||||
virtual mozilla::dom::Element* ThisFrameElement() MOZ_OVERRIDE
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
|
||||
nsSVGLength2 mLengthAttributes[4];
|
||||
static LengthInfo sLengthInfo[4];
|
||||
|
||||
SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -65,6 +65,7 @@ SVG_TAG(feTurbulence, FETurbulence)
|
||||
SVG_TAG(filter, Filter)
|
||||
SVG_TAG(foreignObject, ForeignObject)
|
||||
SVG_TAG(g, G)
|
||||
SVG_FROM_PARSER_TAG(iframe, IFrame)
|
||||
SVG_TAG(image, Image)
|
||||
SVG_TAG(line, Line)
|
||||
SVG_TAG(linearGradient, LinearGradient)
|
||||
|
@ -63,6 +63,7 @@ EXPORTS.mozilla.dom += [
|
||||
'SVGGElement.h',
|
||||
'SVGGradientElement.h',
|
||||
'SVGGraphicsElement.h',
|
||||
'SVGIFrameElement.h',
|
||||
'SVGImageElement.h',
|
||||
'SVGIRect.h',
|
||||
'SVGLineElement.h',
|
||||
@ -188,6 +189,7 @@ UNIFIED_SOURCES += [
|
||||
'SVGGElement.cpp',
|
||||
'SVGGradientElement.cpp',
|
||||
'SVGGraphicsElement.cpp',
|
||||
'SVGIFrameElement.cpp',
|
||||
'SVGImageElement.cpp',
|
||||
'SVGIntegerPairSMILType.cpp',
|
||||
'SVGLength.cpp',
|
||||
|
@ -71,11 +71,20 @@ XPCOMUtils.defineLazyGetter(this, "libcutils", function() {
|
||||
});
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
// On Android, define the "debug" function as a binding of the "d" function
|
||||
// from the AndroidLog module so it gets the "debug" priority and a log tag.
|
||||
// We always report debug messages on Android because it's hard to use a debug
|
||||
// build on Android and unnecessary to restrict reporting, per bug 1003469.
|
||||
let debug = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
|
||||
.AndroidLog.d.bind(null, "Webapps");
|
||||
#else
|
||||
function debug(aMsg) {
|
||||
#ifdef DEBUG
|
||||
dump("-*- Webapps.jsm : " + aMsg + "\n");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
function getNSPRErrorCode(err) {
|
||||
return -1 * ((err) & 0xffff);
|
||||
@ -4052,10 +4061,10 @@ AppcacheObserver.prototype = {
|
||||
app.downloading = false;
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
error: aError,
|
||||
manifestURL: app.manifestURL
|
||||
});
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
||||
error: aError,
|
||||
eventType: "downloaderror",
|
||||
manifestURL: app.manifestURL
|
||||
});
|
||||
|
@ -360,22 +360,22 @@ nsPerformanceNavigation::WrapObject(JSContext *cx)
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPerformance,
|
||||
mWindow, mTiming,
|
||||
mNavigation, mEntries,
|
||||
mParentPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(nsPerformance, DOMEventTargetHelper,
|
||||
mWindow, mTiming,
|
||||
mNavigation, mEntries,
|
||||
mParentPerformance)
|
||||
NS_IMPL_ADDREF_INHERITED(nsPerformance, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(nsPerformance, DOMEventTargetHelper)
|
||||
|
||||
nsPerformance::nsPerformance(nsIDOMWindow* aWindow,
|
||||
nsPerformance::nsPerformance(nsPIDOMWindow* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
nsPerformance* aParentPerformance)
|
||||
: mWindow(aWindow),
|
||||
: DOMEventTargetHelper(aWindow),
|
||||
mWindow(aWindow),
|
||||
mDOMTiming(aDOMTiming),
|
||||
mChannel(aChannel),
|
||||
mParentPerformance(aParentPerformance),
|
||||
mBufferSizeSet(kDefaultBufferSize),
|
||||
mPrimaryBufferSize(kDefaultBufferSize)
|
||||
{
|
||||
MOZ_ASSERT(aWindow, "Parent window object should be provided");
|
||||
@ -390,7 +390,7 @@ nsPerformance::~nsPerformance()
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPerformance)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
|
||||
nsPerformanceTiming*
|
||||
@ -407,6 +407,21 @@ nsPerformance::Timing()
|
||||
return mTiming;
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::DispatchBufferFullEvent()
|
||||
{
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// it bubbles, and it isn't cancelable
|
||||
rv = event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"), true, false);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
event->SetTrusted(true);
|
||||
DispatchDOMEvent(nullptr, event, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsPerformanceNavigation*
|
||||
nsPerformance::Navigation()
|
||||
{
|
||||
@ -433,12 +448,7 @@ nsPerformance::GetEntries(nsTArray<nsRefPtr<PerformanceEntry> >& retval)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
retval.Clear();
|
||||
uint32_t count = mEntries.Length();
|
||||
if (count > mPrimaryBufferSize) {
|
||||
count = mPrimaryBufferSize;
|
||||
}
|
||||
retval.AppendElements(mEntries.Elements(), count);
|
||||
retval = mEntries;
|
||||
}
|
||||
|
||||
void
|
||||
@ -449,7 +459,7 @@ nsPerformance::GetEntriesByType(const nsAString& entryType,
|
||||
|
||||
retval.Clear();
|
||||
uint32_t count = mEntries.Length();
|
||||
for (uint32_t i = 0 ; i < count && i < mPrimaryBufferSize ; i++) {
|
||||
for (uint32_t i = 0 ; i < count; i++) {
|
||||
if (mEntries[i]->GetEntryType().Equals(entryType)) {
|
||||
retval.AppendElement(mEntries[i]);
|
||||
}
|
||||
@ -465,7 +475,7 @@ nsPerformance::GetEntriesByName(const nsAString& name,
|
||||
|
||||
retval.Clear();
|
||||
uint32_t count = mEntries.Length();
|
||||
for (uint32_t i = 0 ; i < count && i < mPrimaryBufferSize ; i++) {
|
||||
for (uint32_t i = 0 ; i < count; i++) {
|
||||
if (mEntries[i]->GetName().Equals(name) &&
|
||||
(!entryType.WasPassed() ||
|
||||
mEntries[i]->GetEntryType().Equals(entryType.Value()))) {
|
||||
@ -478,7 +488,6 @@ void
|
||||
nsPerformance::ClearResourceTimings()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mPrimaryBufferSize = mBufferSizeSet;
|
||||
mEntries.Clear();
|
||||
}
|
||||
|
||||
@ -486,11 +495,7 @@ void
|
||||
nsPerformance::SetResourceTimingBufferSize(uint64_t maxSize)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mBufferSizeSet = maxSize;
|
||||
if (mBufferSizeSet < mEntries.Length()) {
|
||||
// call onresourcetimingbufferfull
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=936813
|
||||
}
|
||||
mPrimaryBufferSize = maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -506,6 +511,12 @@ nsPerformance::AddEntry(nsIHttpChannel* channel,
|
||||
if (!nsContentUtils::IsResourceTimingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't add the entry if the buffer is full
|
||||
if (mEntries.Length() >= mPrimaryBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (channel && timedChannel) {
|
||||
nsAutoCString name;
|
||||
nsAutoString initiatorType;
|
||||
@ -546,9 +557,9 @@ nsPerformance::AddEntry(nsIHttpChannel* channel,
|
||||
|
||||
mEntries.InsertElementSorted(performanceEntry,
|
||||
PerformanceEntryComparator());
|
||||
if (mEntries.Length() > mPrimaryBufferSize) {
|
||||
if (mEntries.Length() >= mPrimaryBufferSize) {
|
||||
// call onresourcetimingbufferfull
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=936813
|
||||
DispatchBufferFullEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
|
||||
class nsITimedChannel;
|
||||
class nsPerformance;
|
||||
@ -254,18 +255,17 @@ private:
|
||||
};
|
||||
|
||||
// Script "performance" object
|
||||
class nsPerformance MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class nsPerformance MOZ_FINAL : public mozilla::DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::PerformanceEntry PerformanceEntry;
|
||||
nsPerformance(nsIDOMWindow* aWindow,
|
||||
nsPerformance(nsPIDOMWindow* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
nsPerformance* aParentPerformance);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformance)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsPerformance, DOMEventTargetHelper)
|
||||
|
||||
nsDOMNavigationTiming* GetDOMTiming() const
|
||||
{
|
||||
@ -282,7 +282,7 @@ public:
|
||||
return mParentPerformance;
|
||||
}
|
||||
|
||||
nsIDOMWindow* GetParentObject() const
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return mWindow.get();
|
||||
}
|
||||
@ -304,18 +304,19 @@ public:
|
||||
nsITimedChannel* timedChannel);
|
||||
void ClearResourceTimings();
|
||||
void SetResourceTimingBufferSize(uint64_t maxSize);
|
||||
IMPL_EVENT_HANDLER(resourcetimingbufferfull)
|
||||
|
||||
private:
|
||||
~nsPerformance();
|
||||
void DispatchBufferFullEvent();
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsRefPtr<nsDOMNavigationTiming> mDOMTiming;
|
||||
nsCOMPtr<nsITimedChannel> mChannel;
|
||||
nsRefPtr<nsPerformanceTiming> mTiming;
|
||||
nsRefPtr<nsPerformanceNavigation> mNavigation;
|
||||
nsTArray<nsRefPtr<PerformanceEntry> > mEntries;
|
||||
nsRefPtr<nsPerformance> mParentPerformance;
|
||||
uint64_t mBufferSizeSet;
|
||||
uint64_t mPrimaryBufferSize;
|
||||
|
||||
static const uint64_t kDefaultBufferSize = 150;
|
||||
|
@ -11,19 +11,20 @@ browserElementTestHelpers.addPermission();
|
||||
function runTest() {
|
||||
var iframe1 = document.createElement('iframe');
|
||||
SpecialPowers.wrap(iframe1).mozbrowser = true;
|
||||
document.body.appendChild(iframe1);
|
||||
|
||||
iframe1.src = 'data:text/html,<html>' +
|
||||
'<body style="background:green">hello</body></html>';
|
||||
document.body.appendChild(iframe1);
|
||||
|
||||
var screenshotImageDatas = [];
|
||||
var numLoaded = 0;
|
||||
|
||||
function screenshotTaken(screenshotImageData) {
|
||||
screenshotImageDatas.push(screenshotImageData);
|
||||
function screenshotTaken(aScreenshotImageData) {
|
||||
screenshotImageDatas.push(aScreenshotImageData);
|
||||
|
||||
if (screenshotImageDatas.length === 1) {
|
||||
ok(true, 'Got initial non blank screenshot');
|
||||
|
||||
var view = screenshotImageData.data;
|
||||
var view = aScreenshotImageData.data;
|
||||
if (view[3] !== 255) {
|
||||
ok(false, 'The first pixel of initial screenshot is not opaque');
|
||||
SimpleTest.finish();
|
||||
@ -34,28 +35,13 @@ function runTest() {
|
||||
iframe1.src = 'data:text/html,<html>' +
|
||||
'<body style="background:transparent">hello</body></html>';
|
||||
|
||||
// Wait until screenshotImageData !== screenshotImageDatas[0].
|
||||
waitForScreenshot(function(screenshotImageData) {
|
||||
var view1 = screenshotImageData.data;
|
||||
var view2 = screenshotImageDatas[0].data;
|
||||
iframe1.addEventListener('mozbrowserloadend', ()=>takeScreenshot('image/png'));
|
||||
|
||||
if (view1.length != view2.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < view1.length; i++) {
|
||||
if (view1[i] != view2[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}, 'image/png');
|
||||
}
|
||||
else if (screenshotImageDatas.length === 2) {
|
||||
ok(true, 'Got updated screenshot after source page changed');
|
||||
|
||||
var view = screenshotImageData.data;
|
||||
var view = aScreenshotImageData.data;
|
||||
if (view[3] !== 0) {
|
||||
// The case here will always fail when oop'd on Firefox Desktop,
|
||||
// but not on B2G Emulator
|
||||
@ -79,15 +65,15 @@ function runTest() {
|
||||
|
||||
// We continually take screenshots until we get one that we are
|
||||
// happy with.
|
||||
function waitForScreenshot(filter, mimeType) {
|
||||
function takeScreenshot(mimeType) {
|
||||
function gotImage(e) {
|
||||
// |this| is the Image.
|
||||
|
||||
URL.revokeObjectURL(this.src);
|
||||
|
||||
if (e.type === 'error' || !this.width || !this.height) {
|
||||
tryAgain();
|
||||
|
||||
ok(false, "load image error");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -97,23 +83,7 @@ function runTest() {
|
||||
ctx.drawImage(this, 0, 0);
|
||||
var imageData = ctx.getImageData(0, 0, 1000, 1000);
|
||||
|
||||
if (filter(imageData)) {
|
||||
screenshotTaken(imageData);
|
||||
return;
|
||||
}
|
||||
tryAgain();
|
||||
}
|
||||
|
||||
function tryAgain() {
|
||||
if (--attempts === 0) {
|
||||
ok(false, 'Timed out waiting for correct screenshot');
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
iframe1.getScreenshot(1000, 1000, mimeType).onsuccess =
|
||||
getScreenshotImageData;
|
||||
}, 200);
|
||||
}
|
||||
screenshotTaken(imageData);
|
||||
}
|
||||
|
||||
function getScreenshotImageData(e) {
|
||||
@ -124,9 +94,8 @@ function runTest() {
|
||||
}
|
||||
|
||||
if (blob.size === 0) {
|
||||
tryAgain();
|
||||
|
||||
return;
|
||||
ok(false, "get screenshot image error");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var img = new Image();
|
||||
@ -134,18 +103,13 @@ function runTest() {
|
||||
img.onload = img.onerror = gotImage;
|
||||
}
|
||||
|
||||
var attempts = 10;
|
||||
iframe1.getScreenshot(1000, 1000, mimeType).onsuccess =
|
||||
getScreenshotImageData;
|
||||
}
|
||||
|
||||
function iframeLoadedHandler() {
|
||||
numLoaded++;
|
||||
if (numLoaded === 2) {
|
||||
waitForScreenshot(function(screenshotImageData) {
|
||||
return true;
|
||||
}, 'image/jpeg');
|
||||
}
|
||||
function iframeLoadedHandler(e) {
|
||||
iframe1.removeEventListener('mozbrowserloadend', iframeLoadedHandler);
|
||||
takeScreenshot('image/jpeg');
|
||||
}
|
||||
|
||||
iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler);
|
||||
|
@ -298,6 +298,13 @@ MaybeTestPBackground()
|
||||
#endif
|
||||
}
|
||||
|
||||
// XXX Workaround for bug 986973 to maintain the existing broken semantics
|
||||
template<>
|
||||
struct nsIConsoleService::COMTypeInfo<nsConsoleService, void> {
|
||||
static const nsIID kIID NS_HIDDEN;
|
||||
};
|
||||
const nsIID nsIConsoleService::COMTypeInfo<nsConsoleService, void>::kIID = NS_ICONSOLESERVICE_IID;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -59,6 +59,18 @@
|
||||
#undef GetCurrentTime
|
||||
#endif
|
||||
|
||||
// XXX Workaround for bug 986974 to maintain the existing broken semantics
|
||||
template<>
|
||||
struct nsIMediaDevice::COMTypeInfo<mozilla::VideoDevice, void> {
|
||||
static const nsIID kIID NS_HIDDEN;
|
||||
};
|
||||
const nsIID nsIMediaDevice::COMTypeInfo<mozilla::VideoDevice, void>::kIID = NS_IMEDIADEVICE_IID;
|
||||
template<>
|
||||
struct nsIMediaDevice::COMTypeInfo<mozilla::AudioDevice, void> {
|
||||
static const nsIID kIID NS_HIDDEN;
|
||||
};
|
||||
const nsIID nsIMediaDevice::COMTypeInfo<mozilla::AudioDevice, void>::kIID = NS_IMEDIADEVICE_IID;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef LOG
|
||||
|
@ -18,7 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=406375
|
||||
<script type="application/javascript">
|
||||
|
||||
if (navigator.platform.startsWith("Mac")) {
|
||||
SimpleTest.expectAssertions(2);
|
||||
SimpleTest.expectAssertions(1);
|
||||
}
|
||||
|
||||
/** Test for Bug 406375 **/
|
||||
|
@ -22,6 +22,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=760851
|
||||
// get tested as well.
|
||||
var toTest = [window.performance];
|
||||
|
||||
// The event handler has to be initialized or else jsonObj will be undefined
|
||||
window.performance.onresourcetimingbufferfull = function() {};
|
||||
|
||||
function checkAttributesMatch(obj, jsonObj) {
|
||||
if (typeof(obj) !== "object") {
|
||||
throw "Expected obj to be of type \"object\". Test failed.";
|
||||
|
@ -63,12 +63,19 @@ function isnot(received, notExpected, message) {
|
||||
window.opener.isnot(received, notExpected, message);
|
||||
}
|
||||
|
||||
var bufferFullCounter = 0;
|
||||
const expectedBufferFullEvents = 1;
|
||||
|
||||
window.onload = function() {
|
||||
ok(!!window.performance, "Performance object should exist");
|
||||
ok(!!window.performance.getEntries, "Performance.getEntries() should exist");
|
||||
ok(!!window.performance.getEntriesByName, "Performance.getEntriesByName() should exist");
|
||||
ok(!!window.performance.getEntriesByType, "Performance.getEntriesByType() should exist");
|
||||
|
||||
window.performance.onresourcetimingbufferfull = function() {
|
||||
bufferFullCounter += 1;
|
||||
}
|
||||
|
||||
// Here, we should have 6 entries (1 css, 3 png, 1 html) since the image was loaded.
|
||||
is(window.performance.getEntries().length, 5, "Performance.getEntries() returned wrong number of entries.");
|
||||
|
||||
@ -205,6 +212,7 @@ function secondCheck() {
|
||||
function finishTest() {
|
||||
// Check if all the tests are completed.
|
||||
if (iframeTestsDone) {
|
||||
is(bufferFullCounter, expectedBufferFullEvents, "onresourcetimingbufferfull called a wrong number of times");
|
||||
window.opener.finishTests();
|
||||
} else {
|
||||
mainWindowTestsDone = true;
|
||||
@ -232,6 +240,7 @@ function checkArraysHaveSameElementsInSameOrder(array1, array2) {
|
||||
|
||||
function iframeTestsCompleted() {
|
||||
if (mainWindowTestsDone) {
|
||||
is(bufferFullCounter, expectedBufferFullEvents, "onresourcetimingbufferfull called a wrong number of times");
|
||||
window.opener.finishTests();
|
||||
}
|
||||
else {
|
||||
|
@ -24,7 +24,7 @@ interface Performance {
|
||||
jsonifier;
|
||||
};
|
||||
|
||||
// http://www.w3c-test.org/webperf/specs/PerformanceTimeline/#sec-window.performance-attribute
|
||||
// http://www.w3.org/TR/performance-timeline/#sec-window.performance-attribute
|
||||
partial interface Performance {
|
||||
[Pref="dom.enable_resource_timing"]
|
||||
PerformanceEntryList getEntries();
|
||||
@ -35,10 +35,12 @@ partial interface Performance {
|
||||
entryType);
|
||||
};
|
||||
|
||||
// http://w3c-test.org/webperf/specs/ResourceTiming/#extensions-performance-interface
|
||||
// http://www.w3.org/TR/resource-timing/#extensions-performance-interface
|
||||
partial interface Performance {
|
||||
[Pref="dom.enable_resource_timing"]
|
||||
void clearResourceTimings();
|
||||
[Pref="dom.enable_resource_timing"]
|
||||
void setResourceTimingBufferSize(unsigned long maxSize);
|
||||
[Pref="dom.enable_resource_timing"]
|
||||
attribute EventHandler onresourcetimingbufferfull;
|
||||
};
|
||||
|
47
dom/webidl/SVGIFrameElement.webidl
Normal file
47
dom/webidl/SVGIFrameElement.webidl
Normal file
@ -0,0 +1,47 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.w3.org/Graphics/SVG/WG/wiki/Proposals/IFrame_Like_Syntax#5.12.14_Interface_SVGIFrameElement
|
||||
* but based
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/#the-iframe-element
|
||||
*
|
||||
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
|
||||
* Opera Software ASA. You are granted a license to use, reproduce
|
||||
* and create derivative works of this document.
|
||||
* Copyright © 2013 KDDI, Inc.
|
||||
*/
|
||||
|
||||
[Pref="svg.svg-iframe.enabled"]
|
||||
interface SVGIFrameElement : SVGGraphicsElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedLength x;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedLength y;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedLength width;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedLength height;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio;
|
||||
|
||||
[Constant]
|
||||
readonly attribute DOMString name;
|
||||
[Constant]
|
||||
readonly attribute DOMString src;
|
||||
[Constant]
|
||||
readonly attribute DOMString srcdoc;
|
||||
[PutForwards=value]
|
||||
readonly attribute DOMSettableTokenList sandbox;
|
||||
|
||||
// not implemented yet
|
||||
//[Constant]
|
||||
//readonly attribute SVGAnimatedBoolean seamless;
|
||||
|
||||
readonly attribute Document? contentDocument;
|
||||
readonly attribute WindowProxy? contentWindow;
|
||||
// not implemented yet
|
||||
//readonly attribute SVGAnimatedBoolean postpone;
|
||||
};
|
@ -370,6 +370,7 @@ WEBIDL_FILES = [
|
||||
'SVGGElement.webidl',
|
||||
'SVGGradientElement.webidl',
|
||||
'SVGGraphicsElement.webidl',
|
||||
'SVGIFrameElement.webidl',
|
||||
'SVGImageElement.webidl',
|
||||
'SVGLength.webidl',
|
||||
'SVGLengthList.webidl',
|
||||
|
@ -2444,7 +2444,7 @@ nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
|
||||
|
||||
|
||||
nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
Text* aTextNode,
|
||||
nsINode* aTextNode,
|
||||
int32_t aOffset,
|
||||
bool aSuppressIME)
|
||||
{
|
||||
|
@ -198,7 +198,7 @@ public:
|
||||
int32_t *aInOutOffset,
|
||||
nsIDOMDocument *aDoc);
|
||||
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
mozilla::dom::Text* aTextNode,
|
||||
nsINode* aTextNode,
|
||||
int32_t aOffset,
|
||||
bool aSuppressIME = false);
|
||||
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
|
@ -170,16 +170,25 @@ class nsEditableTextFunctor : public nsBoolDomIterFunctor
|
||||
* Constructor/Destructor
|
||||
********************************************************/
|
||||
|
||||
nsHTMLEditRules::nsHTMLEditRules() :
|
||||
mDocChangeRange(nullptr)
|
||||
,mListenerEnabled(true)
|
||||
,mReturnInEmptyLIKillsList(true)
|
||||
,mDidDeleteSelection(false)
|
||||
,mDidRangedDelete(false)
|
||||
,mRestoreContentEditableCount(false)
|
||||
,mUtilRange(nullptr)
|
||||
,mJoinOffset(0)
|
||||
nsHTMLEditRules::nsHTMLEditRules()
|
||||
{
|
||||
InitFields();
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLEditRules::InitFields()
|
||||
{
|
||||
mHTMLEditor = nullptr;
|
||||
mDocChangeRange = nullptr;
|
||||
mListenerEnabled = true;
|
||||
mReturnInEmptyLIKillsList = true;
|
||||
mDidDeleteSelection = false;
|
||||
mDidRangedDelete = false;
|
||||
mRestoreContentEditableCount = false;
|
||||
mUtilRange = nullptr;
|
||||
mJoinOffset = 0;
|
||||
mNewBlock = nullptr;
|
||||
mRangeItem = new nsRangeStore();
|
||||
// populate mCachedStyles
|
||||
mCachedStyles[0] = StyleCache(nsEditProperty::b, EmptyString(), EmptyString());
|
||||
mCachedStyles[1] = StyleCache(nsEditProperty::i, EmptyString(), EmptyString());
|
||||
@ -200,7 +209,6 @@ mDocChangeRange(nullptr)
|
||||
mCachedStyles[16] = StyleCache(nsEditProperty::cssBackgroundColor, EmptyString(), EmptyString());
|
||||
mCachedStyles[17] = StyleCache(nsEditProperty::sub, EmptyString(), EmptyString());
|
||||
mCachedStyles[18] = StyleCache(nsEditProperty::sup, EmptyString(), EmptyString());
|
||||
mRangeItem = new nsRangeStore();
|
||||
}
|
||||
|
||||
nsHTMLEditRules::~nsHTMLEditRules()
|
||||
@ -230,9 +238,11 @@ NS_IMPL_QUERY_INTERFACE_INHERITED(nsHTMLEditRules, nsTextEditRules, nsIEditActio
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditRules::Init(nsPlaintextEditor *aEditor)
|
||||
{
|
||||
InitFields();
|
||||
|
||||
mHTMLEditor = static_cast<nsHTMLEditor*>(aEditor);
|
||||
nsresult res;
|
||||
|
||||
|
||||
// call through to base class Init
|
||||
res = nsTextEditRules::Init(aEditor);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
@ -124,6 +124,8 @@ protected:
|
||||
kBlockEnd
|
||||
};
|
||||
|
||||
void InitFields();
|
||||
|
||||
// nsHTMLEditRules implementation methods
|
||||
nsresult WillInsert(nsISelection *aSelection, bool *aCancel);
|
||||
nsresult WillInsertText( EditAction aAction,
|
||||
|
@ -500,9 +500,10 @@ nsHTMLEditor::SetFlags(uint32_t aFlags)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::InitRules()
|
||||
{
|
||||
MOZ_ASSERT(!mRules);
|
||||
// instantiate the rules for the html editor
|
||||
mRules = new nsHTMLEditRules();
|
||||
if (!mRules) {
|
||||
// instantiate the rules for the html editor
|
||||
mRules = new nsHTMLEditRules();
|
||||
}
|
||||
return mRules->Init(static_cast<nsPlaintextEditor*>(this));
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ nsWSRunObject::DeleteWSBackward()
|
||||
// Caller's job to ensure that previous char is really ws. If it is normal
|
||||
// ws, we need to delete the whole run.
|
||||
if (nsCRT::IsAsciiSpace(point.mChar)) {
|
||||
nsCOMPtr<Text> startNodeText, endNodeText;
|
||||
nsCOMPtr<nsIContent> startNodeText, endNodeText;
|
||||
int32_t startOffset, endOffset;
|
||||
GetAsciiWSBounds(eBoth, point.mTextNode, point.mOffset + 1,
|
||||
getter_AddRefs(startNodeText), &startOffset,
|
||||
@ -1495,7 +1495,7 @@ nsWSRunObject::GetCharAfter(nsIDOMNode *aNode, int32_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(aNode);
|
||||
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
|
||||
nsCOMPtr<nsIContent> node(do_QueryInterface(aNode));
|
||||
int32_t idx = mNodeArray.IndexOf(node);
|
||||
if (idx == -1)
|
||||
{
|
||||
@ -1515,7 +1515,7 @@ nsWSRunObject::GetCharBefore(nsIDOMNode *aNode, int32_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(aNode);
|
||||
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
|
||||
nsCOMPtr<nsIContent> node(do_QueryInterface(aNode));
|
||||
int32_t idx = mNodeArray.IndexOf(node);
|
||||
if (idx == -1)
|
||||
{
|
||||
@ -1648,15 +1648,15 @@ nsWSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR)
|
||||
|
||||
void
|
||||
nsWSRunObject::GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
|
||||
Text** outStartNode, int32_t* outStartOffset,
|
||||
Text** outEndNode, int32_t* outEndOffset)
|
||||
nsIContent** outStartNode, int32_t* outStartOffset,
|
||||
nsIContent** outEndNode, int32_t* outEndOffset)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> outStartDOMNode, outEndDOMNode;
|
||||
GetAsciiWSBounds(aDir, GetAsDOMNode(aNode), aOffset,
|
||||
address_of(outStartDOMNode), outStartOffset,
|
||||
address_of(outEndDOMNode), outEndOffset);
|
||||
nsCOMPtr<Text> start(do_QueryInterface(outStartDOMNode));
|
||||
nsCOMPtr<Text> end(do_QueryInterface(outEndDOMNode));
|
||||
nsCOMPtr<nsIContent> start(do_QueryInterface(outStartDOMNode));
|
||||
nsCOMPtr<nsIContent> end(do_QueryInterface(outEndDOMNode));
|
||||
start.forget(outStartNode);
|
||||
end.forget(outEndNode);
|
||||
}
|
||||
@ -2001,7 +2001,7 @@ nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
|
||||
// editor softwraps at this point, the spaces won't be split across lines,
|
||||
// which looks ugly and is bad for the moose.
|
||||
|
||||
nsCOMPtr<Text> startNode, endNode;
|
||||
nsCOMPtr<nsIContent> startNode, endNode;
|
||||
int32_t startOffset, endOffset;
|
||||
GetAsciiWSBounds(eBoth, prevPoint.mTextNode, prevPoint.mOffset + 1,
|
||||
getter_AddRefs(startNode), &startOffset,
|
||||
|
@ -295,13 +295,13 @@ class MOZ_STACK_CLASS nsWSRunObject
|
||||
// stored in the struct.
|
||||
struct MOZ_STACK_CLASS WSPoint
|
||||
{
|
||||
nsCOMPtr<mozilla::dom::Text> mTextNode;
|
||||
nsCOMPtr<nsIContent> mTextNode;
|
||||
uint32_t mOffset;
|
||||
char16_t mChar;
|
||||
|
||||
WSPoint() : mTextNode(0),mOffset(0),mChar(0) {}
|
||||
WSPoint(nsINode* aNode, int32_t aOffset, char16_t aChar) :
|
||||
mTextNode(do_QueryInterface(aNode)),mOffset(aOffset),mChar(aChar)
|
||||
WSPoint(nsIContent* aNode, int32_t aOffset, char16_t aChar) :
|
||||
mTextNode(aNode),mOffset(aOffset),mChar(aChar)
|
||||
{
|
||||
MOZ_ASSERT(mTextNode->IsNodeOfType(nsINode::eTEXT));
|
||||
}
|
||||
@ -348,9 +348,9 @@ class MOZ_STACK_CLASS nsWSRunObject
|
||||
nsresult ConvertToNBSP(WSPoint aPoint,
|
||||
AreaRestriction aAR = eAnywhere);
|
||||
void GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
|
||||
mozilla::dom::Text** outStartNode,
|
||||
nsIContent** outStartNode,
|
||||
int32_t* outStartOffset,
|
||||
mozilla::dom::Text** outEndNode,
|
||||
nsIContent** outEndNode,
|
||||
int32_t* outEndOffset);
|
||||
void GetAsciiWSBounds(int16_t aDir, nsIDOMNode *aNode, int32_t aOffset,
|
||||
nsCOMPtr<nsIDOMNode> *outStartNode, int32_t *outStartOffset,
|
||||
|
@ -125,7 +125,6 @@ NS_IMETHODIMP nsPlaintextEditor::Init(nsIDOMDocument *aDoc,
|
||||
nsresult res = NS_OK, rulesRes = NS_OK;
|
||||
if (mRules) {
|
||||
mRules->DetachEditor();
|
||||
mRules = nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
@ -324,9 +323,10 @@ nsPlaintextEditor::UpdateMetaCharset(nsIDOMDocument* aDocument,
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::InitRules()
|
||||
{
|
||||
MOZ_ASSERT(!mRules);
|
||||
// instantiate the rules for this text editor
|
||||
mRules = new nsTextEditRules();
|
||||
if (!mRules) {
|
||||
// instantiate the rules for this text editor
|
||||
mRules = new nsTextEditRules();
|
||||
}
|
||||
return mRules->Init(this);
|
||||
}
|
||||
|
||||
|
@ -58,17 +58,28 @@ using namespace mozilla::dom;
|
||||
********************************************************/
|
||||
|
||||
nsTextEditRules::nsTextEditRules()
|
||||
: mEditor(nullptr)
|
||||
, mPasswordText()
|
||||
, mPasswordIMEText()
|
||||
, mPasswordIMEIndex(0)
|
||||
, mActionNesting(0)
|
||||
, mLockRulesSniffing(false)
|
||||
, mDidExplicitlySetInterline(false)
|
||||
, mTheAction(EditAction::none)
|
||||
, mLastStart(0)
|
||||
, mLastLength(0)
|
||||
{
|
||||
InitFields();
|
||||
}
|
||||
|
||||
void
|
||||
nsTextEditRules::InitFields()
|
||||
{
|
||||
mEditor = nullptr;
|
||||
mPasswordText.Truncate();
|
||||
mPasswordIMEText.Truncate();
|
||||
mPasswordIMEIndex = 0;
|
||||
mBogusNode = nullptr;
|
||||
mCachedSelectionNode = nullptr;
|
||||
mCachedSelectionOffset = 0;
|
||||
mActionNesting = 0;
|
||||
mLockRulesSniffing = false;
|
||||
mDidExplicitlySetInterline = false;
|
||||
mDeleteBidiImmediately = false;
|
||||
mTheAction = EditAction::none;
|
||||
mTimer = nullptr;
|
||||
mLastStart = 0;
|
||||
mLastLength = 0;
|
||||
}
|
||||
|
||||
nsTextEditRules::~nsTextEditRules()
|
||||
@ -103,6 +114,8 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor)
|
||||
{
|
||||
if (!aEditor) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
InitFields();
|
||||
|
||||
mEditor = aEditor; // we hold a non-refcounted reference back to our editor
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
|
@ -102,6 +102,8 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
void InitFields();
|
||||
|
||||
// nsTextEditRules implementation methods
|
||||
nsresult WillInsertText( EditAction aAction,
|
||||
mozilla::dom::Selection* aSelection,
|
||||
|
@ -92,7 +92,8 @@ struct BaseRect {
|
||||
// Always returns false if aRect is empty or 'this' is empty.
|
||||
bool Intersects(const Sub& aRect) const
|
||||
{
|
||||
return x < aRect.XMost() && aRect.x < XMost() &&
|
||||
return !IsEmpty() && !aRect.IsEmpty() &&
|
||||
x < aRect.XMost() && aRect.x < XMost() &&
|
||||
y < aRect.YMost() && aRect.y < YMost();
|
||||
}
|
||||
// Returns the rectangle containing the intersection of the points
|
||||
|
@ -90,6 +90,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
||||
aDestTarget->CopySurface(mSurface,
|
||||
IntRect(0, 0, mBounds.width, mBounds.height),
|
||||
IntPoint(0, 0));
|
||||
mSurface = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -153,32 +153,39 @@ static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) {
|
||||
#ifdef DEBUG
|
||||
static bool gDumpLayerSortList = getenv("MOZ_DUMP_LAYER_SORT_LIST") != 0;
|
||||
|
||||
static const int BLACK = 0;
|
||||
static const int RED = 1;
|
||||
static const int GREEN = 2;
|
||||
static const int YELLOW = 3;
|
||||
static const int BLUE = 4;
|
||||
static const int MAGENTA = 5;
|
||||
static const int CYAN = 6;
|
||||
static const int WHITE = 7;
|
||||
|
||||
//#define USE_XTERM_COLORING
|
||||
// #define USE_XTERM_COLORING
|
||||
#ifdef USE_XTERM_COLORING
|
||||
// List of color values, which can be added to the xterm foreground offset or
|
||||
// background offset to generate a xterm color code.
|
||||
// NOTE: The colors that we don't explicitly use (by name) are commented out,
|
||||
// to avoid triggering Wunused-const-variable build warnings.
|
||||
static const int XTERM_FOREGROUND_COLOR_OFFSET = 30;
|
||||
static const int XTERM_BACKGROUND_COLOR_OFFSET = 40;
|
||||
static const int BLACK = 0;
|
||||
//static const int RED = 1;
|
||||
static const int GREEN = 2;
|
||||
//static const int YELLOW = 3;
|
||||
//static const int BLUE = 4;
|
||||
//static const int MAGENTA = 5;
|
||||
//static const int CYAN = 6;
|
||||
//static const int WHITE = 7;
|
||||
|
||||
static const int RESET = 0;
|
||||
static const int BRIGHT = 1;
|
||||
static const int DIM = 2;
|
||||
static const int UNDERLINE = 3;
|
||||
static const int BLINK = 4;
|
||||
static const int REVERSE = 7;
|
||||
static const int HIDDEN = 8;
|
||||
// static const int BRIGHT = 1;
|
||||
// static const int DIM = 2;
|
||||
// static const int UNDERLINE = 3;
|
||||
// static const int BLINK = 4;
|
||||
// static const int REVERSE = 7;
|
||||
// static const int HIDDEN = 8;
|
||||
|
||||
static void SetTextColor(uint32_t aColor)
|
||||
{
|
||||
char command[13];
|
||||
|
||||
/* Command is the control command to the terminal */
|
||||
sprintf(command, "%c[%d;%d;%dm", 0x1B, RESET, aColor + 30, BLACK + 40);
|
||||
sprintf(command, "%c[%d;%d;%dm", 0x1B, RESET,
|
||||
aColor + XTERM_FOREGROUND_COLOR_OFFSET,
|
||||
BLACK + XTERM_BACKGROUND_COLOR_OFFSET);
|
||||
printf("%s", command);
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,7 @@ FindBackgroundLayer(ReadbackLayer* aLayer, nsIntPoint* aOffset)
|
||||
return nullptr;
|
||||
|
||||
if (l->GetEffectiveOpacity() != 1.0 ||
|
||||
l->GetMaskLayer() ||
|
||||
!(l->GetContentFlags() & Layer::CONTENT_OPAQUE))
|
||||
return nullptr;
|
||||
|
||||
|
@ -250,6 +250,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
|
||||
aParent->SetLastChild(apzc);
|
||||
} else {
|
||||
mRootApzc = apzc;
|
||||
apzc->MakeRoot();
|
||||
}
|
||||
|
||||
// Let this apzc be the parent of other controllers when we recurse downwards
|
||||
|
@ -791,6 +791,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Make this APZC the root of the APZC tree. Clears the parent pointer.
|
||||
void MakeRoot() {
|
||||
mParent = nullptr;
|
||||
}
|
||||
|
||||
AsyncPanZoomController* GetLastChild() const { return mLastChild; }
|
||||
AsyncPanZoomController* GetPrevSibling() const { return mPrevSibling; }
|
||||
AsyncPanZoomController* GetParent() const { return mParent; }
|
||||
|
@ -21,7 +21,9 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void
|
||||
BasicCanvasLayer::Paint(DrawTarget* aDT, Layer* aMaskLayer)
|
||||
BasicCanvasLayer::Paint(DrawTarget* aDT,
|
||||
const Point& aDeviceOffset,
|
||||
Layer* aMaskLayer)
|
||||
{
|
||||
if (IsHidden())
|
||||
return;
|
||||
@ -43,7 +45,7 @@ BasicCanvasLayer::Paint(DrawTarget* aDT, Layer* aMaskLayer)
|
||||
aDT->SetTransform(newTransform);
|
||||
}
|
||||
|
||||
FillRectWithMask(aDT,
|
||||
FillRectWithMask(aDT, aDeviceOffset,
|
||||
Rect(0, 0, mBounds.width, mBounds.height),
|
||||
mSurface, ToFilter(mFilter),
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
|
@ -34,7 +34,9 @@ public:
|
||||
CanvasLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
virtual void Paint(gfx::DrawTarget* aDT, Layer* aMaskLayer) MOZ_OVERRIDE;
|
||||
virtual void Paint(gfx::DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager()
|
||||
|
@ -44,7 +44,9 @@ public:
|
||||
ColorLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
virtual void Paint(DrawTarget* aDT, Layer* aMaskLayer) MOZ_OVERRIDE
|
||||
virtual void Paint(DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) MOZ_OVERRIDE
|
||||
{
|
||||
if (IsHidden()) {
|
||||
return;
|
||||
@ -57,7 +59,7 @@ public:
|
||||
snapped = mat.TransformBounds(snapped);
|
||||
}
|
||||
|
||||
FillRectWithMask(aDT, snapped, ToColor(mColor),
|
||||
FillRectWithMask(aDT, aDeviceOffset, snapped, ToColor(mColor),
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
aMaskLayer);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
@ -115,14 +116,19 @@ BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect)
|
||||
|
||||
void
|
||||
BasicContainerLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
{
|
||||
ReadbackProcessor readback;
|
||||
if (BasicManager()->IsRetained()) {
|
||||
readback.BuildUpdates(this);
|
||||
}
|
||||
for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
|
||||
BasicImplData* data = ToData(l);
|
||||
data->Validate(aCallback, aCallbackData);
|
||||
data->Validate(aCallback, aCallbackData, &readback);
|
||||
if (l->GetMaskLayer()) {
|
||||
data = ToData(l->GetMaskLayer());
|
||||
data->Validate(aCallback, aCallbackData);
|
||||
data->Validate(aCallback, aCallbackData, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,8 @@ public:
|
||||
void SetSupportsComponentAlphaChildren(bool aSupports) { mSupportsComponentAlphaChildren = aSupports; }
|
||||
|
||||
virtual void Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData) MOZ_OVERRIDE;
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager()
|
||||
|
@ -44,7 +44,9 @@ public:
|
||||
ImageLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
virtual void Paint(DrawTarget* aDT, Layer* aMaskLayer) MOZ_OVERRIDE;
|
||||
virtual void Paint(DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) MOZ_OVERRIDE;
|
||||
|
||||
virtual TemporaryRef<SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
|
||||
|
||||
@ -64,7 +66,9 @@ protected:
|
||||
};
|
||||
|
||||
void
|
||||
BasicImageLayer::Paint(DrawTarget* aDT, Layer* aMaskLayer)
|
||||
BasicImageLayer::Paint(DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer)
|
||||
{
|
||||
if (IsHidden() || !mContainer) {
|
||||
return;
|
||||
@ -81,7 +85,8 @@ BasicImageLayer::Paint(DrawTarget* aDT, Layer* aMaskLayer)
|
||||
return;
|
||||
}
|
||||
|
||||
FillRectWithMask(aDT, Rect(0, 0, size.width, size.height), surface, ToFilter(mFilter),
|
||||
FillRectWithMask(aDT, aDeviceOffset, Rect(0, 0, size.width, size.height),
|
||||
surface, ToFilter(mFilter),
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
aMaskLayer);
|
||||
|
||||
|
@ -59,7 +59,9 @@ public:
|
||||
* set up to account for all the properties of the layer (transform,
|
||||
* opacity, etc).
|
||||
*/
|
||||
virtual void Paint(gfx::DrawTarget* aDT, Layer* aMaskLayer) {}
|
||||
virtual void Paint(gfx::DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) {}
|
||||
|
||||
/**
|
||||
* Like Paint() but called for ThebesLayers with the additional parameters
|
||||
@ -70,11 +72,11 @@ public:
|
||||
virtual void PaintThebes(gfxContext* aContext,
|
||||
Layer* aMasklayer,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) {}
|
||||
void* aCallbackData) {}
|
||||
|
||||
virtual void Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData) {}
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) {}
|
||||
|
||||
/**
|
||||
* Layers will get this call when their layer manager is destroyed, this
|
||||
|
@ -137,13 +137,12 @@ class PaintLayerContext {
|
||||
public:
|
||||
PaintLayerContext(gfxContext* aTarget, Layer* aLayer,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData, ReadbackProcessor* aReadback)
|
||||
void* aCallbackData)
|
||||
: mTarget(aTarget)
|
||||
, mTargetMatrixSR(aTarget)
|
||||
, mLayer(aLayer)
|
||||
, mCallback(aCallback)
|
||||
, mCallbackData(aCallbackData)
|
||||
, mReadback(aReadback)
|
||||
, mPushedOpaqueRect(false)
|
||||
{}
|
||||
|
||||
@ -229,7 +228,6 @@ public:
|
||||
Layer* mLayer;
|
||||
LayerManager::DrawThebesLayerCallback mCallback;
|
||||
void* mCallbackData;
|
||||
ReadbackProcessor* mReadback;
|
||||
Matrix mTransform;
|
||||
bool mPushedOpaqueRect;
|
||||
};
|
||||
@ -593,9 +591,9 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
||||
mTarget ? !(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING) : true;
|
||||
mRoot->ComputeEffectiveTransforms(mTarget ? Matrix4x4::From2D(ToMatrix(mTarget->CurrentMatrix())) : Matrix4x4());
|
||||
|
||||
ToData(mRoot)->Validate(aCallback, aCallbackData);
|
||||
ToData(mRoot)->Validate(aCallback, aCallbackData, nullptr);
|
||||
if (mRoot->GetMaskLayer()) {
|
||||
ToData(mRoot->GetMaskLayer())->Validate(aCallback, aCallbackData);
|
||||
ToData(mRoot->GetMaskLayer())->Validate(aCallback, aCallbackData, nullptr);
|
||||
}
|
||||
|
||||
if (aFlags & END_NO_COMPOSITE) {
|
||||
@ -624,7 +622,7 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
||||
}
|
||||
}
|
||||
|
||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
|
||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData);
|
||||
if (!mRegionToClear.IsEmpty()) {
|
||||
AutoSetOperator op(mTarget, gfxContext::OPERATOR_CLEAR);
|
||||
nsIntRegionRectIterator iter(mRegionToClear);
|
||||
@ -831,24 +829,20 @@ BasicLayerManager::PaintSelfOrChildren(PaintLayerContext& aPaintContext,
|
||||
if (!child) {
|
||||
if (aPaintContext.mLayer->AsThebesLayer()) {
|
||||
data->PaintThebes(aGroupTarget, aPaintContext.mLayer->GetMaskLayer(),
|
||||
aPaintContext.mCallback, aPaintContext.mCallbackData,
|
||||
aPaintContext.mReadback);
|
||||
aPaintContext.mCallback, aPaintContext.mCallbackData);
|
||||
} else {
|
||||
data->Paint(aGroupTarget->GetDrawTarget(),
|
||||
aGroupTarget->GetDeviceOffset(),
|
||||
aPaintContext.mLayer->GetMaskLayer());
|
||||
}
|
||||
} else {
|
||||
ReadbackProcessor readback;
|
||||
ContainerLayer* container =
|
||||
static_cast<ContainerLayer*>(aPaintContext.mLayer);
|
||||
if (IsRetained()) {
|
||||
readback.BuildUpdates(container);
|
||||
}
|
||||
nsAutoTArray<Layer*, 12> children;
|
||||
container->SortChildrenBy3DZOrder(children);
|
||||
for (uint32_t i = 0; i < children.Length(); i++) {
|
||||
PaintLayer(aGroupTarget, children.ElementAt(i), aPaintContext.mCallback,
|
||||
aPaintContext.mCallbackData, &readback);
|
||||
aPaintContext.mCallbackData);
|
||||
if (mTransactionIncomplete)
|
||||
break;
|
||||
}
|
||||
@ -885,11 +879,10 @@ void
|
||||
BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
||||
Layer* aLayer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
void* aCallbackData)
|
||||
{
|
||||
PROFILER_LABEL("BasicLayerManager", "PaintLayer");
|
||||
PaintLayerContext paintLayerContext(aTarget, aLayer, aCallback, aCallbackData, aReadback);
|
||||
PaintLayerContext paintLayerContext(aTarget, aLayer, aCallback, aCallbackData);
|
||||
|
||||
// Don't attempt to paint layers with a singular transform, cairo will
|
||||
// just throw an error.
|
||||
|
@ -165,8 +165,7 @@ protected:
|
||||
void PaintLayer(gfxContext* aTarget,
|
||||
Layer* aLayer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback);
|
||||
void* aCallbackData);
|
||||
|
||||
// Clear the contents of a layer
|
||||
void ClearLayer(Layer* aLayer);
|
||||
|
@ -19,7 +19,9 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
bool
|
||||
GetMaskData(Layer* aMaskLayer, AutoMoz2DMaskData* aMaskData)
|
||||
GetMaskData(Layer* aMaskLayer,
|
||||
const Point& aDeviceOffset,
|
||||
AutoMoz2DMaskData* aMaskData)
|
||||
{
|
||||
if (aMaskLayer) {
|
||||
RefPtr<SourceSurface> surface =
|
||||
@ -29,6 +31,7 @@ GetMaskData(Layer* aMaskLayer, AutoMoz2DMaskData* aMaskData)
|
||||
Matrix4x4 effectiveTransform = aMaskLayer->GetEffectiveTransform();
|
||||
DebugOnly<bool> maskIs2D = effectiveTransform.CanDraw2D(&transform);
|
||||
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
|
||||
transform.Translate(-aDeviceOffset.x, -aDeviceOffset.y);
|
||||
aMaskData->Construct(transform, surface);
|
||||
return true;
|
||||
}
|
||||
@ -40,7 +43,7 @@ void
|
||||
PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
|
||||
{
|
||||
AutoMoz2DMaskData mask;
|
||||
if (GetMaskData(aMaskLayer, &mask)) {
|
||||
if (GetMaskData(aMaskLayer, Point(), &mask)) {
|
||||
if (aOpacity < 1.0) {
|
||||
aContext->PushGroup(gfxContentType::COLOR_ALPHA);
|
||||
aContext->Paint(aOpacity);
|
||||
@ -78,13 +81,14 @@ FillRectWithMask(DrawTarget* aDT,
|
||||
}
|
||||
void
|
||||
FillRectWithMask(DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
const Rect& aRect,
|
||||
const Color& aColor,
|
||||
const DrawOptions& aOptions,
|
||||
Layer* aMaskLayer)
|
||||
{
|
||||
AutoMoz2DMaskData mask;
|
||||
if (GetMaskData(aMaskLayer, &mask)) {
|
||||
if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) {
|
||||
const Matrix& maskTransform = mask.GetTransform();
|
||||
FillRectWithMask(aDT, aRect, aColor, aOptions, mask.GetSurface(), &maskTransform);
|
||||
return;
|
||||
@ -133,6 +137,7 @@ FillRectWithMask(DrawTarget* aDT,
|
||||
|
||||
void
|
||||
FillRectWithMask(DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
const Rect& aRect,
|
||||
SourceSurface* aSurface,
|
||||
Filter aFilter,
|
||||
@ -140,7 +145,7 @@ FillRectWithMask(DrawTarget* aDT,
|
||||
Layer* aMaskLayer)
|
||||
{
|
||||
AutoMoz2DMaskData mask;
|
||||
if (GetMaskData(aMaskLayer, &mask)) {
|
||||
if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) {
|
||||
const Matrix& maskTransform = mask.GetTransform();
|
||||
FillRectWithMask(aDT, aRect, aSurface, aFilter, aOptions, ExtendMode::CLAMP,
|
||||
mask.GetSurface(), &maskTransform);
|
||||
|
@ -82,7 +82,9 @@ protected:
|
||||
* The transform for the layer will be put in aMaskData
|
||||
*/
|
||||
bool
|
||||
GetMaskData(Layer* aMaskLayer, AutoMoz2DMaskData* aMaskData);
|
||||
GetMaskData(Layer* aMaskLayer,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
AutoMoz2DMaskData* aMaskData);
|
||||
|
||||
// Paint the current source to a context using a mask, if present
|
||||
void
|
||||
@ -108,6 +110,7 @@ FillRectWithMask(gfx::DrawTarget* aDT,
|
||||
const gfx::Matrix* aSurfaceTransform = nullptr);
|
||||
void
|
||||
FillRectWithMask(gfx::DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
const gfx::Rect& aRect,
|
||||
gfx::SourceSurface* aSurface,
|
||||
gfx::Filter aFilter,
|
||||
@ -115,6 +118,7 @@ FillRectWithMask(gfx::DrawTarget* aDT,
|
||||
Layer* aMaskLayer);
|
||||
void
|
||||
FillRectWithMask(gfx::DrawTarget* aDT,
|
||||
const gfx::Point& aDeviceOffset,
|
||||
const gfx::Rect& aRect,
|
||||
const gfx::Color& aColor,
|
||||
const gfx::DrawOptions& aOptions,
|
||||
|
@ -48,24 +48,16 @@ void
|
||||
BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
||||
Layer* aMaskLayer,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
void* aCallbackData)
|
||||
{
|
||||
PROFILER_LABEL("BasicThebesLayer", "PaintThebes");
|
||||
NS_ASSERTION(BasicManager()->InDrawing(),
|
||||
"Can only draw in drawing phase");
|
||||
|
||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||
if (aReadback && UsedForReadback()) {
|
||||
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
|
||||
}
|
||||
|
||||
float opacity = GetEffectiveOpacity();
|
||||
CompositionOp effectiveOperator = GetEffectiveOperator(this);
|
||||
|
||||
if (!BasicManager()->IsRetained()) {
|
||||
NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
|
||||
|
||||
mValidRegion.SetEmpty();
|
||||
mContentClient->Clear();
|
||||
|
||||
@ -125,7 +117,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
||||
AutoMoz2DMaskData mask;
|
||||
SourceSurface* maskSurface = nullptr;
|
||||
Matrix maskTransform;
|
||||
if (GetMaskData(aMaskLayer, &mask)) {
|
||||
if (GetMaskData(aMaskLayer, Point(), &mask)) {
|
||||
maskSurface = mask.GetSurface();
|
||||
maskTransform = mask.GetTransform();
|
||||
}
|
||||
@ -135,27 +127,12 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
||||
effectiveOperator,
|
||||
maskSurface, &maskTransform);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
|
||||
ReadbackProcessor::Update& update = readbackUpdates[i];
|
||||
nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
|
||||
update.mSequenceCounter);
|
||||
if (ctx) {
|
||||
NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
|
||||
ctx->Translate(gfxPoint(offset.x, offset.y));
|
||||
mContentClient->DrawTo(this, ctx->GetDrawTarget(), 1.0,
|
||||
CompositionOpForOp(ctx->CurrentOperator()),
|
||||
maskSurface, &maskTransform);
|
||||
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
{
|
||||
if (!mContentClient) {
|
||||
// This client will have a null Forwarder, which means it will not have
|
||||
@ -167,6 +144,11 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||
if (aReadback && UsedForReadback()) {
|
||||
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
|
||||
}
|
||||
|
||||
uint32_t flags = 0;
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
if (BasicManager()->CompositorMightResample()) {
|
||||
@ -215,6 +197,23 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||
NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
|
||||
"No context when we have something to draw, resource exhaustion?");
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
|
||||
ReadbackProcessor::Update& update = readbackUpdates[i];
|
||||
nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
|
||||
update.mSequenceCounter);
|
||||
if (ctx) {
|
||||
NS_ASSERTION(GetEffectiveOpacity() == 1.0, "Should only read back opaque layers");
|
||||
NS_ASSERTION(!GetMaskLayer(), "Should only read back layers without masks");
|
||||
ctx->Translate(gfxPoint(offset.x, offset.y));
|
||||
mContentClient->DrawTo(this, ctx->GetDrawTarget(), 1.0,
|
||||
CompositionOpForOp(ctx->CurrentOperator()),
|
||||
nullptr, nullptr);
|
||||
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ThebesLayer>
|
||||
|
@ -59,11 +59,11 @@ public:
|
||||
virtual void PaintThebes(gfxContext* aContext,
|
||||
Layer* aMaskLayer,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback);
|
||||
void* aCallbackData);
|
||||
|
||||
virtual void Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData) MOZ_OVERRIDE;
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) MOZ_OVERRIDE;
|
||||
|
||||
virtual void ClearCachedResources()
|
||||
{
|
||||
|
449
gfx/layers/composite/FPSCounter.cpp
Normal file
449
gfx/layers/composite/FPSCounter.cpp
Normal file
@ -0,0 +1,449 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 <stddef.h> // for size_t
|
||||
#include "Units.h" // for ScreenIntRect
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfxPrefs.h" // for gfxPrefs
|
||||
#include "mozilla/gfx/Point.h" // for IntSize, Point
|
||||
#include "mozilla/gfx/Rect.h" // for Rect
|
||||
#include "mozilla/gfx/Types.h" // for Color, SurfaceFormat
|
||||
#include "mozilla/layers/Compositor.h" // for Compositor
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsIFile.h" // for nsIFile
|
||||
#include "nsDirectoryServiceDefs.h" // for NS_OS_TMP_DIR
|
||||
#include "prprf.h" // for PR_snprintf
|
||||
#include "FPSCounter.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
FPSCounter::FPSCounter(const char* aName)
|
||||
: mWriteIndex(0)
|
||||
, mFPSName(aName)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
FPSCounter::~FPSCounter() { }
|
||||
|
||||
void
|
||||
FPSCounter::Init()
|
||||
{
|
||||
for (int i = 0; i < kMaxFrames; i++) {
|
||||
mFrameTimestamps.AppendElement(TimeStamp());
|
||||
}
|
||||
mLastInterval = TimeStamp::Now();
|
||||
}
|
||||
|
||||
// Returns true if we captured a full interval of data
|
||||
bool
|
||||
FPSCounter::CapturedFullInterval(TimeStamp aTimestamp) {
|
||||
TimeDuration duration = aTimestamp - mLastInterval;
|
||||
return duration.ToSecondsSigDigits() >= kFpsDumpInterval;
|
||||
}
|
||||
|
||||
void
|
||||
FPSCounter::AddFrame(TimeStamp aTimestamp) {
|
||||
NS_ASSERTION(mWriteIndex < kMaxFrames, "We probably have a bug with the circular buffer");
|
||||
NS_ASSERTION(mWriteIndex >= 0, "Circular Buffer index should never be negative");
|
||||
|
||||
int index = mWriteIndex++;
|
||||
if (mWriteIndex == kMaxFrames) {
|
||||
mWriteIndex = 0;
|
||||
}
|
||||
|
||||
mFrameTimestamps[index] = aTimestamp;
|
||||
|
||||
if (CapturedFullInterval(aTimestamp)) {
|
||||
PrintFPS();
|
||||
WriteFrameTimeStamps();
|
||||
mLastInterval = aTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
FPSCounter::AddFrameAndGetFps(TimeStamp aTimestamp) {
|
||||
AddFrame(aTimestamp);
|
||||
return GetFPS(aTimestamp);
|
||||
}
|
||||
|
||||
int
|
||||
FPSCounter::GetLatestReadIndex()
|
||||
{
|
||||
if (mWriteIndex == 0) {
|
||||
return kMaxFrames - 1;
|
||||
}
|
||||
|
||||
return mWriteIndex - 1;
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
FPSCounter::GetLatestTimeStamp()
|
||||
{
|
||||
TimeStamp timestamp = mFrameTimestamps[GetLatestReadIndex()];
|
||||
MOZ_ASSERT(!timestamp.IsNull(), "Cannot use null timestamps");
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
// Returns true if we iterated over a full interval of data
|
||||
bool
|
||||
FPSCounter::IteratedFullInterval(TimeStamp aTimestamp, double aDuration) {
|
||||
MOZ_ASSERT(mIteratorIndex >= 0, "Cannot be negative");
|
||||
MOZ_ASSERT(mIteratorIndex < kMaxFrames, "Iterator index cannot be greater than kMaxFrames");
|
||||
|
||||
TimeStamp currentStamp = mFrameTimestamps[mIteratorIndex];
|
||||
TimeDuration duration = aTimestamp - currentStamp;
|
||||
return duration.ToSecondsSigDigits() >= aDuration;
|
||||
}
|
||||
|
||||
void
|
||||
FPSCounter::ResetReverseIterator()
|
||||
{
|
||||
mIteratorIndex = GetLatestReadIndex();
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns true if we have another timestamp that is valid and
|
||||
* is within the given duration that we're interested in.
|
||||
* Duration is in seconds
|
||||
*/
|
||||
bool FPSCounter::HasNext(TimeStamp aTimestamp, double aDuration)
|
||||
{
|
||||
// Order of evaluation here has to stay the same
|
||||
// otherwise IteratedFullInterval reads from mFrameTimestamps which cannot
|
||||
// be null
|
||||
return (mIteratorIndex != mWriteIndex) // Didn't loop around the buffer
|
||||
&& !mFrameTimestamps[mIteratorIndex].IsNull() // valid data
|
||||
&& !IteratedFullInterval(aTimestamp, aDuration);
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
FPSCounter::GetNextTimeStamp()
|
||||
{
|
||||
TimeStamp timestamp = mFrameTimestamps[mIteratorIndex--];
|
||||
MOZ_ASSERT(!timestamp.IsNull(), "Reading Invalid Timestamp Data");
|
||||
|
||||
if (mIteratorIndex == -1) {
|
||||
mIteratorIndex = kMaxFrames - 1;
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetFPS calculates how many frames we've already composited from the current
|
||||
* frame timestamp and we iterate from the latest timestamp we recorded,
|
||||
* going back in time. When we hit a frame that is longer than the 1 second
|
||||
* from the current composited frame, we return how many frames we've counted.
|
||||
* Just a visualization:
|
||||
*
|
||||
* aTimestamp
|
||||
* Frames: 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
* Time -------------------------->
|
||||
*
|
||||
* GetFPS iterates from aTimestamp, which is the current frame.
|
||||
* Then starting at frame 12, going back to frame 11, 10, etc, we calculate
|
||||
* the duration of the recorded frame timestamp from aTimestamp.
|
||||
* Once duration is greater than 1 second, we return how many frames
|
||||
* we composited.
|
||||
*/
|
||||
double
|
||||
FPSCounter::GetFPS(TimeStamp aTimestamp)
|
||||
{
|
||||
int frameCount = 0;
|
||||
int duration = 1.0; // Only care about the last 1s of data
|
||||
|
||||
ResetReverseIterator();
|
||||
while (HasNext(aTimestamp, duration)) {
|
||||
GetNextTimeStamp();
|
||||
frameCount++;
|
||||
}
|
||||
|
||||
return frameCount;
|
||||
}
|
||||
|
||||
// Iterate the same way we do in GetFPS()
|
||||
int
|
||||
FPSCounter::BuildHistogram(std::map<int, int>& aFpsData)
|
||||
{
|
||||
TimeStamp currentIntervalStart = GetLatestTimeStamp();
|
||||
TimeStamp currentTimeStamp = GetLatestTimeStamp();
|
||||
TimeStamp startTimeStamp = GetLatestTimeStamp();
|
||||
|
||||
int frameCount = 0;
|
||||
int totalFrameCount = 0;
|
||||
|
||||
ResetReverseIterator();
|
||||
while (HasNext(startTimeStamp)) {
|
||||
currentTimeStamp = GetNextTimeStamp();
|
||||
TimeDuration interval = currentIntervalStart - currentTimeStamp;
|
||||
|
||||
if (interval.ToSecondsSigDigits() >= 1.0 ) {
|
||||
currentIntervalStart = currentTimeStamp;
|
||||
aFpsData[frameCount]++;
|
||||
frameCount = 0;
|
||||
}
|
||||
|
||||
frameCount++;
|
||||
totalFrameCount++;
|
||||
}
|
||||
|
||||
TimeDuration totalTime = currentIntervalStart - currentTimeStamp;
|
||||
printf_stderr("Discarded %d frames over %f ms in histogram for %s\n",
|
||||
frameCount, totalTime.ToMilliseconds(), mFPSName);
|
||||
return totalFrameCount;
|
||||
}
|
||||
|
||||
// Iterate the same way we do in GetFPS()
|
||||
void
|
||||
FPSCounter::WriteFrameTimeStamps(PRFileDesc* fd)
|
||||
{
|
||||
const int bufferSize = 256;
|
||||
char buffer[bufferSize];
|
||||
int writtenCount = PR_snprintf(buffer, bufferSize, "FPS Data for: %s\n", mFPSName);
|
||||
MOZ_ASSERT(writtenCount >= 0);
|
||||
PR_Write(fd, buffer, writtenCount);
|
||||
|
||||
ResetReverseIterator();
|
||||
TimeStamp startTimeStamp = GetLatestTimeStamp();
|
||||
|
||||
MOZ_ASSERT(HasNext(startTimeStamp));
|
||||
TimeStamp previousSample = GetNextTimeStamp();
|
||||
|
||||
MOZ_ASSERT(HasNext(startTimeStamp));
|
||||
TimeStamp nextTimeStamp = GetNextTimeStamp();
|
||||
|
||||
while (HasNext(startTimeStamp)) {
|
||||
TimeDuration duration = previousSample - nextTimeStamp;
|
||||
writtenCount = PR_snprintf(buffer, bufferSize, "%f,\n", duration.ToMilliseconds());
|
||||
|
||||
MOZ_ASSERT(writtenCount >= 0);
|
||||
PR_Write(fd, buffer, writtenCount);
|
||||
|
||||
previousSample = nextTimeStamp;
|
||||
nextTimeStamp = GetNextTimeStamp();
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
FPSCounter::GetMean(std::map<int, int> aHistogram)
|
||||
{
|
||||
double average = 0.0;
|
||||
double samples = 0.0;
|
||||
|
||||
for (std::map<int, int>::iterator iter = aHistogram.begin();
|
||||
iter != aHistogram.end(); ++iter)
|
||||
{
|
||||
int fps = iter->first;
|
||||
int count = iter->second;
|
||||
|
||||
average += fps * count;
|
||||
samples += count;
|
||||
}
|
||||
|
||||
return average / samples;
|
||||
}
|
||||
|
||||
double
|
||||
FPSCounter::GetStdDev(std::map<int, int> aHistogram)
|
||||
{
|
||||
double sumOfDifferences = 0;
|
||||
double average = GetMean(aHistogram);
|
||||
double samples = 0.0;
|
||||
|
||||
for (std::map<int, int>::iterator iter = aHistogram.begin();
|
||||
iter != aHistogram.end(); ++iter)
|
||||
{
|
||||
int fps = iter->first;
|
||||
int count = iter->second;
|
||||
|
||||
double diff = ((double) fps) - average;
|
||||
diff *= diff;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
sumOfDifferences += diff;
|
||||
}
|
||||
samples += count;
|
||||
}
|
||||
|
||||
double stdDev = sumOfDifferences / samples;
|
||||
return sqrt(stdDev);
|
||||
}
|
||||
|
||||
void
|
||||
FPSCounter::PrintFPS()
|
||||
{
|
||||
if (!gfxPrefs::FPSPrintHistogram()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<int, int> histogram;
|
||||
int totalFrames = BuildHistogram(histogram);
|
||||
|
||||
TimeDuration measurementInterval = mFrameTimestamps[GetLatestReadIndex()] - mLastInterval;
|
||||
printf_stderr("FPS for %s. Total Frames: %d Time Interval: %f seconds\n",
|
||||
mFPSName, totalFrames, measurementInterval.ToSecondsSigDigits());
|
||||
|
||||
PrintHistogram(histogram);
|
||||
}
|
||||
|
||||
void
|
||||
FPSCounter::PrintHistogram(std::map<int, int>& aHistogram)
|
||||
{
|
||||
int length = 0;
|
||||
const int kBufferLength = 512;
|
||||
char buffer[kBufferLength];
|
||||
|
||||
for (std::map<int, int>::iterator iter = aHistogram.begin();
|
||||
iter != aHistogram.end(); iter++)
|
||||
{
|
||||
int fps = iter->first;
|
||||
int count = iter->second;
|
||||
|
||||
length += PR_snprintf(buffer + length, kBufferLength - length,
|
||||
"FPS: %d = %d. ", fps, count);
|
||||
NS_ASSERTION(length >= kBufferLength, "Buffer overrun while printing FPS histogram.");
|
||||
}
|
||||
|
||||
printf_stderr("%s\n", buffer);
|
||||
printf_stderr("Mean: %f , std dev %f\n", GetMean(aHistogram), GetStdDev(aHistogram));
|
||||
}
|
||||
|
||||
// Write FPS timestamp data to a file only if
|
||||
// draw-fps.write-to-file is true
|
||||
nsresult
|
||||
FPSCounter::WriteFrameTimeStamps()
|
||||
{
|
||||
if (!gfxPrefs::WriteFPSToFile()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mWriteIndex == 0);
|
||||
|
||||
nsCOMPtr<nsIFile> resultFile;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(resultFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!strncmp(mFPSName, "Compositor", strlen(mFPSName))) {
|
||||
resultFile->Append(NS_LITERAL_STRING("fps.txt"));
|
||||
} else {
|
||||
resultFile->Append(NS_LITERAL_STRING("txn.txt"));
|
||||
}
|
||||
|
||||
PRFileDesc* fd = nullptr;
|
||||
int mode = 644;
|
||||
int openFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
|
||||
rv = resultFile->OpenNSPRFileDesc(openFlags, mode, &fd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
WriteFrameTimeStamps(fd);
|
||||
PR_Close(fd);
|
||||
|
||||
nsAutoCString path;
|
||||
rv = resultFile->GetNativePath(path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
printf_stderr("Wrote FPS data to file: %s\n", path.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
FPSState::FPSState()
|
||||
: mCompositionFps("Compositor")
|
||||
, mTransactionFps("LayerTransactions")
|
||||
{
|
||||
}
|
||||
|
||||
// Size of the builtin font.
|
||||
static const float FontHeight = 7.f;
|
||||
static const float FontWidth = 4.f;
|
||||
static const float FontStride = 4.f;
|
||||
|
||||
// Scale the font when drawing it to the viewport for better readability.
|
||||
static const float FontScaleX = 2.f;
|
||||
static const float FontScaleY = 3.f;
|
||||
|
||||
static void DrawDigits(unsigned int aValue,
|
||||
int aOffsetX, int aOffsetY,
|
||||
Compositor* aCompositor,
|
||||
EffectChain& aEffectChain)
|
||||
{
|
||||
if (aValue > 999) {
|
||||
aValue = 999;
|
||||
}
|
||||
|
||||
unsigned int divisor = 100;
|
||||
float textureWidth = FontWidth * 10;
|
||||
gfx::Float opacity = 1;
|
||||
gfx::Matrix4x4 transform;
|
||||
transform.Scale(FontScaleX, FontScaleY, 1);
|
||||
|
||||
for (size_t n = 0; n < 3; ++n) {
|
||||
unsigned int digit = aValue % (divisor * 10) / divisor;
|
||||
divisor /= 10;
|
||||
|
||||
RefPtr<TexturedEffect> texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
|
||||
texturedEffect->mTextureCoords = Rect(float(digit * FontWidth) / textureWidth, 0, FontWidth / textureWidth, 1.0f);
|
||||
|
||||
Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight);
|
||||
Rect clipRect = Rect(0, 0, 300, 100);
|
||||
aCompositor->DrawQuad(drawRect, clipRect,
|
||||
aEffectChain, opacity, transform);
|
||||
}
|
||||
}
|
||||
|
||||
void FPSState::DrawFPS(TimeStamp aNow,
|
||||
int aOffsetX, int aOffsetY,
|
||||
unsigned int aFillRatio,
|
||||
Compositor* aCompositor)
|
||||
{
|
||||
if (!mFPSTextureSource) {
|
||||
const char *text =
|
||||
" "
|
||||
" XXX XX XXX XXX X X XXX XXX XXX XXX XXX"
|
||||
" X X X X X X X X X X X X X X"
|
||||
" X X X XXX XXX XXX XXX XXX X XXX XXX"
|
||||
" X X X X X X X X X X X X X"
|
||||
" XXX XXX XXX XXX X XXX XXX X XXX X"
|
||||
" ";
|
||||
|
||||
// Convert the text encoding above to RGBA.
|
||||
int w = FontWidth * 10;
|
||||
int h = FontHeight;
|
||||
uint32_t* buf = (uint32_t *) malloc(w * h * sizeof(uint32_t));
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
uint32_t purple = 0xfff000ff;
|
||||
uint32_t white = 0xffffffff;
|
||||
buf[i * w + j] = (text[i * w + j] == ' ') ? purple : white;
|
||||
}
|
||||
}
|
||||
|
||||
int bytesPerPixel = 4;
|
||||
RefPtr<DataSourceSurface> fpsSurface = Factory::CreateWrappingDataSourceSurface(
|
||||
reinterpret_cast<uint8_t*>(buf), w * bytesPerPixel, IntSize(w, h), SurfaceFormat::B8G8R8A8);
|
||||
mFPSTextureSource = aCompositor->CreateDataTextureSource();
|
||||
mFPSTextureSource->Update(fpsSurface);
|
||||
}
|
||||
|
||||
EffectChain effectChain;
|
||||
effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mFPSTextureSource, Filter::POINT);
|
||||
|
||||
unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
|
||||
unsigned int txnFps = unsigned(mTransactionFps.GetFPS(aNow));
|
||||
|
||||
DrawDigits(fps, aOffsetX + 0, aOffsetY, aCompositor, effectChain);
|
||||
DrawDigits(txnFps, aOffsetX + FontWidth * 4, aOffsetY, aCompositor, effectChain);
|
||||
DrawDigits(aFillRatio, aOffsetX + FontWidth * 8, aOffsetY, aCompositor, effectChain);
|
||||
}
|
||||
|
||||
} // end namespace layers
|
||||
} // end namespace mozilla
|
@ -6,12 +6,15 @@
|
||||
#ifndef mozilla_layers_opengl_FPSCounter_h_
|
||||
#define mozilla_layers_opengl_FPSCounter_h_
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <algorithm> // for min
|
||||
#include <stddef.h> // for size_t
|
||||
#include <map> // for std::map
|
||||
#include "GLDefs.h" // for GLuint
|
||||
#include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
|
||||
#include "nsTArray.h" // for nsAutoTArray, nsTArray_Impl, etc
|
||||
#include "VBOArena.h" // for gl::VBOArena
|
||||
#include "prio.h" // for NSPR file i/o
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
@ -21,68 +24,91 @@ namespace layers {
|
||||
|
||||
class DataTextureSource;
|
||||
class ShaderProgramOGL;
|
||||
class Compositor;
|
||||
|
||||
const double kFpsWindowMs = 250.0;
|
||||
const size_t kNumFrameTimeStamps = 16;
|
||||
struct FPSCounter {
|
||||
FPSCounter() : mCurrentFrameIndex(0) {
|
||||
mFrames.SetLength(kNumFrameTimeStamps);
|
||||
}
|
||||
// Dump the FPS histogram every 10 seconds or kMaxFrameFPS
|
||||
const int kFpsDumpInterval = 10;
|
||||
|
||||
// We keep a circular buffer of the time points at which the last K
|
||||
// frames were drawn. To estimate FPS, we count the number of
|
||||
// frames we've drawn within the last kFPSWindowMs milliseconds and
|
||||
// divide by the amount time since the first of those frames.
|
||||
nsAutoTArray<TimeStamp, kNumFrameTimeStamps> mFrames;
|
||||
size_t mCurrentFrameIndex;
|
||||
// On desktop, we can have 240 hz monitors, so 10 seconds
|
||||
// times 240 frames = 2400
|
||||
const int kMaxFrames = 2400;
|
||||
|
||||
void AddFrame(TimeStamp aNewFrame) {
|
||||
mFrames[mCurrentFrameIndex] = aNewFrame;
|
||||
mCurrentFrameIndex = (mCurrentFrameIndex + 1) % kNumFrameTimeStamps;
|
||||
}
|
||||
/**
|
||||
* The FPSCounter tracks how often we composite or have a layer transaction.
|
||||
* At each composite / layer transaction, we record the timestamp.
|
||||
* After kFpsDumpInterval number of composites / transactions, we calculate
|
||||
* the average and standard deviation of frames composited. We dump a histogram,
|
||||
* which allows for more statistically significant measurements. We also dump
|
||||
* absolute frame composite times to a file on the device.
|
||||
* The FPS counters displayed on screen are based on how many frames we
|
||||
* composited within the last ~1 second. The more accurate measurement is to
|
||||
* grab the histogram from stderr or grab the FPS timestamp dumps written to file.
|
||||
*
|
||||
* To enable dumping to file, enable
|
||||
* layers.acceleration.draw-fps.write-to-file pref.
|
||||
|
||||
double AddFrameAndGetFps(TimeStamp aCurrentFrame) {
|
||||
AddFrame(aCurrentFrame);
|
||||
return EstimateFps(aCurrentFrame);
|
||||
}
|
||||
* To enable printing histogram data to logcat,
|
||||
* enable layers.acceleration.draw-fps.print-histogram
|
||||
*
|
||||
* Use the HasNext(), GetNextTimeStamp() like an iterator to read the data,
|
||||
* backwards in time. This abstracts away the mechanics of reading the data.
|
||||
*/
|
||||
class FPSCounter {
|
||||
public:
|
||||
FPSCounter(const char* aName);
|
||||
~FPSCounter();
|
||||
|
||||
double GetFpsAt(TimeStamp aNow) {
|
||||
return EstimateFps(aNow);
|
||||
}
|
||||
void AddFrame(TimeStamp aTimestamp);
|
||||
double AddFrameAndGetFps(TimeStamp aTimestamp);
|
||||
double GetFPS(TimeStamp aTimestamp);
|
||||
|
||||
private:
|
||||
double EstimateFps(TimeStamp aNow) {
|
||||
TimeStamp beginningOfWindow =
|
||||
(aNow - TimeDuration::FromMilliseconds(kFpsWindowMs));
|
||||
TimeStamp earliestFrameInWindow = aNow;
|
||||
size_t numFramesDrawnInWindow = 0;
|
||||
for (size_t i = 0; i < kNumFrameTimeStamps; ++i) {
|
||||
const TimeStamp& frame = mFrames[i];
|
||||
if (!frame.IsNull() && frame > beginningOfWindow) {
|
||||
++numFramesDrawnInWindow;
|
||||
earliestFrameInWindow = std::min(earliestFrameInWindow, frame);
|
||||
}
|
||||
}
|
||||
double realWindowSecs = (aNow - earliestFrameInWindow).ToSeconds();
|
||||
if (realWindowSecs == 0.0 || numFramesDrawnInWindow == 1) {
|
||||
return 0.0;
|
||||
}
|
||||
return double(numFramesDrawnInWindow - 1) / realWindowSecs;
|
||||
}
|
||||
void Init();
|
||||
bool CapturedFullInterval(TimeStamp aTimestamp);
|
||||
|
||||
// Used while iterating backwards over the data
|
||||
void ResetReverseIterator();
|
||||
bool HasNext(TimeStamp aTimestamp, double aDuration = kFpsDumpInterval);
|
||||
TimeStamp GetNextTimeStamp();
|
||||
int GetLatestReadIndex();
|
||||
TimeStamp GetLatestTimeStamp();
|
||||
void WriteFrameTimeStamps(PRFileDesc* fd);
|
||||
bool IteratedFullInterval(TimeStamp aTimestamp, double aDuration);
|
||||
|
||||
void PrintFPS();
|
||||
int BuildHistogram(std::map<int, int>& aHistogram);
|
||||
void PrintHistogram(std::map<int, int>& aHistogram);
|
||||
double GetMean(std::map<int,int> aHistogram);
|
||||
double GetStdDev(std::map<int, int> aHistogram);
|
||||
nsresult WriteFrameTimeStamps();
|
||||
|
||||
/***
|
||||
* mFrameTimestamps is a psuedo circular buffer
|
||||
* Since we have a constant write time and don't
|
||||
* read at an offset except our latest write
|
||||
* we don't need an explicit read pointer.
|
||||
*/
|
||||
nsAutoTArray<TimeStamp, kMaxFrames> mFrameTimestamps;
|
||||
int mWriteIndex; // points to next open write slot
|
||||
int mIteratorIndex; // used only when iterating
|
||||
const char* mFPSName;
|
||||
TimeStamp mLastInterval;
|
||||
};
|
||||
|
||||
struct FPSState {
|
||||
FPSCounter mCompositionFps;
|
||||
FPSCounter mTransactionFps;
|
||||
|
||||
FPSState() {}
|
||||
|
||||
FPSState();
|
||||
void DrawFPS(TimeStamp, int offsetX, int offsetY, unsigned, Compositor* aCompositor);
|
||||
|
||||
void NotifyShadowTreeTransaction() {
|
||||
mTransactionFps.AddFrame(TimeStamp::Now());
|
||||
}
|
||||
|
||||
FPSCounter mCompositionFps;
|
||||
FPSCounter mTransactionFps;
|
||||
|
||||
private:
|
||||
RefPtr<DataTextureSource> mFPSTextureSource;
|
||||
};
|
||||
|
@ -311,89 +311,6 @@ LayerManagerComposite::RootLayer() const
|
||||
return ToLayerComposite(mRoot);
|
||||
}
|
||||
|
||||
// Size of the builtin font.
|
||||
static const float FontHeight = 7.f;
|
||||
static const float FontWidth = 4.f;
|
||||
static const float FontStride = 4.f;
|
||||
|
||||
// Scale the font when drawing it to the viewport for better readability.
|
||||
static const float FontScaleX = 2.f;
|
||||
static const float FontScaleY = 3.f;
|
||||
|
||||
static void DrawDigits(unsigned int aValue,
|
||||
int aOffsetX, int aOffsetY,
|
||||
Compositor* aCompositor,
|
||||
EffectChain& aEffectChain)
|
||||
{
|
||||
if (aValue > 999) {
|
||||
aValue = 999;
|
||||
}
|
||||
|
||||
unsigned int divisor = 100;
|
||||
float textureWidth = FontWidth * 10;
|
||||
gfx::Float opacity = 1;
|
||||
gfx::Matrix4x4 transform;
|
||||
transform.Scale(FontScaleX, FontScaleY, 1);
|
||||
|
||||
for (size_t n = 0; n < 3; ++n) {
|
||||
unsigned int digit = aValue % (divisor * 10) / divisor;
|
||||
divisor /= 10;
|
||||
|
||||
RefPtr<TexturedEffect> texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
|
||||
texturedEffect->mTextureCoords = Rect(float(digit * FontWidth) / textureWidth, 0, FontWidth / textureWidth, 1.0f);
|
||||
|
||||
Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight);
|
||||
Rect clipRect = Rect(0, 0, 300, 100);
|
||||
aCompositor->DrawQuad(drawRect, clipRect,
|
||||
aEffectChain, opacity, transform);
|
||||
}
|
||||
}
|
||||
|
||||
void FPSState::DrawFPS(TimeStamp aNow,
|
||||
int aOffsetX, int aOffsetY,
|
||||
unsigned int aFillRatio,
|
||||
Compositor* aCompositor)
|
||||
{
|
||||
if (!mFPSTextureSource) {
|
||||
const char *text =
|
||||
" "
|
||||
" XXX XX XXX XXX X X XXX XXX XXX XXX XXX"
|
||||
" X X X X X X X X X X X X X X"
|
||||
" X X X XXX XXX XXX XXX XXX X XXX XXX"
|
||||
" X X X X X X X X X X X X X"
|
||||
" XXX XXX XXX XXX X XXX XXX X XXX X"
|
||||
" ";
|
||||
|
||||
// Convert the text encoding above to RGBA.
|
||||
int w = FontWidth * 10;
|
||||
int h = FontHeight;
|
||||
uint32_t* buf = (uint32_t *) malloc(w * h * sizeof(uint32_t));
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
uint32_t purple = 0xfff000ff;
|
||||
uint32_t white = 0xffffffff;
|
||||
buf[i * w + j] = (text[i * w + j] == ' ') ? purple : white;
|
||||
}
|
||||
}
|
||||
|
||||
int bytesPerPixel = 4;
|
||||
RefPtr<DataSourceSurface> fpsSurface = Factory::CreateWrappingDataSourceSurface(
|
||||
reinterpret_cast<uint8_t*>(buf), w * bytesPerPixel, IntSize(w, h), SurfaceFormat::B8G8R8A8);
|
||||
mFPSTextureSource = aCompositor->CreateDataTextureSource();
|
||||
mFPSTextureSource->Update(fpsSurface);
|
||||
}
|
||||
|
||||
EffectChain effectChain;
|
||||
effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mFPSTextureSource, Filter::POINT);
|
||||
|
||||
unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
|
||||
unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow));
|
||||
|
||||
DrawDigits(fps, aOffsetX + 0, aOffsetY, aCompositor, effectChain);
|
||||
DrawDigits(txnFps, aOffsetX + FontWidth * 4, aOffsetY, aCompositor, effectChain);
|
||||
DrawDigits(aFillRatio, aOffsetX + FontWidth * 8, aOffsetY, aCompositor, effectChain);
|
||||
}
|
||||
|
||||
static uint16_t sFrameCount = 0;
|
||||
void
|
||||
LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
|
||||
|
@ -402,6 +402,74 @@ OpaqueRenderer::End()
|
||||
mD3D9ThebesSurface = nullptr;
|
||||
|
||||
}
|
||||
class TransparentRenderer {
|
||||
public:
|
||||
TransparentRenderer(const nsIntRegion& aUpdateRegion) :
|
||||
mUpdateRegion(aUpdateRegion) {}
|
||||
~TransparentRenderer() { End(); }
|
||||
already_AddRefed<gfxImageSurface> Begin(LayerD3D9* aLayer);
|
||||
void End();
|
||||
IDirect3DTexture9* GetTexture() { return mTmpTexture; }
|
||||
|
||||
private:
|
||||
const nsIntRegion& mUpdateRegion;
|
||||
nsRefPtr<IDirect3DTexture9> mTmpTexture;
|
||||
nsRefPtr<gfxImageSurface> mD3D9ThebesSurface;
|
||||
};
|
||||
|
||||
already_AddRefed<gfxImageSurface>
|
||||
TransparentRenderer::Begin(LayerD3D9* aLayer)
|
||||
{
|
||||
nsIntRect bounds = mUpdateRegion.GetBounds();
|
||||
|
||||
HRESULT hr = aLayer->device()->
|
||||
CreateTexture(bounds.width, bounds.height, 1, 0, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(mTmpTexture), nullptr);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
aLayer->ReportFailure(NS_LITERAL_CSTRING("Failed to create temporary texture in system memory."), hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT r;
|
||||
hr = mTmpTexture->LockRect(0, &r, nullptr, 0);
|
||||
if (FAILED(hr)) {
|
||||
// Uh-oh, bail.
|
||||
NS_WARNING("Failed to lock the texture");
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<gfxImageSurface> result =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
bounds.Size(),
|
||||
r.Pitch,
|
||||
gfxImageFormat::ARGB32);
|
||||
|
||||
if (!result || result->CairoStatus()) {
|
||||
NS_WARNING("Failed to d3d9 cairo surface.");
|
||||
return nullptr;
|
||||
}
|
||||
mD3D9ThebesSurface = result;
|
||||
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
void
|
||||
TransparentRenderer::End()
|
||||
{
|
||||
// gfxImageSurface returned from ::Begin() should be released before the
|
||||
// texture is used. This will assert that this is the case
|
||||
#if 1
|
||||
if (mD3D9ThebesSurface) {
|
||||
mD3D9ThebesSurface->AddRef();
|
||||
nsrefcnt c = mD3D9ThebesSurface->Release();
|
||||
if (c != 1)
|
||||
NS_RUNTIMEABORT("Reference mD3D9ThebesSurface must be released by caller of Begin() before calling End()");
|
||||
}
|
||||
#endif
|
||||
mD3D9ThebesSurface = nullptr;
|
||||
if (mTmpTexture)
|
||||
mTmpTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
static void
|
||||
FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
|
||||
@ -418,13 +486,13 @@ void
|
||||
ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
||||
const nsTArray<ReadbackProcessor::Update>& aReadbackUpdates)
|
||||
{
|
||||
HRESULT hr;
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
nsRefPtr<gfxASurface> destinationSurface;
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||
OpaqueRenderer opaqueRenderer(aRegion);
|
||||
TransparentRenderer transparentRenderer(aRegion);
|
||||
OpaqueRenderer opaqueRendererOnWhite(aRegion);
|
||||
|
||||
switch (aMode)
|
||||
@ -434,25 +502,11 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
||||
break;
|
||||
|
||||
case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA: {
|
||||
hr = device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||
0, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), nullptr);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
ReportFailure(NS_LITERAL_CSTRING("Failed to create temporary texture in system memory."), hr);
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX - We may consider retaining a SYSTEMMEM texture texture the size
|
||||
// of our DEFAULT texture and then use UpdateTexture and add dirty rects
|
||||
// to update in a single call.
|
||||
nsRefPtr<gfxWindowsSurface> dest = new gfxWindowsSurface(
|
||||
gfxIntSize(bounds.width, bounds.height), gfxImageFormat::ARGB32);
|
||||
destinationSurface = transparentRenderer.Begin(this);
|
||||
// If the contents of this layer don't require component alpha in the
|
||||
// end of rendering, it's safe to enable Cleartype since all the Cleartype
|
||||
// glyphs must be over (or under) opaque pixels.
|
||||
dest->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
|
||||
destinationSurface = dest.forget();
|
||||
destinationSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -523,36 +577,13 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
||||
destTextures.AppendElement(mTexture);
|
||||
break;
|
||||
|
||||
case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA: {
|
||||
LockTextureRectD3D9 textureLock(tmpTexture);
|
||||
if (!textureLock.HasLock()) {
|
||||
NS_WARNING("Failed to lock ThebesLayer tmpTexture texture.");
|
||||
return;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT r = textureLock.GetLockRect();
|
||||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
bounds.Size(),
|
||||
r.Pitch,
|
||||
gfxImageFormat::ARGB32);
|
||||
|
||||
if (destinationSurface) {
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
|
||||
context->SetSource(destinationSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
}
|
||||
|
||||
// Must release reference to dest surface before ending drawing
|
||||
case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA:
|
||||
// Must release reference to dest surface before ending drawing
|
||||
destinationSurface = nullptr;
|
||||
imgSurface = nullptr;
|
||||
|
||||
srcTextures.AppendElement(tmpTexture);
|
||||
transparentRenderer.End();
|
||||
srcTextures.AppendElement(transparentRenderer.GetTexture());
|
||||
destTextures.AppendElement(mTexture);
|
||||
break;
|
||||
}
|
||||
|
||||
case SurfaceMode::SURFACE_COMPONENT_ALPHA: {
|
||||
// Must release reference to dest surface before ending drawing
|
||||
|
@ -262,6 +262,7 @@ UNIFIED_SOURCES += [
|
||||
'composite/CompositableHost.cpp',
|
||||
'composite/ContainerLayerComposite.cpp',
|
||||
'composite/ContentHost.cpp',
|
||||
'composite/FPSCounter.cpp',
|
||||
'composite/ImageHost.cpp',
|
||||
'composite/ImageLayerComposite.cpp',
|
||||
'composite/LayerManagerComposite.cpp',
|
||||
|
@ -2242,6 +2242,12 @@ gfxContext::GetAzureDeviceSpaceClipBounds()
|
||||
return rect;
|
||||
}
|
||||
|
||||
Point
|
||||
gfxContext::GetDeviceOffset() const
|
||||
{
|
||||
return CurrentState().deviceOffset;
|
||||
}
|
||||
|
||||
Matrix
|
||||
gfxContext::GetDeviceTransform() const
|
||||
{
|
||||
@ -2297,7 +2303,7 @@ gfxContext::GetRoundOffsetsToPixels(bool *aRoundX, bool *aRoundY)
|
||||
// AxisAlignedTransforms, but we leave things simple.
|
||||
// Not much point rounding if a matrix will mess things up anyway.
|
||||
// Also return false for non-cairo contexts.
|
||||
if (CurrentMatrix().HasNonTranslation() || mDT) {
|
||||
if (CurrentMatrix().HasNonTranslation()) {
|
||||
*aRoundY = false;
|
||||
return;
|
||||
}
|
||||
|
@ -657,6 +657,8 @@ public:
|
||||
gfxRect GetUserFillExtent();
|
||||
gfxRect GetUserStrokeExtent();
|
||||
|
||||
mozilla::gfx::Point GetDeviceOffset() const;
|
||||
|
||||
/**
|
||||
** Flags
|
||||
**/
|
||||
|
@ -158,6 +158,8 @@ private:
|
||||
|
||||
DECL_GFX_PREF(Once, "layers.acceleration.disabled", LayersAccelerationDisabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps", LayersDrawFPS, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram", FPSPrintHistogram, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.acceleration.force-enabled", LayersAccelerationForceEnabled, bool, false);
|
||||
#ifdef XP_WIN
|
||||
// On windows, ignore the preference value, forcing async video to false.
|
||||
|
@ -152,6 +152,12 @@ interface imgIContainer : nsISupports
|
||||
const long FLAG_DECODE_NO_COLORSPACE_CONVERSION = 0x4;
|
||||
const long FLAG_CLAMP = 0x8;
|
||||
const long FLAG_HIGH_QUALITY_SCALING = 0x10;
|
||||
/**
|
||||
* Can be passed to GetFrame when the caller wants a DataSourceSurface
|
||||
* instead of a hardware accelerated surface. This can be important for
|
||||
* performance (by avoiding an upload to/readback from the GPU) when the
|
||||
* caller knows they want a SourceSurface of type DATA.
|
||||
*/
|
||||
const long FLAG_WANT_DATA_SURFACE = 0x20;
|
||||
|
||||
/**
|
||||
|
@ -182,7 +182,7 @@ DiscardingEnabled()
|
||||
class ScaleRequest
|
||||
{
|
||||
public:
|
||||
ScaleRequest(RasterImage* aImage, const gfx::Size& aScale, imgFrame* aSrcFrame)
|
||||
ScaleRequest(RasterImage* aImage, const gfxSize& aScale, imgFrame* aSrcFrame)
|
||||
: scale(aScale)
|
||||
, dstLocked(false)
|
||||
, done(false)
|
||||
@ -276,7 +276,7 @@ public:
|
||||
nsRefPtr<gfxImageSurface> dstSurface;
|
||||
|
||||
// Below are the values that may be touched on the scaling thread.
|
||||
gfx::Size scale;
|
||||
gfxSize scale;
|
||||
uint8_t* srcData;
|
||||
uint8_t* dstData;
|
||||
nsIntRect srcRect;
|
||||
@ -327,7 +327,7 @@ private: /* members */
|
||||
class ScaleRunner : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ScaleRunner(RasterImage* aImage, const gfx::Size& aScale, imgFrame* aSrcFrame)
|
||||
ScaleRunner(RasterImage* aImage, const gfxSize& aScale, imgFrame* aSrcFrame)
|
||||
{
|
||||
nsAutoPtr<ScaleRequest> request(new ScaleRequest(aImage, aScale, aSrcFrame));
|
||||
|
||||
@ -2510,7 +2510,7 @@ RasterImage::SyncDecode()
|
||||
}
|
||||
|
||||
bool
|
||||
RasterImage::CanQualityScale(const gfx::Size& scale)
|
||||
RasterImage::CanQualityScale(const gfxSize& scale)
|
||||
{
|
||||
// If target size is 1:1 with original, don't scale.
|
||||
if (scale.width == 1.0 && scale.height == 1.0)
|
||||
@ -2528,7 +2528,7 @@ RasterImage::CanQualityScale(const gfx::Size& scale)
|
||||
|
||||
bool
|
||||
RasterImage::CanScale(GraphicsFilter aFilter,
|
||||
gfx::Size aScale, uint32_t aFlags)
|
||||
gfxSize aScale, uint32_t aFlags)
|
||||
{
|
||||
// The high-quality scaler requires Skia.
|
||||
#ifdef MOZ_ENABLE_SKIA
|
||||
@ -2604,7 +2604,7 @@ RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
||||
gfxMatrix userSpaceToImageSpace = aUserSpaceToImageSpace;
|
||||
gfxMatrix imageSpaceToUserSpace = aUserSpaceToImageSpace;
|
||||
imageSpaceToUserSpace.Invert();
|
||||
gfx::Size scale = ToSize(imageSpaceToUserSpace.ScaleFactors(true));
|
||||
gfxSize scale = imageSpaceToUserSpace.ScaleFactors(true);
|
||||
nsIntRect subimage = aSubimage;
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
|
||||
|
@ -733,8 +733,8 @@ private: // data
|
||||
bool IsDecodeFinished();
|
||||
TimeStamp mDrawStartTime;
|
||||
|
||||
inline bool CanQualityScale(const gfx::Size& scale);
|
||||
inline bool CanScale(GraphicsFilter aFilter, gfx::Size aScale, uint32_t aFlags);
|
||||
inline bool CanQualityScale(const gfxSize& scale);
|
||||
inline bool CanScale(GraphicsFilter aFilter, gfxSize aScale, uint32_t aFlags);
|
||||
|
||||
struct ScaleResult
|
||||
{
|
||||
@ -742,7 +742,7 @@ private: // data
|
||||
: status(SCALE_INVALID)
|
||||
{}
|
||||
|
||||
gfx::Size scale;
|
||||
gfxSize scale;
|
||||
nsAutoPtr<imgFrame> frame;
|
||||
ScaleStatus status;
|
||||
};
|
||||
|
@ -101,7 +101,6 @@ const char implementationString[] = "Mozilla JavaScript Debugger Service";
|
||||
|
||||
const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
|
||||
const char jsdARObserverCtrID[] = "@mozilla.org/js/jsd/app-start-observer;2";
|
||||
const char jsdASObserverCtrID[] = "service,@mozilla.org/js/jsd/app-start-observer;2";
|
||||
|
||||
#ifdef DEBUG_verbose
|
||||
uint32_t gScriptCount = 0;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user