Merge m-c to fx-team.

This commit is contained in:
Ryan VanderMeulen 2014-02-14 08:58:26 -05:00
commit 86e4a34c44
163 changed files with 3784 additions and 1702 deletions

1
aclocal.m4 vendored
View File

@ -3,6 +3,7 @@ dnl Local autoconf macros used with mozilla
dnl The contents of this file are under the Public Domain.
dnl
builtin(include, build/autoconf/hotfixes.m4)dnl
builtin(include, build/autoconf/acwinpaths.m4)dnl
builtin(include, build/autoconf/hooks.m4)dnl
builtin(include, build/autoconf/config.status.m4)dnl

View File

@ -12,7 +12,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="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>

View File

@ -11,7 +11,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>

View File

@ -12,7 +12,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="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>

View File

@ -1,4 +1,4 @@
{
"revision": "3d73a644a8ecb4a4c426584956d0c7f6b05e4cdb",
"revision": "4f00231c5cc538139e63bee1a7ed8456f6cefed7",
"repo_path": "/integration/gaia-central"
}

View File

@ -11,7 +11,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="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -10,7 +10,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="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -12,7 +12,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="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -11,7 +11,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="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -11,7 +11,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>

View File

@ -11,7 +11,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="ade88673d00414c3177f7444543b2fa01324708e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ac5dc6b76709e742cb923c58d1f4b415b3e08fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -28,11 +28,11 @@
command="Tools:PrivateBrowsing"
key="key_privatebrowsing"/>
<menuitem id="menu_newRemoteWindow"
label="New OOP Window"
label="New e10s Window"
hidden="true"
command="Tools:RemoteWindow"/>
<menuitem id="menu_newNonRemoteWindow"
label="New In-process Window"
label="New Non-e10s Window"
hidden="true"
command="Tools:NonRemoteWindow"/>
<menuitem id="menu_openFile"

View File

@ -2347,7 +2347,7 @@ let BrowserOnClick = {
*/
onE10sAboutNewTab: function(aEvent, aOwnerDoc) {
let isTopFrame = (aOwnerDoc.defaultView.parent === aOwnerDoc.defaultView);
if (!isTopFrame) {
if (!isTopFrame || aEvent.button != 0) {
return;
}

View File

@ -0,0 +1,24 @@
dnl This Source Code Form is subject to the terms of the Mozilla Public
dnl dnl License, v. 2.0. If a copy of the MPL was not distributed with this
dnl dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
dnl Set of hotfixes to address issues in autoconf 2.13
dnl Divert AC_CHECK_FUNC so that the #includes it uses can't interfere
dnl with the function it tests.
dnl So, when testing e.g. posix_memalign, any #include that AC_CHECK_FUNC
dnl prints is replaced with:
dnl #define posix_memalign innocuous_posix_memalign
dnl #include "theinclude"
dnl #undef posix_memalign
dnl This avoids double declaration of that function when the header normally
dnl declares it, while the test itself is just expecting the function not to be
dnl declared at all, and declares it differently (which doesn't matter for the
dnl test itself).
dnl More recent versions of autoconf are essentially doing this.
define([ac_cv_func_], [ac_cv_func2_])dnl
define([_AC_CHECK_FUNC],defn([AC_CHECK_FUNC]))dnl
define([AC_CHECK_FUNC], [dnl
patsubst(_AC_CHECK_FUNC($@), [#include.*], [#define $1 innocuous_$1
\&
#undef $1])])dnl

View File

@ -5,3 +5,20 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']
main = add_android_eclipse_project('Robocop', OBJDIR + '/AndroidManifest.xml')
main.package_name = 'org.mozilla.roboexample.test'
main.res = SRCDIR + '/res'
main.recursive_make_targets += [
OBJDIR + '/AndroidManifest.xml',
TOPOBJDIR + '/mobile/android/base/tests/TestConstants.java']
main.extra_jars += [SRCDIR + '/robotium-solo-4.3.1.jar']
main.assets = TOPSRCDIR + '/mobile/android/base/tests/assets'
main.referenced_projects += ['Fennec']
main.add_classpathentry('harness', SRCDIR,
dstdir='harness/org/mozilla/gecko')
main.add_classpathentry('src', TOPSRCDIR + '/mobile/android/base/tests',
dstdir='src/org/mozilla/gecko/tests')
main.add_classpathentry('generated', TOPOBJDIR + '/mobile/android/base/tests',
dstdir='generated/org/mozilla/gecko/tests')

View File

@ -20,7 +20,7 @@ interface nsIContentSecurityPolicy;
[ptr] native JSPrincipals(JSPrincipals);
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[scriptable, builtinclass, uuid(f09d8a53-a6c8-4f68-b329-9a76a709d24e)]
[scriptable, builtinclass, uuid(204555e7-04ad-4cc8-9f0e-840615cc43e8)]
interface nsIPrincipal : nsISerializable
{
/**
@ -31,9 +31,9 @@ interface nsIPrincipal : nsISerializable
boolean equals(in nsIPrincipal other);
/**
* Like equals, but doesn't take document.domain changes into account.
* Like equals, but takes document.domain changes into account.
*/
boolean equalsIgnoringDomain(in nsIPrincipal other);
boolean equalsConsideringDomain(in nsIPrincipal other);
%{C++
inline bool Equals(nsIPrincipal* aOther) {
@ -41,9 +41,9 @@ interface nsIPrincipal : nsISerializable
return NS_SUCCEEDED(Equals(aOther, &equal)) && equal;
}
inline bool EqualsIgnoringDomain(nsIPrincipal* aOther) {
inline bool EqualsConsideringDomain(nsIPrincipal* aOther) {
bool equal = false;
return NS_SUCCEEDED(EqualsIgnoringDomain(aOther, &equal)) && equal;
return NS_SUCCEEDED(EqualsConsideringDomain(aOther, &equal)) && equal;
}
%}
@ -91,10 +91,10 @@ interface nsIPrincipal : nsISerializable
boolean subsumes(in nsIPrincipal other);
/**
* Same as the previous method, subsumes(), but for codebase principals
* ignores changes to document.domain.
* Same as the previous method, subsumes(), but takes document.domain into
* account.
*/
boolean subsumesIgnoringDomain(in nsIPrincipal other);
boolean subsumesConsideringDomain(in nsIPrincipal other);
%{C++
inline bool Subsumes(nsIPrincipal* aOther) {
@ -102,9 +102,9 @@ interface nsIPrincipal : nsISerializable
return NS_SUCCEEDED(Subsumes(aOther, &subsumes)) && subsumes;
}
inline bool SubsumesIgnoringDomain(nsIPrincipal* aOther) {
inline bool SubsumesConsideringDomain(nsIPrincipal* aOther) {
bool subsumes = false;
return NS_SUCCEEDED(SubsumesIgnoringDomain(aOther, &subsumes)) && subsumes;
return NS_SUCCEEDED(SubsumesConsideringDomain(aOther, &subsumes)) && subsumes;
}
%}

View File

@ -51,14 +51,14 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISERIALIZABLE
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval);
NS_IMETHOD EqualsIgnoringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD GetHashValue(uint32_t* aHashValue);
NS_IMETHOD GetURI(nsIURI** aURI);
NS_IMETHOD GetDomain(nsIURI** aDomain);
NS_IMETHOD SetDomain(nsIURI* aDomain);
NS_IMETHOD GetOrigin(char** aOrigin);
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix);
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);
@ -134,14 +134,14 @@ public:
NS_DECL_NSIEXPANDEDPRINCIPAL
NS_DECL_NSISERIALIZABLE
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval);
NS_IMETHOD EqualsIgnoringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD GetHashValue(uint32_t* aHashValue);
NS_IMETHOD GetURI(nsIURI** aURI);
NS_IMETHOD GetDomain(nsIURI** aDomain);
NS_IMETHOD SetDomain(nsIURI* aDomain);
NS_IMETHOD GetOrigin(char** aOrigin);
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval);
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix);
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);

View File

@ -75,9 +75,6 @@ public:
ReportError(JSContext* cx, const nsAString& messageTag,
nsIURI* aSource, nsIURI* aTarget);
static nsresult
CheckSameOriginPrincipal(nsIPrincipal* aSubject,
nsIPrincipal* aObject);
static uint32_t
HashPrincipalByOrigin(nsIPrincipal* aPrincipal);
@ -128,19 +125,6 @@ private:
// when this happens -- this means that there was no JS running.
nsIPrincipal*
doGetSubjectPrincipal(nsresult* rv);
nsresult
CheckPropertyAccessImpl(uint32_t aAction,
nsAXPCNativeCallContext* aCallContext,
JSContext* cx, JSObject* aJSObject,
nsISupports* aObj,
nsIClassInfo* aClassInfo,
const char* aClassName, jsid aProperty);
nsresult
CheckSameOriginDOMProp(nsIPrincipal* aSubject,
nsIPrincipal* aObject,
uint32_t aAction);
nsresult
GetCodebasePrincipalInternal(nsIURI* aURI, uint32_t aAppId,

View File

@ -134,7 +134,7 @@ nsNullPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
}
NS_IMETHODIMP
nsNullPrincipal::EqualsIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
nsNullPrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
{
return Equals(aOther, aResult);
}
@ -211,7 +211,7 @@ nsNullPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
}
NS_IMETHODIMP
nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
nsNullPrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
{
return Subsumes(aOther, aResult);
}

View File

@ -231,7 +231,7 @@ nsPrincipal::GetOrigin(char **aOrigin)
}
NS_IMETHODIMP
nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
nsPrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
{
*aResult = false;
@ -245,14 +245,36 @@ nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
return NS_OK;
}
// Codebases are equal if they have the same origin.
*aResult = NS_SUCCEEDED(
nsScriptSecurityManager::CheckSameOriginPrincipal(this, aOther));
if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) {
return NS_OK;
}
// If either the subject or the object has changed its principal by
// explicitly setting document.domain then the other must also have
// done so in order to be considered the same origin. This prevents
// DNS spoofing based on document.domain (154930)
nsCOMPtr<nsIURI> thisURI;
this->GetDomain(getter_AddRefs(thisURI));
bool thisSetDomain = !!thisURI;
if (!thisURI) {
this->GetURI(getter_AddRefs(thisURI));
}
nsCOMPtr<nsIURI> otherURI;
aOther->GetDomain(getter_AddRefs(otherURI));
bool otherSetDomain = !!otherURI;
if (!otherURI) {
aOther->GetURI(getter_AddRefs(otherURI));
}
*aResult = thisSetDomain == otherSetDomain &&
nsScriptSecurityManager::SecurityCompareURIs(thisURI, otherURI);
return NS_OK;
}
NS_IMETHODIMP
nsPrincipal::EqualsIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
{
*aResult = false;
@ -292,9 +314,9 @@ nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
}
NS_IMETHODIMP
nsPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
nsPrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
{
return EqualsIgnoringDomain(aOther, aResult);
return EqualsConsideringDomain(aOther, aResult);
}
NS_IMETHODIMP
@ -639,15 +661,15 @@ typedef nsresult (NS_STDCALL nsIPrincipal::*nsIPrincipalMemFn)(nsIPrincipal* aOt
bool* aResult);
#define CALL_MEMBER_FUNCTION(THIS,MEM_FN) ((THIS)->*(MEM_FN))
// nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsIgnoringDomain
// nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsConsideringDomain
// shares the same logic. The difference only that Equals requires 'this'
// and 'aOther' to Subsume each other while EqualsIgnoringDomain requires
// bidirectional SubsumesIgnoringDomain.
// and 'aOther' to Subsume each other while EqualsConsideringDomain requires
// bidirectional SubsumesConsideringDomain.
static nsresult
Equals(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
bool* aResult)
{
// If (and only if) 'aThis' and 'aOther' both Subsume/SubsumesIgnoringDomain
// If (and only if) 'aThis' and 'aOther' both Subsume/SubsumesConsideringDomain
// each other, then they are Equal.
*aResult = false;
// Calling the corresponding subsume function on this (aFn).
@ -669,14 +691,14 @@ nsExpandedPrincipal::Equals(nsIPrincipal* aOther, bool* aResult)
}
NS_IMETHODIMP
nsExpandedPrincipal::EqualsIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
nsExpandedPrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult)
{
return ::Equals(this, &nsIPrincipal::SubsumesIgnoringDomain, aOther, aResult);
return ::Equals(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult);
}
// nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesIgnoringDomain
// nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesConsideringDomain
// shares the same logic. The difference only that Subsumes calls are replaced
//with SubsumesIgnoringDomain calls in the second case.
//with SubsumesConsideringDomain calls in the second case.
static nsresult
Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
bool* aResult)
@ -721,9 +743,9 @@ nsExpandedPrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult)
}
NS_IMETHODIMP
nsExpandedPrincipal::SubsumesIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
nsExpandedPrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult)
{
return ::Subsumes(this, &nsIPrincipal::SubsumesIgnoringDomain, aOther, aResult);
return ::Subsumes(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult);
}
NS_IMETHODIMP

View File

@ -486,71 +486,6 @@ nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
return NS_OK;
}
/* static */
nsresult
nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
nsIPrincipal* aObject)
{
/*
** Get origin of subject and object and compare.
*/
if (aSubject == aObject)
return NS_OK;
if (!AppAttributesEqual(aSubject, aObject)) {
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
// Default to false, and change if that turns out wrong.
bool subjectSetDomain = false;
bool objectSetDomain = false;
nsCOMPtr<nsIURI> subjectURI;
nsCOMPtr<nsIURI> objectURI;
aSubject->GetDomain(getter_AddRefs(subjectURI));
if (!subjectURI) {
aSubject->GetURI(getter_AddRefs(subjectURI));
} else {
subjectSetDomain = true;
}
aObject->GetDomain(getter_AddRefs(objectURI));
if (!objectURI) {
aObject->GetURI(getter_AddRefs(objectURI));
} else {
objectSetDomain = true;
}
if (SecurityCompareURIs(subjectURI, objectURI))
{ // If either the subject or the object has changed its principal by
// explicitly setting document.domain then the other must also have
// done so in order to be considered the same origin. This prevents
// DNS spoofing based on document.domain (154930)
// If both or neither explicitly set their domain, allow the access
if (subjectSetDomain == objectSetDomain)
return NS_OK;
}
/*
** Access tests failed, so now report error.
*/
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
// It's important that
//
// CheckSameOriginPrincipal(A, B) == NS_OK
//
// imply
//
// HashPrincipalByOrigin(A) == HashPrincipalByOrigin(B)
//
// if principals A and B could ever be used as keys in a hashtable.
// Violation of this invariant leads to spurious failures of hashtable
// lookups. See bug 454850.
/*static*/ uint32_t
nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal* aPrincipal)
{
@ -581,33 +516,6 @@ nsScriptSecurityManager::AppAttributesEqual(nsIPrincipal* aFirst,
(aFirst->GetIsInBrowserElement() == aSecond->GetIsInBrowserElement()));
}
nsresult
nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
nsIPrincipal* aObject,
uint32_t aAction)
{
nsresult rv;
bool subsumes;
rv = aSubject->Subsumes(aObject, &subsumes);
if (NS_SUCCEEDED(rv) && !subsumes) {
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
if (NS_SUCCEEDED(rv))
return NS_OK;
/*
* Content can't ever touch chrome (we check for UniversalXPConnect later)
*/
if (aObject == mSystemPrincipal)
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
/*
** Access tests failed, so now report error.
*/
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
NS_IMETHODIMP
nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI)
{

View File

@ -79,7 +79,7 @@ nsSystemPrincipal::Equals(nsIPrincipal *other, bool *result)
}
NS_IMETHODIMP
nsSystemPrincipal::EqualsIgnoringDomain(nsIPrincipal *other, bool *result)
nsSystemPrincipal::EqualsConsideringDomain(nsIPrincipal *other, bool *result)
{
return Equals(other, result);
}
@ -92,7 +92,7 @@ nsSystemPrincipal::Subsumes(nsIPrincipal *other, bool *result)
}
NS_IMETHODIMP
nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result)
nsSystemPrincipal::SubsumesConsideringDomain(nsIPrincipal *other, bool *result)
{
*result = true;
return NS_OK;

View File

@ -1,3 +1,7 @@
[DEFAULT]
support-files =
file_disableScript.html
[test_disableScript.xul]
[test_principal_jarprefix_origin_appid_appstatus.html]
# jarPrefix test doesn't work on Windows, see bug 776296.

View File

@ -14,7 +14,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840488
target="_blank">Mozilla Bug 840488</a>
</body>
<iframe id="root" name="root" onload="go();" type="content"/>
<iframe id="root" name="root" type="content"/>
<iframe id="chromeFrame" name="chromeFrame" type="content"/>
<!-- test code goes here -->
<script type="application/javascript">
@ -32,7 +33,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840488
const path = "/tests/caps/tests/mochitest/file_disableScript.html";
const uri = "http://www.example.com" + path;
var rootFrame = document.getElementById('root');
rootFrame.setAttribute('src', uri + "?name=rootframe");
var chromeFrame = document.getElementById('chromeFrame');
navigateFrame(rootFrame, uri + "?name=rootframe").then(function() {
navigateFrame(chromeFrame, "file_disableScript.html").then(go);
});
function navigateFrame(ifr, src) {
let deferred = Promise.defer();
@ -137,16 +141,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840488
}
function go() {
rootFrame.setAttribute('onload', null);
var rootWin = rootFrame.contentWindow;
var chromeWin = chromeFrame.contentWindow;
// Test simple docshell enable/disable.
var rootWin = rootFrame.contentWindow;
checkScriptEnabled(rootWin, true);
setScriptEnabledForDocShell(rootWin, false);
checkScriptEnabled(rootWin, false);
setScriptEnabledForDocShell(rootWin, true);
checkScriptEnabled(rootWin, true);
// Privileged frames are immune to docshell flags.
ok(ssm.isSystemPrincipal(chromeWin.document.nodePrincipal), "Sanity check for System Principal");
setScriptEnabledForDocShell(chromeWin, false);
checkScriptEnabled(chromeWin, true);
setScriptEnabledForDocShell(chromeWin, true);
// Play around with the docshell tree and make sure everything works as
// we expect.
addFrame(rootWin, 'parent', true).then(function() {
@ -209,6 +219,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840488
return reloadFrame(rootFrame);
}).then(function() {
checkScriptEnabled(rootWin, false);
checkScriptEnabled(chromeWin, true);
setScriptEnabledForBrowser(true);
return reloadFrame(rootFrame);
}).then(function() {
@ -223,6 +234,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840488
Cu.unblockScriptForGlobal(rootWin);
checkScriptEnabled(rootWin, true);
Cu.blockScriptForGlobal(rootWin);
try {
Cu.blockScriptForGlobal(chromeWin);
ok(false, "Should have thrown");
} catch (e) {
ok(/may not be disabled/.test(e),
"Shouldn't be able to programmatically block script for system globals");
}
return reloadFrame(rootFrame);
}).then(function() {
checkScriptEnabled(rootWin, true);

View File

@ -5665,10 +5665,6 @@ already_AddRefed<nsINode>
nsIDocument::ImportNode(nsINode& aNode, bool aDeep, ErrorResult& rv) const
{
nsINode* imported = &aNode;
rv = nsContentUtils::CheckSameOrigin(this, imported);
if (rv.Failed()) {
return nullptr;
}
switch (imported->NodeType()) {
case nsIDOMNode::ATTRIBUTE_NODE:
@ -5925,12 +5921,6 @@ nsIDocument::CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
ErrorResult& rv) const
{
nsINode* root = &aRoot;
nsresult res = nsContentUtils::CheckSameOrigin(this, root);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;
}
nsRefPtr<NodeIterator> iterator = new NodeIterator(root, aWhatToShow,
aFilter);
return iterator.forget();
@ -5974,12 +5964,6 @@ nsIDocument::CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
ErrorResult& rv) const
{
nsINode* root = &aRoot;
nsresult res = nsContentUtils::CheckSameOrigin(this, root);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;
}
nsRefPtr<TreeWalker> walker = new TreeWalker(root, aWhatToShow, aFilter);
return walker.forget();
}
@ -6688,10 +6672,6 @@ nsINode*
nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
{
nsINode* adoptedNode = &aAdoptedNode;
rv = nsContentUtils::CheckSameOrigin(this, adoptedNode);
if (rv.Failed()) {
return nullptr;
}
// Scope firing mutation events so that we don't carry any state that
// might be stale
@ -11113,16 +11093,12 @@ nsIDocument::GetMozPointerLockElement()
return nullptr;
}
// Make sure pointer locked element is in the same document and domain.
// Make sure pointer locked element is in the same document.
nsCOMPtr<nsIDocument> pointerLockedDoc =
do_QueryReferent(nsEventStateManager::sPointerLockedDoc);
if (pointerLockedDoc != this) {
return nullptr;
}
nsresult rv = nsContentUtils::CheckSameOrigin(this, pointerLockedElement);
if (NS_FAILED(rv)) {
return nullptr;
}
return pointerLockedElement;
}

View File

@ -3143,7 +3143,7 @@ nsObjectLoadingContent::GetContentDocument()
}
// Return null for cross-origin contentDocument.
if (!nsContentUtils::GetSubjectPrincipal()->Subsumes(sub_doc->NodePrincipal())) {
if (!nsContentUtils::GetSubjectPrincipal()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
return nullptr;
}

View File

@ -56,13 +56,7 @@ DoDrawImageSecurityCheck(dom::HTMLCanvasElement *aCanvasElement,
if (CORSUsed)
return;
// Ignore document.domain in this check.
bool subsumes;
nsresult rv =
aCanvasElement->NodePrincipal()->SubsumesIgnoringDomain(aPrincipal,
&subsumes);
if (NS_SUCCEEDED(rv) && subsumes) {
if (aCanvasElement->NodePrincipal()->Subsumes(aPrincipal)) {
// This canvas has access to that image anyway
return;
}

View File

@ -895,6 +895,7 @@ protected:
// -------------------------------------------------------------------------
// WebGL extensions (implemented in WebGLContextExtensions.cpp)
enum WebGLExtensionID {
EXT_frag_depth,
EXT_sRGB,
EXT_texture_filter_anisotropic,
OES_element_index_uint,

View File

@ -17,6 +17,7 @@ using namespace mozilla::gl;
// must match WebGLContext::WebGLExtensionID
static const char *sExtensionNames[] = {
"EXT_frag_depth",
"EXT_sRGB",
"EXT_texture_filter_anisotropic",
"OES_element_index_uint",
@ -139,6 +140,8 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
return WebGLExtensionSRGB::IsSupported(this);
case WEBGL_draw_buffers:
return WebGLExtensionDrawBuffers::IsSupported(this);
case EXT_frag_depth:
return WebGLExtensionFragDepth::IsSupported(this);
default:
// For warnings-as-errors.
break;
@ -295,6 +298,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
case EXT_sRGB:
obj = new WebGLExtensionSRGB(this);
break;
case EXT_frag_depth:
obj = new WebGLExtensionFragDepth(this);
break;
default:
MOZ_ASSERT(false, "should not get there.");
}

View File

@ -530,6 +530,18 @@ WebGLContext::CopyTexImage2D(GLenum target,
return ErrorInvalidValue("copyTexImage2D: with level > 0, width and height must be powers of two");
}
if (internalformat == LOCAL_GL_DEPTH_COMPONENT ||
internalformat == LOCAL_GL_DEPTH_STENCIL)
return ErrorInvalidOperation("copyTexImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex)
return ErrorInvalidOperation("copyTexImage2D: no texture bound to this target");
if (mBoundFramebuffer)
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
bool texFormatRequiresAlpha = internalformat == LOCAL_GL_RGBA ||
internalformat == LOCAL_GL_ALPHA ||
internalformat == LOCAL_GL_LUMINANCE_ALPHA;
@ -539,18 +551,6 @@ WebGLContext::CopyTexImage2D(GLenum target,
return ErrorInvalidOperation("copyTexImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
if (internalformat == LOCAL_GL_DEPTH_COMPONENT ||
internalformat == LOCAL_GL_DEPTH_STENCIL)
return ErrorInvalidOperation("copyTexImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
if (mBoundFramebuffer)
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex)
return ErrorInvalidOperation("copyTexImage2D: no texture bound to this target");
// copyTexImage2D only generates textures with type = UNSIGNED_BYTE
GLenum type = LOCAL_GL_UNSIGNED_BYTE;
@ -639,16 +639,6 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
GLenum internalFormat = imageInfo.InternalFormat();
bool texFormatRequiresAlpha = (internalFormat == LOCAL_GL_RGBA ||
internalFormat == LOCAL_GL_ALPHA ||
internalFormat == LOCAL_GL_LUMINANCE_ALPHA);
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
: bool(gl->GetPixelFormat().alpha > 0);
if (texFormatRequiresAlpha && !fboFormatHasAlpha)
return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
if (IsGLDepthFormat(internalFormat) ||
IsGLDepthStencilFormat(internalFormat))
{
@ -659,6 +649,16 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
bool texFormatRequiresAlpha = (internalFormat == LOCAL_GL_RGBA ||
internalFormat == LOCAL_GL_ALPHA ||
internalFormat == LOCAL_GL_LUMINANCE_ALPHA);
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
: bool(gl->GetPixelFormat().alpha > 0);
if (texFormatRequiresAlpha && !fboFormatHasAlpha)
return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
if (imageInfo.HasUninitializedImageData()) {
tex->DoDeferredImageInitialization(target, level);
}
@ -3087,6 +3087,9 @@ WebGLContext::CompileShader(WebGLShader *shader)
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
resources.MaxDrawBuffers = mGLMaxDrawBuffers;
if (IsExtensionEnabled(EXT_frag_depth))
resources.EXT_frag_depth = 1;
if (IsExtensionEnabled(OES_standard_derivatives))
resources.OES_standard_derivatives = 1;

View File

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "WebGLContext.h"
#include "WebGLExtensions.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "GLContext.h"
using namespace mozilla;
WebGLExtensionFragDepth::WebGLExtensionFragDepth(WebGLContext* context)
: WebGLExtensionBase(context)
{
MOZ_ASSERT(IsSupported(context),
"Should not construct extension object if unsupported.");
}
WebGLExtensionFragDepth::~WebGLExtensionFragDepth()
{
}
bool
WebGLExtensionFragDepth::IsSupported(const WebGLContext* context)
{
gl::GLContext* gl = context->GL();
return gl->IsSupported(gl::GLFeature::frag_depth);
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth)

View File

@ -108,6 +108,18 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionFragDepth
: public WebGLExtensionBase
{
public:
WebGLExtensionFragDepth(WebGLContext*);
virtual ~WebGLExtensionFragDepth();
static bool IsSupported(const WebGLContext* context);
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionLoseContext
: public WebGLExtensionBase
{

View File

@ -50,6 +50,8 @@ WebGLFramebuffer::Attachment::IsDeleteRequested() const
bool
WebGLFramebuffer::Attachment::HasAlpha() const
{
MOZ_ASSERT(HasImage());
GLenum format = 0;
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).InternalFormat();
@ -75,7 +77,9 @@ WebGLFramebuffer::Attachment::HasUninitializedImageData() const
if (Renderbuffer()) {
return Renderbuffer()->HasUninitializedImageData();
} else if (Texture()) {
}
if (Texture()) {
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
}
@ -90,11 +94,13 @@ WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus)
if (!HasImage())
return;
if (mRenderbufferPtr) {
mRenderbufferPtr->SetImageDataStatus(newStatus);
if (Renderbuffer()) {
Renderbuffer()->SetImageDataStatus(newStatus);
return;
} else if (mTexturePtr) {
mTexturePtr->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
}
if (Texture()) {
Texture()->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
return;
}
@ -106,7 +112,8 @@ WebGLFramebuffer::Attachment::HasImage() const
{
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
return true;
else if (Renderbuffer())
if (Renderbuffer())
return true;
return false;
@ -120,7 +127,9 @@ WebGLFramebuffer::Attachment::RectangleObject() const
if (Texture()) {
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
} else if (Renderbuffer()) {
}
if (Renderbuffer()) {
return *Renderbuffer();
}
@ -228,10 +237,10 @@ WebGLFramebuffer::Attachment::IsComplete() const
return false;
}
if (mTexturePtr) {
MOZ_ASSERT(mTexturePtr->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
if (Texture()) {
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
const WebGLTexture::ImageInfo& imageInfo =
mTexturePtr->ImageInfoAt(mTexImageTarget, mTexImageLevel);
Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
GLenum internalFormat = imageInfo.InternalFormat();
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
@ -250,8 +259,8 @@ WebGLFramebuffer::Attachment::IsComplete() const
return false;
}
if (mRenderbufferPtr) {
GLenum internalFormat = mRenderbufferPtr->InternalFormat();
if (Renderbuffer()) {
GLenum internalFormat = Renderbuffer()->InternalFormat();
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
return IsValidFBORenderbufferDepthFormat(internalFormat);
@ -438,7 +447,8 @@ WebGLFramebuffer::GetAttachment(GLenum attachment) const
void
WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
{
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[i].Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_TEXTURE_2D, nullptr, 0);
// a texture might be attached more that once while editing the framebuffer
@ -456,7 +466,8 @@ WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
void
WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
{
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[0].Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, nullptr);
// a renderbuffer might be attached more that once while editing the framebuffer
@ -476,7 +487,8 @@ WebGLFramebuffer::HasDefinedAttachments() const
{
bool hasAttachments = false;
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
hasAttachments |= mColorAttachments[i].IsDefined();
}
@ -491,7 +503,7 @@ WebGLFramebuffer::HasDefinedAttachments() const
static bool
IsIncomplete(const WebGLFramebuffer::Attachment& cur)
{
return cur.IsDefined() && !cur.IsComplete();
return cur.IsDefined() && !cur.IsComplete();
}
bool
@ -499,7 +511,8 @@ WebGLFramebuffer::HasIncompleteAttachments() const
{
bool hasIncomplete = false;
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
hasIncomplete |= IsIncomplete(mColorAttachments[i]);
}
@ -516,7 +529,8 @@ WebGLFramebuffer::GetAnyRectObject() const
{
MOZ_ASSERT(HasDefinedAttachments());
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[i].HasImage())
return mColorAttachments[i].RectangleObject();
}
@ -552,7 +566,8 @@ WebGLFramebuffer::AllImageRectsMatch() const
// Alright, we have *a* rect, let's check all the others.
bool imageRectsMatch = true;
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[i].HasImage())
imageRectsMatch &= RectsMatch(mColorAttachments[i], rect);
}
@ -591,7 +606,7 @@ WebGLFramebuffer::PrecheckFramebufferStatus() const
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
if (!AllImageRectsMatch())
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // No consistent size
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // Inconsistent sizes
if (HasDepthStencilConflict())
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
@ -616,7 +631,6 @@ WebGLFramebuffer::CheckFramebufferStatus() const
}
bool
WebGLFramebuffer::CheckAndInitializeAttachments()
{
@ -626,7 +640,7 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
return false;
// Cool! We've checked out ok. Just need to initialize.
size_t colorAttachmentCount = size_t(mColorAttachments.Length());
size_t colorAttachmentCount = mColorAttachments.Length();
// Check if we need to initialize anything
{
@ -764,7 +778,8 @@ FinalizeDrawAndReadBuffers(GLContext* aGL, bool aColorBufferDefined)
void
WebGLFramebuffer::FinalizeAttachments() const
{
for (size_t i = 0; i < ColorAttachmentCount(); i++) {
size_t count = ColorAttachmentCount();
for (size_t i = 0; i < count; i++) {
if (ColorAttachment(i).IsDefined())
ColorAttachment(i).FinalizeAttachment(LOCAL_GL_COLOR_ATTACHMENT0 + i);
}

View File

@ -52,6 +52,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLExtensionDepthTexture.cpp',
'WebGLExtensionDrawBuffers.cpp',
'WebGLExtensionElementIndexUint.cpp',
'WebGLExtensionFragDepth.cpp',
'WebGLExtensionInstancedArrays.cpp',
'WebGLExtensionLoseContext.cpp',
'WebGLExtensionSRGB.cpp',

View File

@ -79,7 +79,7 @@ nsGenericHTMLFrameElement::GetContentDocument()
nsIDocument *doc = win->GetDoc();
// Return null for cross-origin contentDocument.
if (!nsContentUtils::GetSubjectPrincipal()->Subsumes(doc->NodePrincipal())) {
if (!nsContentUtils::GetSubjectPrincipal()->SubsumesConsideringDomain(doc->NodePrincipal())) {
return nullptr;
}
return doc;

View File

@ -295,11 +295,7 @@ SVGFEImageElement::OutputIsTainted(const nsTArray<bool>& aInputsAreTainted,
return false;
}
// Ignore document.domain in this check.
bool subsumes;
rv = aReferencePrincipal->SubsumesIgnoringDomain(principal, &subsumes);
if (NS_SUCCEEDED(rv) && subsumes) {
if (aReferencePrincipal->Subsumes(principal)) {
// The page is allowed to read from the image.
return false;
}

View File

@ -7438,7 +7438,9 @@ JSObject* nsGlobalWindow::CallerGlobal()
// isn't, something is screwy, and we want to clamp to the cx global.
JS::Rooted<JSObject*> scriptedGlobal(cx, JS_GetScriptedGlobal(cx));
JS::Rooted<JSObject*> cxGlobal(cx, JS::CurrentGlobalOrNull(cx));
if (!xpc::AccessCheck::subsumes(cxGlobal, scriptedGlobal)) {
nsIPrincipal* scriptedPrin = nsContentUtils::GetObjectPrincipal(scriptedGlobal);
nsIPrincipal* cxPrin = nsContentUtils::GetObjectPrincipal(cxGlobal);
if (!cxPrin->SubsumesConsideringDomain(scriptedPrin)) {
NS_WARNING("Something nasty is happening! Applying countermeasures...");
return cxGlobal;
}
@ -7718,7 +7720,7 @@ PostMessageEvent::Run()
// don't do that in other places it seems better to hold the line for
// now. Long-term, we want HTML5 to address this so that we can
// be compliant while being safer.
if (!targetPrin->EqualsIgnoringDomain(mProvidedPrincipal)) {
if (!targetPrin->Equals(mProvidedPrincipal)) {
return NS_OK;
}
}

View File

@ -266,7 +266,7 @@ public:
nsresult Get(nsIPrincipal* aSubject, nsIVariant** aResult)
{
nsCOMPtr<nsIVariant> result;
if (aSubject->Subsumes(mOrigin)) {
if (aSubject->SubsumesConsideringDomain(mOrigin)) {
result = mValue;
} else {
result = CreateVoidVariant();

View File

@ -2971,6 +2971,16 @@ AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
aHandle);
}
static void
OnLargeAllocationFailure()
{
nsCOMPtr<nsIObserverService> os =
mozilla::services::GetObserverService();
if (os) {
os->NotifyObservers(nullptr, "memory-pressure", MOZ_UTF16("heap-minimize"));
}
}
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
void
@ -3027,6 +3037,8 @@ nsJSContext::EnsureStatics()
};
JS::SetAsmJSCacheOps(sRuntime, &asmJSCacheOps);
JS::SetLargeAllocationFailureCallback(sRuntime, OnLargeAllocationFailure);
// Set these global xpconnect options...
Preferences::RegisterCallbackAndCall(ReportAllJSExceptionsPrefChangedCallback,
"dom.report_all_js_exceptions");

View File

@ -908,7 +908,7 @@ nsLocation::CallerSubsumes()
return false;
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(outer);
bool subsumes = false;
nsresult rv = nsContentUtils::GetSubjectPrincipal()->Subsumes(sop->GetPrincipal(), &subsumes);
nsresult rv = nsContentUtils::GetSubjectPrincipal()->SubsumesConsideringDomain(sop->GetPrincipal(), &subsumes);
NS_ENSURE_SUCCESS(rv, false);
return subsumes;
}

View File

@ -1380,6 +1380,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionFragDepth': {
'nativeType': 'mozilla::WebGLExtensionFragDepth',
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionLoseContext': {
'nativeType': 'mozilla::WebGLExtensionLoseContext',
'headerFile': 'WebGLExtensions.h'

View File

@ -26,7 +26,6 @@ SimpleTest.waitForExplicitFinish();
var index = -1;
var todayDate = new Date();
var baseServeURL = "http://mochi.test:8888/tests/dom/downloads/tests/";
var baseDownloadPath = "/mnt/sdcard/downloads/";
var lastKnownCurrentBytes = 0;
function next() {
@ -45,11 +44,12 @@ function next() {
function checkConsistentDownloadAttributes(download) {
var href = document.getElementById("download1").getAttribute("href");
var expectedServeURL = baseServeURL + href;
var expectedDownloadPath = baseDownloadPath + "test.bin";
var destinationRegEx = /test\(?[0-9]*\)?\.bin$/;
// bug 945323: Download path isn't honoring download attribute
todo(download.path === expectedDownloadPath,
"Download path = " + expectedDownloadPath);
ok(destinationRegEx.test(download.path),
"Download path '" + download.path +
"' should match '" + destinationRegEx + "' regexp.");
ok(download.startTime >= todayDate,
"Download start time should be greater than or equal to today");

View File

@ -959,6 +959,8 @@ PExternalHelperAppChild*
ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
const nsCString& aMimeContentType,
const nsCString& aContentDisposition,
const uint32_t& aContentDispositionHint,
const nsString& aContentDispositionFilename,
const bool& aForceSave,
const int64_t& aContentLength,
const OptionalURIParams& aReferrer,

View File

@ -144,6 +144,8 @@ public:
const OptionalURIParams& uri,
const nsCString& aMimeContentType,
const nsCString& aContentDisposition,
const uint32_t& aContentDispositionHint,
const nsString& aContentDispositionFilename,
const bool& aForceSave,
const int64_t& aContentLength,
const OptionalURIParams& aReferrer,

View File

@ -2393,6 +2393,8 @@ PExternalHelperAppParent*
ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
const nsCString& aMimeContentType,
const nsCString& aContentDisposition,
const uint32_t& aContentDispositionHint,
const nsString& aContentDispositionFilename,
const bool& aForceSave,
const int64_t& aContentLength,
const OptionalURIParams& aReferrer,
@ -2400,7 +2402,14 @@ ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
{
ExternalHelperAppParent *parent = new ExternalHelperAppParent(uri, aContentLength);
parent->AddRef();
parent->Init(this, aMimeContentType, aContentDisposition, aForceSave, aReferrer, aBrowser);
parent->Init(this,
aMimeContentType,
aContentDisposition,
aContentDispositionHint,
aContentDispositionFilename,
aForceSave,
aReferrer,
aBrowser);
return parent;
}

View File

@ -367,6 +367,8 @@ private:
const OptionalURIParams& aUri,
const nsCString& aMimeContentType,
const nsCString& aContentDisposition,
const uint32_t& aContentDispositionHint,
const nsString& aContentDispositionFilename,
const bool& aForceSave,
const int64_t& aContentLength,
const OptionalURIParams& aReferrer,

View File

@ -422,9 +422,14 @@ parent:
CloseAlert(nsString name, Principal principal);
PExternalHelperApp(OptionalURIParams uri, nsCString aMimeContentType,
nsCString aContentDisposition, bool aForceSave,
int64_t aContentLength, OptionalURIParams aReferrer,
PExternalHelperApp(OptionalURIParams uri,
nsCString aMimeContentType,
nsCString aContentDisposition,
uint32_t aContentDispositionHint,
nsString aContentDispositionFilename,
bool aForceSave,
int64_t aContentLength,
OptionalURIParams aReferrer,
nullable PBrowser aBrowser);
AddGeolocationListener(Principal principal, bool highAccuracy);

View File

@ -319,29 +319,7 @@ DOMStorage::PrincipalEquals(nsIPrincipal* aPrincipal)
bool
DOMStorage::CanAccess(nsIPrincipal* aPrincipal)
{
// Allow C++ callers to access the storage
if (!aPrincipal) {
return true;
}
// For content, either the code base or domain must be the same. When code
// base is the same, this is enough to say it is safe for a page to access
// this storage.
bool subsumes;
nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
if (NS_FAILED(rv)) {
return false;
}
if (!subsumes) {
nsresult rv = aPrincipal->Subsumes(mPrincipal, &subsumes);
if (NS_FAILED(rv)) {
return false;
}
}
return subsumes;
return !aPrincipal || aPrincipal->Subsumes(mPrincipal);
}
nsTArray<nsString>*

View File

@ -91,17 +91,7 @@ PrincipalsEqual(nsIPrincipal* aObjectPrincipal, nsIPrincipal* aSubjectPrincipal)
return false;
}
bool equals;
nsresult rv = aSubjectPrincipal->EqualsIgnoringDomain(aObjectPrincipal, &equals);
NS_ASSERTION(NS_SUCCEEDED(rv) && equals,
"Trying to get DOM storage for wrong principal!");
if (NS_FAILED(rv) || !equals) {
return false;
}
return true;
return aSubjectPrincipal->Equals(aObjectPrincipal);
}
NS_IMPL_ISUPPORTS1(DOMStorageManager,

View File

@ -822,6 +822,11 @@ interface WebGLExtensionElementIndexUint
{
};
[NoInterfaceObject]
interface WebGLExtensionFragDepth
{
};
[NoInterfaceObject]
interface WebGLExtensionLoseContext {
void loseContext();

View File

@ -75,7 +75,11 @@ FileReaderSync::ReadAsArrayBuffer(JSContext* aCx,
}
uint32_t bufferLength = JS_GetArrayBufferByteLength(jsArrayBuffer);
uint8_t* arrayBuffer = JS_GetArrayBufferData(jsArrayBuffer);
uint8_t* arrayBuffer = JS_GetStableArrayBufferData(aCx, jsArrayBuffer);
if (!arrayBuffer) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
nsCOMPtr<nsIInputStream> stream;
rv = blob->GetInternalStream(getter_AddRefs(stream));

View File

@ -133,6 +133,7 @@ static const char *sExtensionNames[] = {
"GL_EXT_framebuffer_sRGB",
"GL_KHR_debug",
"GL_ARB_half_float_pixel",
"GL_EXT_frag_depth",
nullptr
};

View File

@ -90,6 +90,7 @@ MOZ_BEGIN_ENUM_CLASS(GLFeature)
element_index_uint,
ES2_compatibility,
ES3_compatibility,
frag_depth,
framebuffer_blit,
framebuffer_multisample,
framebuffer_object,
@ -410,6 +411,7 @@ public:
EXT_framebuffer_sRGB,
KHR_debug,
ARB_half_float_pixel,
EXT_frag_depth,
Extensions_Max,
Extensions_End
};
@ -1160,7 +1162,7 @@ public:
AFTER_GL_CALL;
}
void fGetObjectPtrLabel(GLvoid* ptr, GLsizei bufSize, GLsizei* length, GLchar* label) {
void fGetObjectPtrLabel(const GLvoid* ptr, GLsizei bufSize, GLsizei* length, GLchar* label) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fGetObjectPtrLabel);
mSymbols.fGetObjectPtrLabel(ptr, bufSize, length, label);
@ -1191,7 +1193,7 @@ public:
AFTER_GL_CALL;
}
void fTexParameteriv(GLenum target, GLenum pname, GLint* params) {
void fTexParameteriv(GLenum target, GLenum pname, const GLint* params) {
BEFORE_GL_CALL;
mSymbols.fTexParameteriv(target, pname, params);
AFTER_GL_CALL;
@ -1225,13 +1227,13 @@ public:
AFTER_GL_CALL;
}
void fGetTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {
void fGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
BEFORE_GL_CALL;
mSymbols.fGetTexParameterfv(target, pname, params);
AFTER_GL_CALL;
}
void fGetTexParameteriv(GLenum target, GLenum pname, const GLint *params) {
void fGetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
BEFORE_GL_CALL;
mSymbols.fGetTexParameteriv(target, pname, params);
AFTER_GL_CALL;
@ -1334,7 +1336,7 @@ public:
AFTER_GL_CALL;
}
void fObjectPtrLabel(GLvoid* ptr, GLsizei length, const GLchar* label) {
void fObjectPtrLabel(const GLvoid* ptr, GLsizei length, const GLchar* label) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fObjectPtrLabel);
mSymbols.fObjectPtrLabel(ptr, length, label);

View File

@ -111,6 +111,15 @@ static const FeatureInfo sFeatureInfoArr[] = {
GLContext::Extensions_End
}
},
{
"frag_depth",
200, // OpenGL version
300, // OpenGL ES version
{
GLContext::EXT_frag_depth,
GLContext::Extensions_End
}
},
{
"framebuffer_blit",
300, // OpenGL version

View File

@ -142,12 +142,12 @@ GrGLvoid glCullFace_mozilla(GrGLenum mode)
GrGLvoid glDeleteBuffers_mozilla(GrGLsizei n, const GrGLuint* buffers)
{
return sGLContext.get()->fDeleteBuffers(n, const_cast<GrGLuint*>(buffers));
return sGLContext.get()->fDeleteBuffers(n, buffers);
}
GrGLvoid glDeleteFramebuffers_mozilla(GrGLsizei n, const GrGLuint* framebuffers)
{
return sGLContext.get()->fDeleteFramebuffers(n, const_cast<GrGLuint*>(framebuffers));
return sGLContext.get()->fDeleteFramebuffers(n, framebuffers);
}
GrGLvoid glDeleteProgram_mozilla(GrGLuint program)
@ -157,7 +157,7 @@ GrGLvoid glDeleteProgram_mozilla(GrGLuint program)
GrGLvoid glDeleteRenderbuffers_mozilla(GrGLsizei n, const GrGLuint* renderbuffers)
{
return sGLContext.get()->fDeleteRenderbuffers(n, const_cast<GrGLuint*>(renderbuffers));
return sGLContext.get()->fDeleteRenderbuffers(n, renderbuffers);
}
GrGLvoid glDeleteShader_mozilla(GrGLuint shader)
@ -167,7 +167,7 @@ GrGLvoid glDeleteShader_mozilla(GrGLuint shader)
GrGLvoid glDeleteTextures_mozilla(GrGLsizei n, const GrGLuint* textures)
{
return sGLContext.get()->fDeleteTextures(n, const_cast<GrGLuint*>(textures));
return sGLContext.get()->fDeleteTextures(n, textures);
}
GrGLvoid glDepthMask_mozilla(GrGLboolean flag)
@ -447,7 +447,7 @@ GrGLvoid glTexParameteri_mozilla(GrGLenum target, GrGLenum pname, GrGLint param)
GrGLvoid glTexParameteriv_mozilla(GrGLenum target, GrGLenum pname, const GrGLint* params)
{
return sGLContext.get()->fTexParameteriv(target, pname, const_cast<GrGLint*>(params));
return sGLContext.get()->fTexParameteriv(target, pname, params);
}
GrGLvoid glTexSubImage2D_mozilla(GrGLenum target, GrGLint level,
@ -619,7 +619,7 @@ GrGLvoid glGenQueries_mozilla(GrGLsizei n, GrGLuint* ids)
GrGLvoid glDeleteQueries_mozilla(GrGLsizei n, const GrGLuint* ids)
{
return sGLContext.get()->fDeleteQueries(n, const_cast<GrGLuint*>(ids));
return sGLContext.get()->fDeleteQueries(n, ids);
}
GrGLvoid glBeginQuery_mozilla(GrGLenum target, GrGLuint id)
@ -651,7 +651,7 @@ GrGLvoid glGetQueryObjectuiv_mozilla(GrGLuint id, GrGLenum pname, GrGLuint* para
GrGLvoid glDrawBuffers_mozilla(GrGLsizei n, const GrGLenum* bufs)
{
return sGLContext.get()->fDrawBuffers(n, const_cast<GrGLenum*>(bufs));
return sGLContext.get()->fDrawBuffers(n, bufs);
}
// GLContext supports glMapBuffer on everything (GL_OES_mapbuffer)

View File

@ -139,7 +139,7 @@ struct GLContextSymbols
PFNGLGETQUERYOBJECTUIVPROC fGetQueryObjectuiv;
typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
PFNGLTEXPARAMETERIPROC fTexParameteri;
typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* param);
typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint* param);
PFNGLTEXPARAMETERIVPROC fTexParameteriv;
typedef void (GLAPIENTRY * PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
PFNGLTEXPARAMETERFPROC fTexParameterf;
@ -149,9 +149,9 @@ struct GLContextSymbols
PFNGLGETTEXIMAGEPROC fGetTexImage;
typedef void (GLAPIENTRY * PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
PFNGLGETTEXLEVELPARAMETERIVPROC fGetTexLevelParameteriv;
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
PFNGLGETTEXPARAMETERFVPROC fGetTexParameterfv;
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
PFNGLGETTEXPARAMETERIVPROC fGetTexParameteriv;
typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params);
PFNGLGETUNIFORMFVPROC fGetUniformfv;
@ -464,9 +464,9 @@ struct GLContextSymbols
PFNGLOBJECTLABEL fObjectLabel;
typedef void (GLAPIENTRY * PFNGLGETOBJECTLABEL) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label);
PFNGLGETOBJECTLABEL fGetObjectLabel;
typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABEL) (GLvoid* ptr, GLsizei length, const GLchar* label);
typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABEL) (const GLvoid* ptr, GLsizei length, const GLchar* label);
PFNGLOBJECTPTRLABEL fObjectPtrLabel;
typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABEL) (GLvoid* ptr, GLsizei bufSize, GLsizei* length, GLchar* label);
typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABEL) (const GLvoid* ptr, GLsizei bufSize, GLsizei* length, GLchar* label);
PFNGLGETOBJECTPTRLABEL fGetObjectPtrLabel;
};

View File

@ -156,7 +156,8 @@ GLReadTexImageHelper::DidGLErrorOccur(const char* str)
}
static bool
GetActualReadFormats(GLContext* gl, GLenum destFormat, GLenum destType,
GetActualReadFormats(GLContext* gl,
GLenum destFormat, GLenum destType,
GLenum& readFormat, GLenum& readType)
{
if (destFormat == LOCAL_GL_RGBA &&
@ -231,16 +232,43 @@ static void SwapRAndBComponents(DataSourceSurface* surf)
}
}
static int
CalcStride(int width, int pixelSize, int alignment)
{
MOZ_ASSERT(alignment);
int stride = width * pixelSize;
if (stride % alignment) { // Extra at the end of the line?
int alignmentCount = stride / alignment;
stride = (alignmentCount+1) * alignment;
}
return stride;
}
static int
GuessAlignment(int width, int pixelSize, int stride)
{
int alignment = 8; // Max GLES allows.
while (CalcStride(width, pixelSize, alignment) != stride) {
alignment /= 2;
if (!alignment) {
MOZ_ASSERT(alignment);
return 1;
}
}
return alignment;
}
void
ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
gl->MakeCurrent();
MOZ_ASSERT(dest->GetSize() != gfxIntSize(0, 0));
/* gfxImageFormat::ARGB32:
* RGBA+UByte: be[RGBA], le[ABGR]
* RGBA+UInt: le[RGBA]
* BGRA+UInt: le[BGRA]
* BGRA+UIntRev: le[ARGB]
* RGBA+UByte: be[RGBA], le[ABGR]
* RGBA+UInt: be[ABGR], le[RGBA]
* BGRA+UInt: be[ARGB], le[BGRA]
* BGRA+UIntRev: be[BGRA], le[ARGB]
*
* gfxImageFormat::RGB16_565:
* RGB+UShort: le[rrrrrggg,gggbbbbb]
@ -269,7 +297,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
default:
MOZ_CRASH("Bad format.");
}
MOZ_ASSERT(dest->Stride() == dest->Width() * destPixelSize);
MOZ_ASSERT(dest->Width() * destPixelSize <= dest->Stride());
GLenum readFormat = destFormat;
GLenum readType = destType;
@ -279,7 +307,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
nsAutoPtr<gfxImageSurface> tempSurf;
gfxImageSurface* readSurf = nullptr;
int readPixelSize = 0;
int readAlignment = 0;
if (needsTempSurf) {
if (gl->DebugMode()) {
NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
@ -294,7 +322,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
break;
}
case LOCAL_GL_RGB: {
MOZ_ASSERT(readPixelSize == 2);
MOZ_ASSERT(destPixelSize == 2);
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
readFormatGFX = SurfaceFormat::R5G6B5;
break;
@ -307,17 +335,17 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
switch (readType) {
case LOCAL_GL_UNSIGNED_BYTE: {
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
readPixelSize = 4;
readAlignment = 1;
break;
}
case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: {
MOZ_ASSERT(readFormat == LOCAL_GL_BGRA);
readPixelSize = 4;
readAlignment = 4;
break;
}
case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: {
MOZ_ASSERT(readFormat == LOCAL_GL_RGB);
readPixelSize = 2;
readAlignment = 2;
break;
}
default: {
@ -330,16 +358,20 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
false);
readSurf = tempSurf;
} else {
readPixelSize = destPixelSize;
// Figure out alignment. We don't need to know why, we just need it
// to be valid.
readAlignment = GuessAlignment(dest->Width(),
destPixelSize,
dest->Stride());
readSurf = dest;
}
MOZ_ASSERT(readPixelSize);
MOZ_ASSERT(readAlignment);
GLint currentPackAlignment = 0;
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &currentPackAlignment);
if (currentPackAlignment != readPixelSize)
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readPixelSize);
if (currentPackAlignment != readAlignment)
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment);
GLsizei width = dest->Width();
GLsizei height = dest->Height();
@ -351,7 +383,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
readSurf->Data());
readSurf->MarkDirty();
if (currentPackAlignment != readPixelSize)
if (currentPackAlignment != readAlignment)
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
if (readSurf != dest) {
@ -387,6 +419,8 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
if (!alphaBits) {
const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0);
MOZ_ASSERT(dest->Width() * destPixelSize == dest->Stride());
dest->Flush();
uint32_t* itr = (uint32_t*)dest->Data();
uint32_t testPixel = *itr;

View File

@ -294,8 +294,7 @@ SharedSurface_Basic::~SharedSurface_Basic()
if (!mGL->MakeCurrent())
return;
GLuint tex = mTex;
mGL->fDeleteTextures(1, &tex);
mGL->fDeleteTextures(1, &mTex);
}
void
@ -339,8 +338,7 @@ SharedSurface_GLTexture::~SharedSurface_GLTexture()
if (!mGL->MakeCurrent())
return;
GLuint tex = mTex;
mGL->fDeleteTextures(1, &tex);
mGL->fDeleteTextures(1, &mTex);
if (mSync) {
mGL->fDeleteSync(mSync);

View File

@ -141,7 +141,7 @@ SharedSurface_Gralloc::~SharedSurface_Gralloc()
DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
mGL->MakeCurrent();
mGL->fDeleteTextures(1, (GLuint*)&mProdTex);
mGL->fDeleteTextures(1, &mProdTex);
}
void

View File

@ -566,8 +566,8 @@ BufferTextureClient::Lock(OpenMode aMode)
// XXX - Turn this into a fatal assertion as soon as Bug 952507 is fixed
NS_WARN_IF_FALSE(!mLocked, "The TextureClient is already Locked!");
mOpenMode = aMode;
mLocked = true;
return IsValid() && IsAllocated();
mLocked = IsValid() && IsAllocated();;
return mLocked;
}
void

View File

@ -843,6 +843,24 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
namespace js {
/*
* Augment the generic Rooted<T> interface when T = JSObject* with
* class-querying and downcasting operations.
*
* Given a Rooted<JSObject*> obj, one can view
* Handle<StringObject*> h = obj.as<StringObject*>();
* as an optimization of
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
* Handle<StringObject*> h = rooted;
*/
template <>
class RootedBase<JSObject*>
{
public:
template <class U>
JS::Handle<U*> as() const;
};
/*
* Mark a stack location as a root for the rooting analysis, without actually
* rooting it in release builds. This should only be used for stack locations

1
js/src/aclocal.m4 vendored
View File

@ -3,6 +3,7 @@ dnl Local autoconf macros used with mozilla
dnl The contents of this file are under the Public Domain.
dnl
builtin(include, ../../build/autoconf/hotfixes.m4)dnl
builtin(include, ../../build/autoconf/acwinpaths.m4)dnl
builtin(include, ../../build/autoconf/hooks.m4)dnl
builtin(include, ../../build/autoconf/config.status.m4)dnl

View File

@ -2414,7 +2414,10 @@ ImplicitConvert(JSContext* cx,
// Convert ArrayBuffer to pointer without any copy.
// Just as with C arrays, we make no effort to
// keep the ArrayBuffer alive.
*static_cast<void**>(buffer) = JS_GetArrayBufferData(valObj);
void* p = JS_GetStableArrayBufferData(cx, valObj);
if (!p)
return false;
*static_cast<void**>(buffer) = p;
break;
} if (!JSVAL_IS_PRIMITIVE(val) && JS_IsTypedArrayObject(valObj)) {
if(!CanConvertTypedArrayItemTo(baseType, valObj, cx)) {

View File

@ -0,0 +1,15 @@
// XXXshu: I tried wrapping the entire test in an |if (pjs)|, but the timing
// is fragile and it no longer reproduced the bug, thus getting this value at
// the beginning.
var pjs = getBuildConfiguration().parallelJS;
function f(a, b) {
var o = a;
gczeal(2);
}
f(3, 4);
var len = 5000;
var iters = 100;
for (var i = 0; i < iters; i++) {
var par = pjs ? Array.buildPar(len, fill) : true;
}
function fill(i) { return 10/i; }

View File

@ -44,7 +44,7 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
CHECK_SAME(v, INT_TO_JSVAL(size));
// Modifying the underlying data should update the value returned through the view
uint8_t *data = JS_GetArrayBufferData(obj);
uint8_t *data = JS_GetStableArrayBufferData(cx, obj);
CHECK(data != nullptr);
*reinterpret_cast<uint32_t*>(data) = MAGIC_VALUE_2;
CHECK(JS_GetElement(cx, view, 0, &v));
@ -74,13 +74,13 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
// Transfer to a new ArrayBuffer
JS::RootedObject dst(cx, JS_NewArrayBufferWithContents(cx, contents));
CHECK(JS_IsArrayBufferObject(dst));
data = JS_GetArrayBufferData(obj);
data = JS_GetStableArrayBufferData(cx, obj);
JS::RootedObject dstview(cx, JS_NewInt32ArrayWithBuffer(cx, dst, 0, -1));
CHECK(dstview != nullptr);
CHECK_EQUAL(JS_GetArrayBufferByteLength(dst), size);
data = JS_GetArrayBufferData(dst);
data = JS_GetStableArrayBufferData(cx, dst);
CHECK(data != nullptr);
CHECK_EQUAL(*reinterpret_cast<uint32_t*>(data), MAGIC_VALUE_2);
CHECK(JS_GetElement(cx, dstview, 0, &v));

View File

@ -37,7 +37,7 @@ BEGIN_TEST(testTypedArrays)
CHECK(!JS_IsArrayBufferObject(dummy));
CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer), nbytes);
memset(JS_GetArrayBufferData(buffer), 1, nbytes);
memset(JS_GetStableArrayBufferData(cx, buffer), 1, nbytes);
ok = ok &&
TestArrayFromBuffer<JS_NewInt8ArrayWithBuffer, JS_NewInt8ArrayFromArray, int8_t, JS_GetInt8ArrayData>(cx) &&
@ -97,7 +97,7 @@ TestArrayFromBuffer(JSContext *cx)
size_t nbytes = elts * sizeof(Element);
RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
uint8_t *bufdata;
CHECK(bufdata = JS_GetArrayBufferData(buffer));
CHECK(bufdata = JS_GetStableArrayBufferData(cx, buffer));
memset(bufdata, 1, nbytes);
{
@ -113,7 +113,7 @@ TestArrayFromBuffer(JSContext *cx)
Element *data;
CHECK(data = GetData(array));
CHECK(bufdata = JS_GetArrayBufferData(buffer));
CHECK(bufdata = JS_GetStableArrayBufferData(cx, buffer));
CHECK_EQUAL((void*) data, (void*) bufdata);
CHECK_EQUAL(*bufdata, 1);

View File

@ -6297,3 +6297,9 @@ JSAutoByteString::encodeLatin1(ExclusiveContext *cx, JSString *str)
mBytes = LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
return mBytes;
}
JS_PUBLIC_API(void)
JS::SetLargeAllocationFailureCallback(JSRuntime *rt, JS::LargeAllocationFailureCallback lafc)
{
rt->largeAllocationFailureCallback = lafc;
}

View File

@ -3173,9 +3173,9 @@ JS_StealArrayBufferContents(JSContext *cx, JS::HandleObject obj, void **contents
* the number of payload bytes required. The pointer to pass to
* JS_NewArrayBufferWithContents is returned in |contents|. The pointer to the
* |nbytes| of usable memory is returned in |data|. (*|contents| will contain a
* header before |data|.) The only legal operations on *|contents| is to free
* it, or pass it to JS_NewArrayBufferWithContents or
* JS_ReallocateArrayBufferContents.
* header before |data|.) The only legal operations on *|contents| are to pass
* it to either JS_NewArrayBufferWithContents or
* JS_ReallocateArrayBufferContents, or free it with js_free or JS_free.
*/
extern JS_PUBLIC_API(bool)
JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void **contents, uint8_t **data);
@ -4919,6 +4919,20 @@ class MOZ_STACK_CLASS JS_PUBLIC_API(ForOfIterator) {
bool materializeArrayIterator();
};
/*
* If a large allocation fails, the JS engine may call the large-allocation-
* failure callback, if set, to allow the embedding to flush caches, possibly
* perform shrinking GCs, etc. to make some room so that the allocation will
* succeed if retried.
*/
typedef void
(* LargeAllocationFailureCallback)();
extern JS_PUBLIC_API(void)
SetLargeAllocationFailureCallback(JSRuntime *rt, LargeAllocationFailureCallback afc);
} /* namespace JS */
#endif /* jsapi_h */

View File

@ -555,16 +555,6 @@ struct JSContext : public js::ExclusiveContext,
void enterGenerator(JSGenerator *gen);
void leaveGenerator(JSGenerator *gen);
void *onOutOfMemory(void *p, size_t nbytes) {
return runtime()->onOutOfMemory(p, nbytes, this);
}
void updateMallocCounter(size_t nbytes) {
runtime()->updateMallocCounter(zone(), nbytes);
}
void reportAllocationOverflow() {
js_ReportAllocationOverflow(this);
}
bool isExceptionPending() {
return throwing;
}

View File

@ -1347,18 +1347,6 @@ JS_IsArrayBufferObject(JSObject *obj);
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj);
/*
* Return a pointer to an array buffer's data. The buffer is still owned by the
* array buffer object, and should not be modified on another thread. The
* returned pointer is stable across GCs.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj);
/*
* Return the number of elements in a typed array.
*
@ -1407,13 +1395,17 @@ JS_GetArrayBufferViewByteLength(JSObject *obj);
/*
* Return a pointer to the start of the data referenced by a typed array. The
* data is still owned by the typed array, and should not be modified on
* another thread.
* another thread. Furthermore, the pointer can become invalid on GC (if the
* data is small and fits inside the array's GC header), so callers must take
* care not to hold on across anything that could GC.
*
* |obj| must have passed a JS_Is*Array test, or somehow be known that it would
* pass such a test: it is a typed array or a wrapper of a typed array, and the
* unwrapping will succeed.
*/
extern JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj);
extern JS_FRIEND_API(int8_t *)
JS_GetInt8ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint8_t *)
@ -1433,6 +1425,13 @@ JS_GetFloat32ArrayData(JSObject *obj);
extern JS_FRIEND_API(double *)
JS_GetFloat64ArrayData(JSObject *obj);
/*
* Stable versions of the above functions where the buffer remains valid as long
* as the object is live.
*/
extern JS_FRIEND_API(uint8_t *)
JS_GetStableArrayBufferData(JSContext *cx, JSObject *obj);
/*
* Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
* versions when possible.

View File

@ -1210,6 +1210,15 @@ class JSObject : public js::ObjectImpl
void operator=(const JSObject &other) MOZ_DELETE;
};
template <class U>
MOZ_ALWAYS_INLINE JS::Handle<U*>
js::RootedBase<JSObject*>::as() const
{
const JS::Rooted<JSObject*> &self = *static_cast<const JS::Rooted<JSObject*>*>(this);
JS_ASSERT(self->is<U>());
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
}
/*
* The only sensible way to compare JSObject with == is by identity. We use
* const& instead of * as a syntactic way to assert non-null. This leads to an

View File

@ -1294,6 +1294,7 @@ ScriptSource::setSourceCopy(ExclusiveContext *cx, const jschar *src, uint32_t le
argumentsNotIncluded_ = argumentsNotIncluded;
// There are several cases where source compression is not a good idea:
// - If the script is tiny, then compression will save little or no space.
// - If the script is enormous, then decompression can take seconds. With
// lazy parsing, decompression is not uncommon, so this can significantly
// increase latency.
@ -1320,8 +1321,9 @@ ScriptSource::setSourceCopy(ExclusiveContext *cx, const jschar *src, uint32_t le
#else
bool canCompressOffThread = false;
#endif
const size_t TINY_SCRIPT = 256;
const size_t HUGE_SCRIPT = 5 * 1024 * 1024;
if (length < HUGE_SCRIPT && canCompressOffThread) {
if (TINY_SCRIPT <= length && length < HUGE_SCRIPT && canCompressOffThread) {
task->ss = this;
task->chars = src;
ready_ = false;
@ -1360,48 +1362,46 @@ SourceCompressionTask::work()
// threadsafe. We have to use the js_* variants.
#ifdef USE_ZLIB
const size_t COMPRESS_THRESHOLD = 512;
if (nbytes >= COMPRESS_THRESHOLD) {
// Try to keep the maximum memory usage down by only allocating half the
// size of the string, first.
size_t firstSize = nbytes / 2;
if (!ss->adjustDataSize(firstSize))
return false;
Compressor comp(reinterpret_cast<const unsigned char *>(chars), nbytes);
if (!comp.init())
return false;
comp.setOutput(ss->data.compressed, firstSize);
bool cont = !abort_;
while (cont) {
switch (comp.compressMore()) {
case Compressor::CONTINUE:
break;
case Compressor::MOREOUTPUT: {
if (comp.outWritten() == nbytes) {
cont = false;
break;
}
// The compressed output is greater than half the size of the
// original string. Reallocate to the full size.
if (!ss->adjustDataSize(nbytes))
return false;
comp.setOutput(ss->data.compressed, nbytes);
break;
}
case Compressor::DONE:
// Try to keep the maximum memory usage down by only allocating half the
// size of the string, first.
size_t firstSize = nbytes / 2;
if (!ss->adjustDataSize(firstSize))
return false;
Compressor comp(reinterpret_cast<const unsigned char *>(chars), nbytes);
if (!comp.init())
return false;
comp.setOutput(ss->data.compressed, firstSize);
bool cont = !abort_;
while (cont) {
switch (comp.compressMore()) {
case Compressor::CONTINUE:
break;
case Compressor::MOREOUTPUT: {
if (comp.outWritten() == nbytes) {
cont = false;
break;
case Compressor::OOM:
return false;
}
cont = cont && !abort_;
// The compressed output is greater than half the size of the
// original string. Reallocate to the full size.
if (!ss->adjustDataSize(nbytes))
return false;
comp.setOutput(ss->data.compressed, nbytes);
break;
}
case Compressor::DONE:
cont = false;
break;
case Compressor::OOM:
return false;
}
compressedLength = comp.outWritten();
if (abort_ || compressedLength == nbytes)
compressedLength = 0;
cont = cont && !abort_;
}
compressedLength = comp.outWritten();
if (abort_ || compressedLength == nbytes)
compressedLength = 0;
#endif
if (compressedLength == 0) {
if (!ss->adjustDataSize(nbytes))
return false;

View File

@ -361,6 +361,15 @@ class ScriptSource
{
friend class SourceCompressionTask;
// A note on concurrency:
//
// The source may be compressed by a worker thread during parsing. (See
// SourceCompressionTask.) When compression is running in the background,
// ready() returns false. The compression thread touches the |data| union
// and |compressedLength_|. Therefore, it is not safe to read these members
// unless ready() is true. With that said, users of the public ScriptSource
// API should be fine.
union {
// Before setSourceCopy or setSource are successfully called, this union
// has a nullptr pointer. When the script source is ready,
@ -416,7 +425,7 @@ class ScriptSource
bool hasIntroductionOffset_:1;
public:
ScriptSource(JSPrincipals *originPrincipals)
explicit ScriptSource(JSPrincipals *originPrincipals)
: refs(0),
length_(0),
compressedLength_(0),
@ -451,7 +460,7 @@ class ScriptSource
bool ready() const { return ready_; }
void setSourceRetrievable() { sourceRetrievable_ = true; }
bool sourceRetrievable() const { return sourceRetrievable_; }
bool hasSourceData() const { return !!data.source || !ready(); }
bool hasSourceData() const { return !ready() || !!data.source; }
uint32_t length() const {
JS_ASSERT(hasSourceData());
return length_;

View File

@ -1175,8 +1175,6 @@ ForkJoinOperation::parallelExecution(ExecutionStatus *status)
// functions such as ForkJoin().
JS_ASSERT(ForkJoinContext::current() == nullptr);
ForkJoinActivation activation(cx_);
uint16_t from, to;
if (!computeBounds(&from, &to)) {
*status = ExecutionFatal;
@ -1189,6 +1187,7 @@ ForkJoinOperation::parallelExecution(ExecutionStatus *status)
return RedLight;
}
ForkJoinActivation activation(cx_);
ThreadPool *threadPool = &cx_->runtime()->threadPool;
ForkJoinShared shared(cx_, threadPool, fun_, from, to, &bailoutRecords_[0]);
if (!shared.init()) {

View File

@ -302,10 +302,11 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
useHelperThreads_(useHelperThreads),
parallelIonCompilationEnabled_(true),
parallelParsingEnabled_(true),
isWorkerRuntime_(false)
isWorkerRuntime_(false),
#ifdef DEBUG
, enteredPolicy(nullptr)
enteredPolicy(nullptr),
#endif
largeAllocationFailureCallback(nullptr)
{
liveRuntimesCount++;

View File

@ -1788,6 +1788,34 @@ struct JSRuntime : public JS::shadow::Runtime,
public:
js::AutoEnterPolicy *enteredPolicy;
#endif
/*
* These variations of malloc/calloc/realloc will call the
* large-allocation-failure callback on OOM and retry the allocation.
*/
JS::LargeAllocationFailureCallback largeAllocationFailureCallback;
static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
void *callocCanGC(size_t bytes) {
void *p = calloc_(bytes);
if (MOZ_LIKELY(!!p))
return p;
if (!largeAllocationFailureCallback || bytes < LARGE_ALLOCATION)
return nullptr;
largeAllocationFailureCallback();
return js_calloc(bytes);
}
void *reallocCanGC(void *p, size_t bytes) {
void *p2 = realloc_(p, bytes);
if (MOZ_LIKELY(!!p2))
return p2;
if (!largeAllocationFailureCallback || bytes < LARGE_ALLOCATION)
return nullptr;
largeAllocationFailureCallback();
return js_realloc(p, bytes);
}
};
namespace js {

View File

@ -240,13 +240,16 @@ AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr =
if (oldptr) {
ObjectElements *oldheader = static_cast<ObjectElements *>(oldptr);
uint32_t oldnbytes = ArrayBufferObject::headerInitializedLength(oldheader);
newheader = static_cast<ObjectElements *>(maybecx ? maybecx->realloc_(oldptr, size) : js_realloc(oldptr, size));
void *p = maybecx ? maybecx->runtime()->reallocCanGC(oldptr, size) : js_realloc(oldptr, size);
newheader = static_cast<ObjectElements *>(p);
// if we grew the array, we need to set the new bytes to 0
if (newheader && nbytes > oldnbytes)
memset(reinterpret_cast<uint8_t*>(newheader->elements()) + oldnbytes, 0, nbytes - oldnbytes);
} else {
newheader = static_cast<ObjectElements *>(maybecx ? maybecx->calloc_(size) : js_calloc(size));
void *p = maybecx ? maybecx->runtime()->callocCanGC(size) : js_calloc(size);
newheader = static_cast<ObjectElements *>(p);
}
if (!newheader) {
if (maybecx)
@ -254,45 +257,11 @@ AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr =
return nullptr;
}
// we rely on this being correct
ArrayBufferObject::updateElementsHeader(newheader, nbytes);
return newheader;
}
bool
ArrayBufferObject::allocateSlots(JSContext *maybecx, uint32_t bytes, bool clear)
{
/*
* ArrayBufferObjects delegate added properties to another JSObject, so
* their internal layout can use the object's fixed slots for storage.
* Set up the object to look like an array with an elements header.
*/
JS_ASSERT(!hasDynamicSlots() && !hasDynamicElements());
size_t usableSlots = ARRAYBUFFER_RESERVED_SLOTS - ObjectElements::VALUES_PER_HEADER;
if (bytes > sizeof(Value) * usableSlots) {
ObjectElements *header = AllocateArrayBufferContents(maybecx, bytes);
if (!header)
return false;
elements = header->elements();
#ifdef JSGC_GENERATIONAL
JSRuntime *rt = runtimeFromMainThread();
rt->gcNursery.notifyNewElements(this, header);
#endif
} else {
setFixedElements();
if (clear)
memset(dataPointer(), 0, bytes);
}
initElementsHeader(getElementsHeader(), bytes);
return true;
}
static inline void
PostBarrierTypedArrayObject(JSObject *obj)
{
@ -386,7 +355,7 @@ ArrayBufferObject::neuterViews(JSContext *cx, Handle<ArrayBufferObject*> buffer)
}
void
ArrayBufferObject::changeContents(JSContext *maybecx, ObjectElements *newHeader)
ArrayBufferObject::changeContents(JSContext *cx, ObjectElements *newHeader)
{
JS_ASSERT(!isAsmJSArrayBuffer());
@ -402,8 +371,7 @@ ArrayBufferObject::changeContents(JSContext *maybecx, ObjectElements *newHeader)
view->setPrivate(reinterpret_cast<uint8_t*>(newDataPtr));
// Notify compiled jit code that the base pointer has moved.
if (maybecx)
MarkObjectStateChange(maybecx, view);
MarkObjectStateChange(cx, view);
}
// The list of views in the old header is reachable if the contents are
@ -447,49 +415,23 @@ ArrayBufferObject::neuter(JSContext *cx)
getElementsHeader()->setIsNeuteredBuffer();
}
bool
ArrayBufferObject::copyData(JSContext *maybecx)
/* static */ bool
ArrayBufferObject::ensureNonInline(JSContext *cx, Handle<ArrayBufferObject*> buffer)
{
ObjectElements *newHeader = AllocateArrayBufferContents(maybecx, byteLength());
if (buffer->hasDynamicElements())
return true;
ObjectElements *newHeader = AllocateArrayBufferContents(cx, buffer->byteLength());
if (!newHeader)
return false;
memcpy(reinterpret_cast<void*>(newHeader->elements()), dataPointer(), byteLength());
changeContents(maybecx, newHeader);
void *newHeaderDataPointer = reinterpret_cast<void*>(newHeader->elements());
memcpy(newHeaderDataPointer, buffer->dataPointer(), buffer->byteLength());
buffer->changeContents(cx, newHeader);
return true;
}
bool
ArrayBufferObject::ensureNonInline(JSContext *maybecx)
{
if (hasDynamicElements())
return true;
return copyData(maybecx);
}
// If the ArrayBuffer already contains dynamic contents, hand them back.
// Otherwise, allocate some new contents and copy the data over, but in no case
// modify the original ArrayBuffer. (Also, any allocated contents will have no
// views linked to in its header.)
ObjectElements *
ArrayBufferObject::getTransferableContents(JSContext *maybecx, bool *callerOwns)
{
if (hasDynamicElements() && !isAsmJSArrayBuffer()) {
*callerOwns = false;
return getElementsHeader();
}
uint32_t byteLen = byteLength();
ObjectElements *newheader = AllocateArrayBufferContents(maybecx, byteLen);
if (!newheader)
return nullptr;
initElementsHeader(newheader, byteLen);
memcpy(reinterpret_cast<void*>(newheader->elements()), dataPointer(), byteLen);
*callerOwns = true;
return newheader;
}
#if defined(JS_ION) && defined(JS_CPU_X64)
// To avoid dynamically checking bounds on each load/store, asm.js code relies
// on the SIGSEGV handler in AsmJSSignalHandlers.cpp. However, this only works
@ -586,10 +528,10 @@ ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buf
if (buffer->isAsmJSArrayBuffer())
return true;
if (!buffer->ensureNonInline(cx))
if (!ensureNonInline(cx, buffer))
return false;
JS_ASSERT(buffer->hasDynamicElements());
JS_ASSERT(buffer->hasDynamicElements());
buffer->getElementsHeader()->setIsAsmJSArrayBuffer();
return true;
}
@ -643,7 +585,7 @@ ArrayBufferObject::addView(ArrayBufferViewObject *view)
SetViewList(this, view);
}
JSObject *
ArrayBufferObject *
ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, bool clear /* = true */)
{
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_));
@ -659,14 +601,37 @@ ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, bool clear /* = true *
return nullptr;
obj->setLastPropertyInfallible(empty);
/*
* The beginning stores an ObjectElements header structure holding the
* length. The rest of it is a flat data store for the array buffer.
*/
if (!obj->as<ArrayBufferObject>().allocateSlots(cx, nbytes, clear))
return nullptr;
// ArrayBufferObjects delegate added properties to another JSObject, so
// their internal layout can use the object's fixed slots for storage.
// Set up the object to look like an array with an elements header.
JS_ASSERT(!obj->hasDynamicSlots());
JS_ASSERT(!obj->hasDynamicElements());
return obj;
// The beginning stores an ObjectElements header structure holding the
// length. The rest of it is a flat data store for the array buffer.
size_t usableSlots = ARRAYBUFFER_RESERVED_SLOTS - ObjectElements::VALUES_PER_HEADER;
Handle<ArrayBufferObject*> buffer = obj.as<ArrayBufferObject>();
if (nbytes > sizeof(Value) * usableSlots) {
ObjectElements *header = AllocateArrayBufferContents(cx, nbytes);
if (!header)
return nullptr;
buffer->elements = header->elements();
#ifdef JSGC_GENERATIONAL
JSRuntime *rt = buffer->runtimeFromMainThread();
rt->gcNursery.notifyNewElements(buffer, header);
#endif
} else {
buffer->setFixedElements();
if (clear)
memset(buffer->dataPointer(), 0, nbytes);
}
buffer->initElementsHeader(buffer->getElementsHeader(), nbytes);
return buffer;
}
JSObject *
@ -719,31 +684,48 @@ ArrayBufferObject::createDataViewForThis(JSContext *cx, unsigned argc, Value *vp
return CallNonGenericMethod<IsArrayBuffer, createDataViewForThisImpl>(cx, args);
}
bool
/* static */ bool
ArrayBufferObject::stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
uint8_t **data)
{
// Make the data stealable
bool own;
ObjectElements *header = reinterpret_cast<ObjectElements*>(buffer->getTransferableContents(cx, &own));
if (!header)
return false;
JS_ASSERT(!IsInsideNursery(cx->runtime(), header));
*contents = header;
*data = reinterpret_cast<uint8_t *>(header + 1);
// If the ArrayBuffer's elements are dynamically allocated and nothing else
// prevents us from stealing them, transfer ownership directly. Otherwise,
// the elements are small and allocated inside the ArrayBuffer object's GC
// header so we must make a copy.
ObjectElements *transferableHeader;
bool stolen;
if (buffer->hasDynamicElements() && !buffer->isAsmJSArrayBuffer()) {
stolen = true;
transferableHeader = buffer->getElementsHeader();
} else {
stolen = false;
uint32_t byteLen = buffer->byteLength();
transferableHeader = AllocateArrayBufferContents(cx, byteLen);
if (!transferableHeader)
return false;
initElementsHeader(transferableHeader, byteLen);
void *headerDataPointer = reinterpret_cast<void*>(transferableHeader->elements());
memcpy(headerDataPointer, buffer->dataPointer(), byteLen);
}
JS_ASSERT(!IsInsideNursery(cx->runtime(), transferableHeader));
*contents = transferableHeader;
*data = reinterpret_cast<uint8_t *>(transferableHeader + 1);
// Neuter the views, which may also mprotect(PROT_NONE) the buffer. So do
// it after copying out the data.
if (!ArrayBufferObject::neuterViews(cx, buffer))
return false;
if (!own) {
// If header has dynamically allocated elements, revert it back to
// fixed-element storage before neutering it.
// If the elements were taken from the neutered buffer, revert it back to
// using inline storage so it doesn't attempt to free the stolen elements
// when finalized.
if (stolen)
buffer->changeContents(cx, ObjectElements::fromElements(buffer->fixedElements()));
}
buffer->neuter(cx);
buffer->neuter(cx);
return true;
}
@ -4042,10 +4024,21 @@ JS_GetArrayBufferData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return nullptr;
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
if (!buffer.ensureNonInline(nullptr))
return obj->as<ArrayBufferObject>().dataPointer();
}
JS_FRIEND_API(uint8_t *)
JS_GetStableArrayBufferData(JSContext *cx, JSObject *obj)
{
obj = CheckedUnwrap(obj);
if (!obj)
return nullptr;
return buffer.dataPointer();
Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());
if (!ArrayBufferObject::ensureNonInline(cx, buffer))
return nullptr;
return buffer->dataPointer();
}
JS_FRIEND_API(bool)
@ -4103,9 +4096,9 @@ JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes,
}
JS_PUBLIC_API(bool)
JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents, uint8_t **data)
JS_ReallocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void **contents, uint8_t **data)
{
js::ObjectElements *header = AllocateArrayBufferContents(cx, nbytes, *contents);
js::ObjectElements *header = AllocateArrayBufferContents(maybecx, nbytes, *contents);
if (!header)
return false;

View File

@ -66,7 +66,7 @@ class ArrayBufferObject : public JSObject
static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
static JSObject *create(JSContext *cx, uint32_t nbytes, bool clear = true);
static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, bool clear = true);
static JSObject *createSlice(JSContext *cx, Handle<ArrayBufferObject*> arrayBuffer,
uint32_t begin, uint32_t end);
@ -168,34 +168,18 @@ class ArrayBufferObject : public JSObject
void addView(ArrayBufferViewObject *view);
bool allocateSlots(JSContext *cx, uint32_t size, bool clear);
void changeContents(JSContext *cx, ObjectElements *newHeader);
/*
* Copy the data into freshly-allocated memory. Used when un-inlining or
* when converting an ArrayBuffer to an AsmJS (MMU-assisted) ArrayBuffer.
*/
bool copyData(JSContext *maybecx);
/*
* Ensure data is not stored inline in the object. Used when handing back a
* GC-safe pointer.
*/
bool ensureNonInline(JSContext *maybecx);
static bool ensureNonInline(JSContext *cx, Handle<ArrayBufferObject*> buffer);
uint32_t byteLength() const {
return getElementsHeader()->initializedLength;
}
/*
* Return the contents of an ArrayBuffer without modifying the ArrayBuffer
* itself. Set *callerOwns to true if the caller has the only pointer to
* the returned contents (which is the case for inline or asm.js buffers),
* and false if the ArrayBuffer still owns the pointer.
*/
ObjectElements *getTransferableContents(JSContext *maybecx, bool *callerOwns);
/*
* Neuter all views of an ArrayBuffer.
*/
@ -209,7 +193,7 @@ class ArrayBufferObject : public JSObject
* Discard the ArrayBuffer contents. For asm.js buffers, at least, should
* be called after neuterViews().
*/
void neuter(JSContext *maybecx);
void neuter(JSContext *cx);
/*
* Check if the arrayBuffer contains any data. This will return false for

View File

@ -491,7 +491,7 @@ Scriptability::Unblock()
void
Scriptability::SetDocShellAllowsScript(bool aAllowed)
{
mDocShellAllowsScript = aAllowed;
mDocShellAllowsScript = aAllowed || mImmuneToScriptPolicy;
}
/* static */

View File

@ -42,18 +42,7 @@ AccessCheck::subsumes(JSCompartment *a, JSCompartment *b)
{
nsIPrincipal *aprin = GetCompartmentPrincipal(a);
nsIPrincipal *bprin = GetCompartmentPrincipal(b);
// If either a or b doesn't have principals, we don't have enough
// information to tell. Seeing as how this is Gecko, we are default-unsafe
// in this case.
if (!aprin || !bprin)
return true;
bool subsumes;
nsresult rv = aprin->Subsumes(bprin, &subsumes);
NS_ENSURE_SUCCESS(rv, false);
return subsumes;
return aprin->Subsumes(bprin);
}
bool
@ -62,21 +51,13 @@ AccessCheck::subsumes(JSObject *a, JSObject *b)
return subsumes(js::GetObjectCompartment(a), js::GetObjectCompartment(b));
}
// Same as above, but ignoring document.domain.
// Same as above, but considering document.domain.
bool
AccessCheck::subsumesIgnoringDomain(JSCompartment *a, JSCompartment *b)
AccessCheck::subsumesConsideringDomain(JSCompartment *a, JSCompartment *b)
{
nsIPrincipal *aprin = GetCompartmentPrincipal(a);
nsIPrincipal *bprin = GetCompartmentPrincipal(b);
if (!aprin || !bprin)
return false;
bool subsumes;
nsresult rv = aprin->SubsumesIgnoringDomain(bprin, &subsumes);
NS_ENSURE_SUCCESS(rv, false);
return subsumes;
return aprin->SubsumesConsideringDomain(bprin);
}
// Does the compartment of the wrapper subsumes the compartment of the wrappee?

View File

@ -20,7 +20,7 @@ class AccessCheck {
static bool subsumes(JSCompartment *a, JSCompartment *b);
static bool subsumes(JSObject *a, JSObject *b);
static bool wrapperSubsumes(JSObject *wrapper);
static bool subsumesIgnoringDomain(JSCompartment *a, JSCompartment *b);
static bool subsumesConsideringDomain(JSCompartment *a, JSCompartment *b);
static bool isChrome(JSCompartment *compartment);
static bool isChrome(JSObject *obj);
static bool callerIsChrome();

View File

@ -166,9 +166,9 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
//
// NB: We need to ignore domain here so that the security relationship we
// compute here can't change over time. See the comment above the other
// subsumesIgnoringDomain call below.
bool subsumes = AccessCheck::subsumesIgnoringDomain(js::GetContextCompartment(cx),
js::GetObjectCompartment(obj));
// subsumes call below.
bool subsumes = AccessCheck::subsumes(js::GetContextCompartment(cx),
js::GetObjectCompartment(obj));
XrayType xrayType = GetXrayType(obj);
if (!subsumes && xrayType == NotXray) {
JSProtoKey key = JSProto_Null;
@ -269,8 +269,8 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
// the correct (opaque) wrapper for the object below given the security
// characteristics of the two compartments.
if (!AccessCheck::isChrome(js::GetObjectCompartment(wrapScope)) &&
AccessCheck::subsumesIgnoringDomain(js::GetObjectCompartment(wrapScope),
js::GetObjectCompartment(obj)))
AccessCheck::subsumes(js::GetObjectCompartment(wrapScope),
js::GetObjectCompartment(obj)))
{
return DoubleWrap(cx, obj, flags);
}
@ -323,7 +323,7 @@ DEBUG_CheckUnwrapSafety(HandleObject obj, js::Wrapper *handler,
// this case.
} else {
// Otherwise, it should depend on whether the target subsumes the origin.
MOZ_ASSERT(handler->hasSecurityPolicy() == !AccessCheck::subsumes(target, origin));
MOZ_ASSERT(handler->hasSecurityPolicy() == !AccessCheck::subsumesConsideringDomain(target, origin));
}
}
#else
@ -385,8 +385,8 @@ WrapperFactory::Rewrap(JSContext *cx, HandleObject existing, HandleObject obj,
JSCompartment *target = js::GetContextCompartment(cx);
bool originIsChrome = AccessCheck::isChrome(origin);
bool targetIsChrome = AccessCheck::isChrome(target);
bool originSubsumesTarget = AccessCheck::subsumes(origin, target);
bool targetSubsumesOrigin = AccessCheck::subsumes(target, origin);
bool originSubsumesTarget = AccessCheck::subsumesConsideringDomain(origin, target);
bool targetSubsumesOrigin = AccessCheck::subsumesConsideringDomain(target, origin);
bool sameOrigin = targetSubsumesOrigin && originSubsumesTarget;
XrayType xrayType = GetXrayType(obj);
bool waiveXrayFlag = flags & WAIVE_XRAY_WRAPPER_FLAG;

View File

@ -350,7 +350,6 @@ XrayTraits::expandoObjectMatchesConsumer(JSContext *cx,
// First, compare the principals.
nsIPrincipal *o = GetExpandoObjectPrincipal(expandoObject);
bool equal;
// Note that it's very important here to ignore document.domain. We
// pull the principal for the expando object off of the first consumer
// for a given origin, and freely share the expandos amongst multiple
@ -358,9 +357,8 @@ XrayTraits::expandoObjectMatchesConsumer(JSContext *cx,
// no way to know whether _all_ consumers have opted in to collaboration
// by explicitly setting document.domain. So we just mandate that expando
// sharing is unaffected by it.
nsresult rv = consumerOrigin->EqualsIgnoringDomain(o, &equal);
if (NS_FAILED(rv) || !equal)
return false;
if (!consumerOrigin->Equals(o))
return false;
// Sandboxes want exclusive expando objects.
JSObject *owner = JS_GetReservedSlot(expandoObject,

View File

@ -0,0 +1,8 @@
<html><head><title>crash test for bug #945912</title></head>
<body>
<img src="data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgAQMAAACYU+zHAAAAAFBMVEVLqIlVAAAADUlEQVQY02Ng
GAX4AAABIAABYJ+juAAAAABJRU5ErkJggg==
">
</body>
</html>

View File

@ -1 +1,2 @@
load 374810-1.html
load 945912-1.html

View File

@ -0,0 +1,112 @@
/* 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 mozalloc_VolatileBuffer_h
#define mozalloc_VolatileBuffer_h
#include "mozilla/mozalloc.h"
#include "mozilla/RefPtr.h"
#include "mozilla/MemoryReporting.h"
/* VolatileBuffer
*
* This class represents a piece of memory that can potentially be reclaimed
* by the OS when not in use. As long as there are one or more
* VolatileBufferPtrs holding on to a VolatileBuffer, the memory will remain
* available. However, when there are no VolatileBufferPtrs holding a
* VolatileBuffer, the OS can purge the pages if it wants to. The OS can make
* better decisions about what pages to purge than we can.
*
* VolatileBuffers may not always be volatile - if the allocation is too small,
* or if the OS doesn't support the feature, or if the OS doesn't want to,
* the buffer will be allocated on heap.
*
* VolatileBuffer allocations are fallible. They are intended for uses where
* one may allocate large buffers for caching data. Init() must be called
* exactly once.
*
* After getting a reference to VolatileBuffer using VolatileBufferPtr,
* WasPurged() can be used to check if the OS purged any pages in the buffer.
* The OS cannot purge a buffer immediately after a VolatileBuffer is
* initialized. At least one VolatileBufferPtr must be created before the
* buffer can be purged, so the first use of VolatileBufferPtr does not need
* to check WasPurged().
*
* When a buffer is purged, some or all of the buffer is zeroed out. This
* API cannot tell which parts of the buffer were lost.
*
* VolatileBuffer is not thread safe. Do not use VolatileBufferPtrs on
* different threads.
*/
namespace mozilla {
class MOZALLOC_EXPORT VolatileBuffer : public RefCounted<VolatileBuffer>
{
friend class VolatileBufferPtr_base;
public:
VolatileBuffer();
~VolatileBuffer();
/* aAlignment must be a multiple of the pointer size */
bool Init(size_t aSize, size_t aAlignment = sizeof(void*));
size_t HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
size_t NonHeapSizeOfExcludingThis() const;
protected:
bool Lock(void** aBuf);
void Unlock();
bool OnHeap() const;
private:
void* mBuf;
size_t mSize;
int mLockCount;
#if defined(ANDROID)
int mFd;
#elif defined(XP_DARWIN)
bool mHeap;
#elif defined(XP_WIN)
bool mHeap;
bool mFirstLock;
#endif
};
class VolatileBufferPtr_base {
public:
VolatileBufferPtr_base(VolatileBuffer* vbuf) : mVBuf(vbuf) {
mPurged = !vbuf->Lock(&mMapping);
}
~VolatileBufferPtr_base() {
mVBuf->Unlock();
}
bool WasBufferPurged() const {
return mPurged;
}
protected:
void* mMapping;
private:
RefPtr<VolatileBuffer> mVBuf;
bool mPurged;
};
template <class T>
class VolatileBufferPtr : public VolatileBufferPtr_base
{
public:
VolatileBufferPtr(VolatileBuffer* vbuf) : VolatileBufferPtr_base(vbuf) {}
operator T*() const {
return (T*) mMapping;
}
};
}; /* namespace mozilla */
#endif /* mozalloc_VolatileBuffer_h */

View File

@ -0,0 +1,137 @@
/* 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 "VolatileBuffer.h"
#include "mozilla/Assertions.h"
#include "mozilla/NullPtr.h"
#include "mozilla/mozalloc.h"
#include <fcntl.h>
#include <linux/ashmem.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef MOZ_MEMORY
#ifdef MOZ_WIDGET_ANDROID
extern "C" int __wrap_posix_memalign(void** memptr, size_t alignment, size_t size);
#else
extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
#endif
#endif
#define MIN_VOLATILE_ALLOC_SIZE 8192
namespace mozilla {
VolatileBuffer::VolatileBuffer()
: mBuf(nullptr)
, mSize(0)
, mLockCount(0)
, mFd(-1)
{
}
bool
VolatileBuffer::Init(size_t aSize, size_t aAlignment)
{
MOZ_ASSERT(!mSize && !mBuf, "Init called twice");
MOZ_ASSERT(!(aAlignment % sizeof(void *)),
"Alignment must be multiple of pointer size");
mSize = aSize;
if (aSize < MIN_VOLATILE_ALLOC_SIZE) {
goto heap_alloc;
}
mFd = open("/" ASHMEM_NAME_DEF, O_RDWR);
if (mFd < 0) {
goto heap_alloc;
}
if (ioctl(mFd, ASHMEM_SET_SIZE, mSize) < 0) {
close(mFd);
mFd = -1;
goto heap_alloc;
}
mBuf = mmap(nullptr, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, 0);
if (mBuf != MAP_FAILED) {
return true;
}
heap_alloc:
#ifdef MOZ_MEMORY
#ifdef MOZ_WIDGET_ANDROID
__wrap_posix_memalign(&mBuf, aAlignment, aSize);
#else
posix_memalign(&mBuf, aAlignment, aSize);
#endif
#else
mBuf = memalign(aAlignment, aSize);
#endif
return !!mBuf;
}
VolatileBuffer::~VolatileBuffer()
{
if (OnHeap()) {
free(mBuf);
} else {
munmap(mBuf, mSize);
close(mFd);
}
}
bool
VolatileBuffer::Lock(void** aBuf)
{
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf;
if (++mLockCount > 1 || OnHeap()) {
return true;
}
// Zero offset and zero length means we want to pin/unpin the entire thing.
struct ashmem_pin pin = { 0, 0 };
return ioctl(mFd, ASHMEM_PIN, &pin) == ASHMEM_NOT_PURGED;
}
void
VolatileBuffer::Unlock()
{
MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
if (--mLockCount || OnHeap()) {
return;
}
struct ashmem_pin pin = { 0, 0 };
ioctl(mFd, ASHMEM_UNPIN, &pin);
}
bool
VolatileBuffer::OnHeap() const
{
return mFd < 0;
}
size_t
VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
return OnHeap() ? aMallocSizeOf(mBuf) : 0;
}
size_t
VolatileBuffer::NonHeapSizeOfExcludingThis() const
{
if (OnHeap()) {
return 0;
}
return (mSize + (PAGE_SIZE - 1)) & PAGE_MASK;
}
} // namespace mozilla

View File

@ -0,0 +1,80 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VolatileBuffer.h"
#include "mozilla/Assertions.h"
#include "mozilla/mozalloc.h"
#ifdef MOZ_MEMORY
int posix_memalign(void** memptr, size_t alignment, size_t size);
#endif
namespace mozilla {
VolatileBuffer::VolatileBuffer()
: mBuf(nullptr)
, mSize(0)
, mLockCount(0)
{
}
bool VolatileBuffer::Init(size_t aSize, size_t aAlignment)
{
MOZ_ASSERT(!mSize && !mBuf, "Init called twice");
MOZ_ASSERT(!(aAlignment % sizeof(void *)),
"Alignment must be multiple of pointer size");
mSize = aSize;
#if defined(MOZ_MEMORY)
posix_memalign(&mBuf, aAlignment, aSize);
#elif defined(HAVE_POSIX_MEMALIGN)
moz_posix_memalign(&mBuf, aAlignment, aSize);
#else
#error "No memalign implementation found"
#endif
return !!mBuf;
}
VolatileBuffer::~VolatileBuffer()
{
free(mBuf);
}
bool
VolatileBuffer::Lock(void** aBuf)
{
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf;
mLockCount++;
return true;
}
void
VolatileBuffer::Unlock()
{
mLockCount--;
MOZ_ASSERT(mLockCount >= 0, "VolatileBuffer unlocked too many times!");
}
bool
VolatileBuffer::OnHeap() const
{
return true;
}
size_t
VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(mBuf);
}
size_t
VolatileBuffer::NonHeapSizeOfExcludingThis() const
{
return 0;
}
} // namespace mozilla

View File

@ -0,0 +1,122 @@
/* 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 "VolatileBuffer.h"
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/mozalloc.h"
#include <mach/mach.h>
#include <sys/mman.h>
#include <unistd.h>
#define MIN_VOLATILE_ALLOC_SIZE 8192
namespace mozilla {
VolatileBuffer::VolatileBuffer()
: mBuf(nullptr)
, mSize(0)
, mLockCount(0)
, mHeap(false)
{
}
bool
VolatileBuffer::Init(size_t aSize, size_t aAlignment)
{
MOZ_ASSERT(!mSize && !mBuf, "Init called twice");
MOZ_ASSERT(!(aAlignment % sizeof(void *)),
"Alignment must be multiple of pointer size");
mSize = aSize;
kern_return_t ret = 0;
if (aSize < MIN_VOLATILE_ALLOC_SIZE) {
goto heap_alloc;
}
ret = vm_allocate(mach_task_self(),
(vm_address_t*)&mBuf,
mSize,
VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE);
if (ret == KERN_SUCCESS) {
return true;
}
heap_alloc:
moz_posix_memalign(&mBuf, aAlignment, aSize);
mHeap = true;
return !!mBuf;
}
VolatileBuffer::~VolatileBuffer()
{
if (OnHeap()) {
free(mBuf);
} else {
vm_deallocate(mach_task_self(), (vm_address_t)mBuf, mSize);
}
}
bool
VolatileBuffer::Lock(void** aBuf)
{
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf;
if (++mLockCount > 1 || OnHeap()) {
return true;
}
int state = VM_PURGABLE_NONVOLATILE;
kern_return_t ret =
vm_purgable_control(mach_task_self(),
(vm_address_t)mBuf,
VM_PURGABLE_SET_STATE,
&state);
return ret == KERN_SUCCESS && !(state & VM_PURGABLE_EMPTY);
}
void
VolatileBuffer::Unlock()
{
MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
if (--mLockCount || OnHeap()) {
return;
}
int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
DebugOnly<kern_return_t> ret =
vm_purgable_control(mach_task_self(),
(vm_address_t)mBuf,
VM_PURGABLE_SET_STATE,
&state);
MOZ_ASSERT(ret == KERN_SUCCESS, "Failed to set buffer as purgable");
}
bool
VolatileBuffer::OnHeap() const
{
return mHeap;
}
size_t
VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
return OnHeap() ? aMallocSizeOf(mBuf) : 0;
}
size_t
VolatileBuffer::NonHeapSizeOfExcludingThis() const
{
if (OnHeap()) {
return 0;
}
unsigned long pagemask = getpagesize() - 1;
return (mSize + pagemask) & ~pagemask;
}
} // namespace mozilla

View File

@ -0,0 +1,173 @@
/* 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/. */
#if defined(XP_WIN) || defined(XP_OS2)
# define MOZALLOC_EXPORT __declspec(dllexport)
#endif
#include "VolatileBuffer.h"
#include "mozilla/Assertions.h"
#include "mozilla/mozalloc.h"
#include <Windows.h>
#ifdef MOZ_MEMORY
extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
#endif
#ifndef MEM_RESET_UNDO
#define MEM_RESET_UNDO 0x1000000
#endif
#define MIN_VOLATILE_ALLOC_SIZE 8192
namespace mozilla {
VolatileBuffer::VolatileBuffer()
: mBuf(nullptr)
, mSize(0)
, mLockCount(0)
, mHeap(false)
, mFirstLock(true)
{
}
bool
VolatileBuffer::Init(size_t aSize, size_t aAlignment)
{
MOZ_ASSERT(!mSize && !mBuf, "Init called twice");
MOZ_ASSERT(!(aAlignment % sizeof(void *)),
"Alignment must be multiple of pointer size");
mSize = aSize;
if (aSize < MIN_VOLATILE_ALLOC_SIZE) {
goto heap_alloc;
}
static bool sCheckedVersion = false;
static bool sUndoSupported = false;
if (!sCheckedVersion) {
OSVERSIONINFOEX verinfo = { 0 };
verinfo.dwOSVersionInfoSize = sizeof(verinfo);
verinfo.dwMajorVersion = 6;
verinfo.dwMinorVersion = 2;
DWORDLONG mask = 0;
VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(mask, VER_MINORVERSION, VER_GREATER_EQUAL);
sUndoSupported = VerifyVersionInfo(&verinfo,
VER_MAJORVERSION | VER_MINORVERSION,
mask);
sCheckedVersion = true;
}
if (!sUndoSupported) {
goto heap_alloc;
}
mBuf = VirtualAllocEx(GetCurrentProcess(),
nullptr,
mSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
if (mBuf) {
return true;
}
heap_alloc:
#ifdef MOZ_MEMORY
posix_memalign(&mBuf, aAlignment, aSize);
#else
mBuf = _aligned_malloc(aSize, aAlignment);
#endif
mHeap = true;
return !!mBuf;
}
VolatileBuffer::~VolatileBuffer()
{
if (OnHeap()) {
#ifdef MOZ_MEMORY
free(mBuf);
#else
_aligned_free(mBuf);
#endif
} else {
VirtualFreeEx(GetCurrentProcess(), mBuf, 0, MEM_RELEASE);
}
}
bool
VolatileBuffer::Lock(void** aBuf)
{
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf;
if (++mLockCount > 1 || OnHeap()) {
return true;
}
// MEM_RESET_UNDO's behavior is undefined when called on memory that
// hasn't been MEM_RESET.
if (mFirstLock) {
mFirstLock = false;
return true;
}
void* addr = VirtualAllocEx(GetCurrentProcess(),
mBuf,
mSize,
MEM_RESET_UNDO,
PAGE_READWRITE);
return !!addr;
}
void
VolatileBuffer::Unlock()
{
MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
if (--mLockCount || OnHeap()) {
return;
}
void* addr = VirtualAllocEx(GetCurrentProcess(),
mBuf,
mSize,
MEM_RESET,
PAGE_READWRITE);
MOZ_ASSERT(addr, "Failed to MEM_RESET");
}
bool
VolatileBuffer::OnHeap() const
{
return mHeap;
}
size_t
VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
if (OnHeap()) {
#ifdef MOZ_MEMORY
return aMallocSizeOf(mBuf);
#else
return mSize;
#endif
}
return 0;
}
size_t
VolatileBuffer::NonHeapSizeOfExcludingThis() const
{
if (OnHeap()) {
return 0;
}
return (mSize + 4095) & ~4095;
}
} // namespace mozilla

View File

@ -10,6 +10,7 @@ EXPORTS.mozilla += [
'mozalloc.h',
'mozalloc_abort.h',
'mozalloc_oom.h',
'VolatileBuffer.h',
]
if CONFIG['MOZ_MSVC_STL_WRAP__RAISE'] or CONFIG['MOZ_MSVC_STL_WRAP__Throw']:
@ -38,6 +39,23 @@ UNIFIED_SOURCES += [
'mozalloc_oom.cpp',
]
if CONFIG['OS_TARGET'] == 'Android':
UNIFIED_SOURCES += [
'VolatileBufferAshmem.cpp',
]
elif CONFIG['OS_TARGET'] == 'Darwin':
UNIFIED_SOURCES += [
'VolatileBufferOSX.cpp',
]
elif CONFIG['OS_TARGET'] == 'WINNT':
UNIFIED_SOURCES += [
'VolatileBufferWindows.cpp',
]
else:
UNIFIED_SOURCES += [
'VolatileBufferFallback.cpp',
]
LIBRARY_NAME = 'mozalloc'
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
@ -47,3 +65,5 @@ else:
# The strndup declaration in string.h is in an ifdef __USE_GNU section
DEFINES['_GNU_SOURCE'] = True
TEST_TOOL_DIRS += ['tests']

View File

@ -0,0 +1,144 @@
/* 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 "TestHarness.h"
#include "mozilla/VolatileBuffer.h"
#include "mozilla/NullPtr.h"
#include <string.h>
#if defined(ANDROID)
#include <fcntl.h>
#include <linux/ashmem.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#elif defined(XP_DARWIN)
#include <mach/mach.h>
#endif
using namespace mozilla;
int main(int argc, char **argv)
{
ScopedXPCOM xpcom("VolatileBufferTests");
if (xpcom.failed()) {
return 1;
}
RefPtr<VolatileBuffer> heapbuf = new VolatileBuffer();
if (!heapbuf || !heapbuf->Init(512)) {
fail("Failed to initialize VolatileBuffer");
return 1;
}
{
VolatileBufferPtr<char> ptr(heapbuf);
if (ptr.WasBufferPurged()) {
fail("Buffer was immediately purged after initialization");
return 1;
}
if (!ptr) {
fail("Didn't get a pointer");
return 1;
}
}
RefPtr<VolatileBuffer> buf = new VolatileBuffer();
if (!buf || !buf->Init(16384)) {
fail("Failed to initialize VolatileBuffer");
return 1;
}
const char teststr[] = "foobar";
{
VolatileBufferPtr<char> ptr(buf);
if (ptr.WasBufferPurged()) {
fail("Buffer should not be purged immediately after initialization");
return 1;
}
if (!ptr) {
fail("Didn't get a pointer");
return 1;
}
{
VolatileBufferPtr<char> ptr2(buf);
if (ptr2.WasBufferPurged()) {
fail("Failed to Lock buffer again while currently locked");
return 1;
}
if (!ptr2) {
fail("Didn't get a pointer on the second lock");
return 1;
}
strcpy(ptr2, teststr);
}
}
{
VolatileBufferPtr<char> ptr(buf);
if (ptr.WasBufferPurged()) {
fail("Buffer was immediately purged after unlock");
return 1;
}
if (strcmp(ptr, teststr)) {
fail("Buffer failed to retain data after unlock");
return 1;
}
}
// Test purging if we know how to
#if defined(MOZ_WIDGET_GONK)
// This also works on Android, but we need root.
int fd = open("/" ASHMEM_NAME_DEF, O_RDWR);
if (fd < 0) {
fail("Failed to open ashmem device");
return 1;
}
if (ioctl(fd, ASHMEM_PURGE_ALL_CACHES, NULL) < 0) {
fail("Failed to purge ashmem caches");
return 1;
}
#elif defined(XP_DARWIN)
int state;
vm_purgable_control(mach_task_self(), (vm_address_t)NULL,
VM_PURGABLE_PURGE_ALL, &state);
#else
return 0;
#endif
if (!buf->NonHeapSizeOfExcludingThis()) {
fail("Buffer should not be allocated on heap");
return 1;
}
{
VolatileBufferPtr<char> ptr(buf);
if (!ptr.WasBufferPurged()) {
fail("Buffer should not be unpurged after forced purge");
return 1;
}
if (!strcmp(ptr, teststr)) {
fail("Purge did not actually purge data");
return 1;
}
}
{
VolatileBufferPtr<char> ptr(buf);
if (ptr.WasBufferPurged()) {
fail("Buffer still purged after lock");
return 1;
}
}
return 0;
}

View File

@ -0,0 +1,9 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
CPP_UNIT_TESTS += [
'TestVolatileBuffer.cpp',
]

View File

@ -164,6 +164,9 @@
*/
#define MALLOC_STATS
/* Memory filling (junk/poison/zero). */
#define MALLOC_FILL
#ifndef MALLOC_PRODUCTION
/*
* MALLOC_DEBUG enables assertions and other sanity checks, and disables
@ -171,9 +174,6 @@
*/
# define MALLOC_DEBUG
/* Memory filling (junk/zero). */
# define MALLOC_FILL
/* Allocation tracing. */
# ifndef MOZ_MEMORY_WINDOWS
# define MALLOC_UTRACE
@ -1287,13 +1287,18 @@ const char *_malloc_options = MOZ_MALLOC_OPTIONS;
static bool opt_abort = true;
#ifdef MALLOC_FILL
static bool opt_junk = true;
static bool opt_poison = true;
static bool opt_zero = false;
#endif
#else
static bool opt_abort = false;
#ifdef MALLOC_FILL
static bool opt_junk = false;
static const bool opt_junk = false;
static const bool opt_poison = true;
static const bool opt_zero = false;
#endif
#endif
static size_t opt_dirty_max = DIRTY_MAX_DEFAULT;
#ifdef MALLOC_BALANCE
static uint64_t opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT;
@ -1320,9 +1325,6 @@ static bool opt_sysv = false;
#ifdef MALLOC_XMALLOC
static bool opt_xmalloc = false;
#endif
#ifdef MALLOC_FILL
static bool opt_zero = false;
#endif
static int opt_narenas_lshift = 0;
#ifdef MALLOC_UTRACE
@ -4448,7 +4450,7 @@ arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
size = bin->reg_size;
#ifdef MALLOC_FILL
if (opt_junk)
if (opt_poison)
memset(ptr, 0x5a, size);
#endif
@ -4531,7 +4533,7 @@ arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
#ifdef MALLOC_FILL
#ifndef MALLOC_STATS
if (opt_junk)
if (opt_poison)
#endif
#endif
{
@ -4541,7 +4543,7 @@ arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
#ifdef MALLOC_FILL
#ifdef MALLOC_STATS
if (opt_junk)
if (opt_poison)
#endif
memset(ptr, 0x5a, size);
#endif
@ -4682,7 +4684,7 @@ arena_ralloc_large(void *ptr, size_t size, size_t oldsize)
if (psize == oldsize) {
/* Same size class. */
#ifdef MALLOC_FILL
if (opt_junk && size < oldsize) {
if (opt_poison && size < oldsize) {
memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
size);
}
@ -4699,7 +4701,7 @@ arena_ralloc_large(void *ptr, size_t size, size_t oldsize)
if (psize < oldsize) {
#ifdef MALLOC_FILL
/* Fill before shrinking in order avoid a race. */
if (opt_junk) {
if (opt_poison) {
memset((void *)((uintptr_t)ptr + size), 0x5a,
oldsize - size);
}
@ -4769,7 +4771,7 @@ arena_ralloc(void *ptr, size_t size, size_t oldsize)
return (ret);
IN_PLACE:
#ifdef MALLOC_FILL
if (opt_junk && size < oldsize)
if (opt_poison && size < oldsize)
memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
else if (opt_zero && size > oldsize)
memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize);
@ -5161,7 +5163,7 @@ huge_ralloc(void *ptr, size_t size, size_t oldsize)
CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) {
size_t psize = PAGE_CEILING(size);
#ifdef MALLOC_FILL
if (opt_junk && size < oldsize) {
if (opt_poison && size < oldsize) {
memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize
- size);
}
@ -5407,6 +5409,7 @@ malloc_print_stats(void)
_malloc_message("Boolean MALLOC_OPTIONS: ",
opt_abort ? "A" : "a", "", "");
#ifdef MALLOC_FILL
_malloc_message(opt_poison ? "C" : "c", "", "", "");
_malloc_message(opt_junk ? "J" : "j", "", "", "");
#endif
#ifdef MALLOC_PAGEFILE
@ -5750,6 +5753,16 @@ MALLOC_OUT:
opt_balance_threshold <<= 1;
#endif
break;
#ifdef MALLOC_FILL
#ifndef MALLOC_PRODUCTION
case 'c':
opt_poison = false;
break;
case 'C':
opt_poison = true;
break;
#endif
#endif
case 'f':
opt_dirty_max >>= 1;
break;
@ -5760,6 +5773,7 @@ MALLOC_OUT:
opt_dirty_max <<= 1;
break;
#ifdef MALLOC_FILL
#ifndef MALLOC_PRODUCTION
case 'j':
opt_junk = false;
break;
@ -5767,6 +5781,7 @@ MALLOC_OUT:
opt_junk = true;
break;
#endif
#endif
#ifndef MALLOC_STATIC_SIZES
case 'k':
/*
@ -5851,12 +5866,14 @@ MALLOC_OUT:
break;
#endif
#ifdef MALLOC_FILL
#ifndef MALLOC_PRODUCTION
case 'z':
opt_zero = false;
break;
case 'Z':
opt_zero = true;
break;
#endif
#endif
default: {
char cbuf[2];
@ -6581,6 +6598,11 @@ jemalloc_stats_impl(jemalloc_stats_t *stats)
stats->opt_junk =
#ifdef MALLOC_FILL
opt_junk ? true :
#endif
false;
stats->opt_poison =
#ifdef MALLOC_FILL
opt_poison ? true :
#endif
false;
stats->opt_utrace =

View File

@ -55,7 +55,8 @@ typedef struct {
* Run-time configuration settings.
*/
jemalloc_bool opt_abort; /* abort(3) on error? */
jemalloc_bool opt_junk; /* Fill allocated/free memory with 0xa5/0x5a? */
jemalloc_bool opt_junk; /* Fill allocated memory with 0xa5/0x5a? */
jemalloc_bool opt_poison; /* Fill free memory with 0xa5/0x5a? */
jemalloc_bool opt_utrace; /* Trace all allocation events? */
jemalloc_bool opt_sysv; /* SysV semantics? */
jemalloc_bool opt_xmalloc; /* abort(3) on OOM? */

View File

@ -485,3 +485,35 @@ if '-march=armv7' in CONFIG['OS_CFLAGS']:
DEFINES['MOZ_MIN_CPU_VERSION'] = 7
else:
DEFINES['MOZ_MIN_CPU_VERSION'] = 5
generated = add_android_eclipse_library_project('FennecGeneratedResources')
generated.package_name = 'org.mozilla.fennec.generatedresources'
generated.res = OBJDIR + '/res'
branding = add_android_eclipse_library_project('FennecBrandingResources')
branding.package_name = 'org.mozilla.fennec.brandingresources'
branding.res = TOPSRCDIR + '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res'
main = add_android_eclipse_project('Fennec', OBJDIR + '/AndroidManifest.xml')
main.package_name = 'org.mozilla.gecko'
main.res = SRCDIR + '/resources'
main.recursive_make_targets += ['.aapt.deps'] # Captures dependencies on Android manifest and all resources.
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in mgjar.generated_sources]
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in gbjar.generated_sources]
main.included_projects += ['../' + generated.name, '../' + branding.name]
main.extra_jars += [CONFIG['ANDROID_COMPAT_LIB']]
main.assets = TOPOBJDIR + '/dist/fennec/assets'
main.libs = TOPOBJDIR + '/dist/fennec/lib'
cpe = main.add_classpathentry('src', SRCDIR,
dstdir='src/org/mozilla/gecko',
exclude_patterns=['org/mozilla/gecko/tests/**'])
if not CONFIG['MOZ_CRASHREPORTER']:
cpe.exclude_patterns += ['org/mozilla/gecko/CrashReporter.java']
main.add_classpathentry('generated', OBJDIR + '/generated',
dstdir='generated')
main.add_classpathentry('thirdparty', TOPSRCDIR + '/mobile/android/thirdparty',
dstdir='thirdparty',
ignore_warnings=True)

View File

@ -5,3 +5,14 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
include('android-services.mozbuild')
main = add_android_eclipse_project('BackgroundInstrumentationTests', OBJDIR + '/AndroidManifest.xml')
main.package_name = 'org.mozilla.background.test'
main.res = SRCDIR + '/res'
main.recursive_make_targets += [
OBJDIR + '/AndroidManifest.xml',
TOPOBJDIR + '/mobile/android/base/tests/TestConstants.java']
main.referenced_projects += ['Fennec']
main.add_classpathentry('src', SRCDIR + '/src',
dstdir='src/org/mozilla/gecko/background')

View File

@ -1,56 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko.background.fxa;
import java.security.NoSuchAlgorithmException;
import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
import org.mozilla.gecko.background.testhelpers.WaitHelper;
import org.mozilla.gecko.browserid.BrowserIDKeyPair;
import org.mozilla.gecko.browserid.RSACryptoImplementation;
import org.mozilla.gecko.fxa.sync.FxAccount;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
public class TestLiveFxAccountOnDevice extends AndroidSyncTestCase {
protected final BrowserIDKeyPair keyPair;
public TestLiveFxAccountOnDevice() throws NoSuchAlgorithmException {
this.keyPair = RSACryptoImplementation.generateKeypair(1024);
}
public void testLogin() {
String email = "testtestd@mockmyid.com";
byte[] sessionTokenBytes = Utils.hex2Byte("8deef2af6acf532a07ad03ec7052e91f01213767b2bee6b27705253baff3eb72");
byte[] kA = Utils.hex2Byte("1defe49c39d697a4213ba129adcbf08e3e838be3d16d755367fd749cfaea65c9");
byte[] kB = Utils.hex2Byte("d02d8fe39f28b601159c543f2deeb8f72bdf2043e8279aa08496fbd9ebaea361");
String idpEndpoint = "https://api-accounts.dev.lcip.org";
String authEndpoint = "http://auth.oldsync.dev.lcip.org";
final FxAccount fxa = new FxAccount(email, sessionTokenBytes, kA, kB, idpEndpoint, authEndpoint);
WaitHelper.getTestWaiter().performWait(new Runnable() {
@Override
public void run() {
fxa.login(getApplicationContext(), keyPair, new FxAccount.Delegate() {
@Override
public void handleSuccess(String uid, String endpoint, AuthHeaderProvider authHeaderProvider) {
try {
assertNotNull(uid);
assertNotNull(endpoint);
WaitHelper.getTestWaiter().performNotify();
} catch (Throwable e) {
WaitHelper.getTestWaiter().performNotify(e);
}
}
@Override
public void handleError(Exception e) {
WaitHelper.getTestWaiter().performNotify(e);
}
});
}
});
}
}

View File

@ -1,110 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko.background.fxa;
import java.net.URI;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.Executors;
import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
import org.mozilla.gecko.background.testhelpers.WaitHelper;
import org.mozilla.gecko.browserid.BrowserIDKeyPair;
import org.mozilla.gecko.browserid.JSONWebTokenUtils;
import org.mozilla.gecko.browserid.MockMyIDTokenFactory;
import org.mozilla.gecko.browserid.RSACryptoImplementation;
import org.mozilla.gecko.tokenserver.TokenServerClient;
import org.mozilla.gecko.tokenserver.TokenServerClientDelegate;
import org.mozilla.gecko.tokenserver.TokenServerException;
import org.mozilla.gecko.tokenserver.TokenServerException.TokenServerInvalidCredentialsException;
import org.mozilla.gecko.tokenserver.TokenServerToken;
public class TestLiveTokenServerClientOnDevice extends AndroidSyncTestCase {
public static final String TEST_USERNAME = "test";
public static final String TEST_REMOTE_SERVER_URL = "http://auth.oldsync.dev.lcip.org";
public static final String TEST_REMOTE_AUDIENCE = "http://auth.oldsync.dev.lcip.org"; // Audience accepted by the token server.
public static final String TEST_REMOTE_URL = TEST_REMOTE_SERVER_URL + "/1.0/sync/1.1";
public static final String TEST_ENDPOINT = "http://db1.oldsync.dev.lcip.org/1.1/";
protected final MockMyIDTokenFactory mockMyIDTokenFactory;
protected final BrowserIDKeyPair keyPair;
protected TokenServerClient client;
public TestLiveTokenServerClientOnDevice() throws NoSuchAlgorithmException {
this.mockMyIDTokenFactory = new MockMyIDTokenFactory();
this.keyPair = RSACryptoImplementation.generateKeypair(1024);
}
public void setUp() throws Exception {
client = new TokenServerClient(new URI(TEST_REMOTE_URL), Executors.newSingleThreadExecutor());
}
public void testRemoteSuccess() throws Exception {
final String assertion = mockMyIDTokenFactory.createMockMyIDAssertion(keyPair, TEST_USERNAME, TEST_REMOTE_AUDIENCE);
JSONWebTokenUtils.dumpAssertion(assertion);
WaitHelper.getTestWaiter().performWait(new Runnable() {
@Override
public void run() {
client.getTokenFromBrowserIDAssertion(assertion, true, new TokenServerClientDelegate() {
@Override
public void handleSuccess(TokenServerToken token) {
try {
assertNotNull(token.id);
assertNotNull(token.key);
assertNotNull(Long.valueOf(token.uid));
assertEquals(TEST_ENDPOINT + token.uid, token.endpoint);
WaitHelper.getTestWaiter().performNotify();
} catch (Throwable t) {
WaitHelper.getTestWaiter().performNotify(t);
}
}
@Override
public void handleFailure(TokenServerException e) {
WaitHelper.getTestWaiter().performNotify(e);
}
@Override
public void handleError(Exception e) {
WaitHelper.getTestWaiter().performNotify(e);
}
});
}
});
}
public void testRemoteFailure() throws Exception {
final String badAssertion = mockMyIDTokenFactory.createMockMyIDAssertion(keyPair, TEST_USERNAME, TEST_REMOTE_AUDIENCE,
0, 1,
System.currentTimeMillis(), JSONWebTokenUtils.DEFAULT_ASSERTION_DURATION_IN_MILLISECONDS);
WaitHelper.getTestWaiter().performWait(new Runnable() {
@Override
public void run() {
client.getTokenFromBrowserIDAssertion(badAssertion, false, new TokenServerClientDelegate() {
@Override
public void handleSuccess(TokenServerToken token) {
WaitHelper.getTestWaiter().performNotify(new RuntimeException("Expected failure due to expired assertion."));
}
@Override
public void handleFailure(TokenServerException e) {
try {
assertEquals(TokenServerInvalidCredentialsException.class, e.getClass());
WaitHelper.getTestWaiter().performNotify();
} catch (Throwable t) {
WaitHelper.getTestWaiter().performNotify(t);
}
}
@Override
public void handleError(Exception e) {
WaitHelper.getTestWaiter().performNotify(e);
}
});
}
});
}
}

View File

@ -50,7 +50,10 @@ ArrayBufferInputStream::SetData(JS::Handle<JS::Value> aBuffer,
uint32_t buflen = JS_GetArrayBufferByteLength(arrayBuffer);
mOffset = std::min(buflen, aByteOffset);
mBufferLength = std::min(buflen - mOffset, aLength);
mBuffer = JS_GetArrayBufferData(arrayBuffer);
mBuffer = JS_GetStableArrayBufferData(aCx, arrayBuffer);
if (!mBuffer) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}

Some files were not shown because too many files have changed in this diff Show More