mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team.
This commit is contained in:
commit
86e4a34c44
1
aclocal.m4
vendored
1
aclocal.m4
vendored
@ -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
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "3d73a644a8ecb4a4c426584956d0c7f6b05e4cdb",
|
||||
"revision": "4f00231c5cc538139e63bee1a7ed8456f6cefed7",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
24
build/autoconf/hotfixes.m4
Normal file
24
build/autoconf/hotfixes.m4
Normal 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
|
@ -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')
|
||||
|
@ -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;
|
||||
}
|
||||
%}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
33
content/canvas/src/WebGLExtensionFragDepth.cpp
Normal file
33
content/canvas/src/WebGLExtensionFragDepth.cpp
Normal 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)
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLExtensionDepthTexture.cpp',
|
||||
'WebGLExtensionDrawBuffers.cpp',
|
||||
'WebGLExtensionElementIndexUint.cpp',
|
||||
'WebGLExtensionFragDepth.cpp',
|
||||
'WebGLExtensionInstancedArrays.cpp',
|
||||
'WebGLExtensionLoseContext.cpp',
|
||||
'WebGLExtensionSRGB.cpp',
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1380,6 +1380,11 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionFragDepth': {
|
||||
'nativeType': 'mozilla::WebGLExtensionFragDepth',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionLoseContext': {
|
||||
'nativeType': 'mozilla::WebGLExtensionLoseContext',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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>*
|
||||
|
@ -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,
|
||||
|
@ -822,6 +822,11 @@ interface WebGLExtensionElementIndexUint
|
||||
{
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionFragDepth
|
||||
{
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionLoseContext {
|
||||
void loseContext();
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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, ¤tPackAlignment);
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
1
js/src/aclocal.m4
vendored
@ -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
|
||||
|
@ -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)) {
|
||||
|
15
js/src/jit-test/tests/parallel/bug970427.js
Normal file
15
js/src/jit-test/tests/parallel/bug970427.js
Normal 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; }
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
|
@ -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()) {
|
||||
|
@ -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++;
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -491,7 +491,7 @@ Scriptability::Unblock()
|
||||
void
|
||||
Scriptability::SetDocShellAllowsScript(bool aAllowed)
|
||||
{
|
||||
mDocShellAllowsScript = aAllowed;
|
||||
mDocShellAllowsScript = aAllowed || mImmuneToScriptPolicy;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -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?
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
8
media/libpng/crashtests/945912-1.html
Normal file
8
media/libpng/crashtests/945912-1.html
Normal 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>
|
@ -1 +1,2 @@
|
||||
load 374810-1.html
|
||||
load 945912-1.html
|
||||
|
112
memory/mozalloc/VolatileBuffer.h
Normal file
112
memory/mozalloc/VolatileBuffer.h
Normal 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 */
|
137
memory/mozalloc/VolatileBufferAshmem.cpp
Normal file
137
memory/mozalloc/VolatileBufferAshmem.cpp
Normal 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
|
80
memory/mozalloc/VolatileBufferFallback.cpp
Normal file
80
memory/mozalloc/VolatileBufferFallback.cpp
Normal 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
|
122
memory/mozalloc/VolatileBufferOSX.cpp
Normal file
122
memory/mozalloc/VolatileBufferOSX.cpp
Normal 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
|
173
memory/mozalloc/VolatileBufferWindows.cpp
Normal file
173
memory/mozalloc/VolatileBufferWindows.cpp
Normal 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
|
@ -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']
|
||||
|
144
memory/mozalloc/tests/TestVolatileBuffer.cpp
Normal file
144
memory/mozalloc/tests/TestVolatileBuffer.cpp
Normal 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;
|
||||
}
|
9
memory/mozalloc/tests/moz.build
Normal file
9
memory/mozalloc/tests/moz.build
Normal 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',
|
||||
]
|
@ -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 =
|
||||
|
@ -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? */
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user