Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-05-12 13:52:46 +02:00
commit 3009130936
332 changed files with 27773 additions and 2695 deletions

View File

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

View File

@ -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"/>

View File

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

View File

@ -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"/>

View File

@ -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"/>

View File

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

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "95766b5f4b8108d3524431422ccf744e11797497",
"revision": "3207323b68e65e12f8281ccb22e88fb3a59bb391",
"repo_path": "/integration/gaia-central"
}

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

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

View File

@ -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"/>

View File

@ -6053,7 +6053,7 @@ function GetSearchFieldBookmarkData(node) {
function AddKeywordForSearchField() {
bookmarkData = GetSearchFieldBookmarkData(document.popupNode);
bookmarkData = GetSearchFieldBookmarkData(gContextMenu.target);
PlacesUIUtils.showBookmarkDialog({ action: "add"
, type: "bookmark"

View File

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

View File

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

View File

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

View File

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

View 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>

View File

@ -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();
/*

View File

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

View File

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

View File

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

View File

@ -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',

View File

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

View 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);
}

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@ MediaTaskQueue::~MediaTaskQueue()
}
nsresult
MediaTaskQueue::Dispatch(nsIRunnable* aRunnable)
MediaTaskQueue::Dispatch(TemporaryRef<nsIRunnable> aRunnable)
{
MonitorAutoLock mon(mQueueMonitor);
if (mIsShutdown) {

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View 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

View File

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

View File

@ -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',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 **/

View File

@ -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.";

View File

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

View File

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

View 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;
};

View File

@ -370,6 +370,7 @@ WEBIDL_FILES = [
'SVGGElement.webidl',
'SVGGradientElement.webidl',
'SVGGraphicsElement.webidl',
'SVGIFrameElement.webidl',
'SVGImageElement.webidl',
'SVGLength.webidl',
'SVGLengthList.webidl',

View File

@ -2444,7 +2444,7 @@ nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
Text* aTextNode,
nsINode* aTextNode,
int32_t aOffset,
bool aSuppressIME)
{

View File

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

View File

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

View File

@ -124,6 +124,8 @@ protected:
kBlockEnd
};
void InitFields();
// nsHTMLEditRules implementation methods
nsresult WillInsert(nsISelection *aSelection, bool *aCancel);
nsresult WillInsertText( EditAction aAction,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -102,6 +102,8 @@ public:
protected:
void InitFields();
// nsTextEditRules implementation methods
nsresult WillInsertText( EditAction aAction,
mozilla::dom::Selection* aSelection,

View File

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

View File

@ -90,6 +90,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
aDestTarget->CopySurface(mSurface,
IntRect(0, 0, mBounds.width, mBounds.height),
IntPoint(0, 0));
mSurface = nullptr;
}
return;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()
{

View 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

View File

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

View File

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

View File

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

View File

@ -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',

View File

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

View File

@ -657,6 +657,8 @@ public:
gfxRect GetUserFillExtent();
gfxRect GetUserStrokeExtent();
mozilla::gfx::Point GetDeviceOffset() const;
/**
** Flags
**/

View File

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

View File

@ -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;
/**

View File

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

View File

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

View File

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