mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-12 00:50:40 +00:00
Merge mozilla-central and inbound
This commit is contained in:
commit
76c3da1c9d
@ -2,11 +2,13 @@
|
||||
# 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/.
|
||||
|
||||
# Disabled for too many intermittent failures (bug 895390)
|
||||
# browser_privatebrowsing_cache.js \
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
head.js \
|
||||
browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js \
|
||||
browser_privatebrowsing_aboutSessionRestore.js \
|
||||
browser_privatebrowsing_cache.js \
|
||||
browser_privatebrowsing_certexceptionsui.js \
|
||||
browser_privatebrowsing_concurrent.js \
|
||||
browser_privatebrowsing_concurrent_page.html \
|
||||
|
@ -8,10 +8,13 @@ MOCHITEST_BROWSER_FILES := \
|
||||
browser_bug400731.js \
|
||||
$(NULL)
|
||||
|
||||
# The browser chrome test for bug 415846 doesn't run on Mac because of its
|
||||
# bizarre special-and-unique snowflake of a help menu.
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_bug415846.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
# browser_bug415846.js disabled for too many intermittent failures (bug 546169)
|
||||
#
|
||||
# # The browser chrome test for bug 415846 doesn't run on Mac because of its
|
||||
# # bizarre special-and-unique snowflake of a help menu.
|
||||
# ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
# MOCHITEST_BROWSER_FILES += \
|
||||
# browser_bug415846.js \
|
||||
# $(NULL)
|
||||
# endif
|
||||
|
@ -1,18 +1,25 @@
|
||||
|
||||
if [ -d "/c/Program Files (x86)/Microsoft Visual Studio 10.0" ]; then
|
||||
_VSPATH="/c/Program Files (x86)/Microsoft Visual Studio 10.0"
|
||||
else
|
||||
_VSPATH="/c/tools/msvs10"
|
||||
fi
|
||||
|
||||
## SDK redist ##
|
||||
export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x86/Microsoft.VC100.CRT
|
||||
export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x86/Microsoft.VC100.CRT
|
||||
|
||||
## moz tools location for 64-bit builders ##
|
||||
export MOZ_TOOLS=C:/mozilla-build/moztools
|
||||
|
||||
## includes: win8 sdk includes, winrt headers for metro, msvc 10 std library, directx sdk for d3d9 ##
|
||||
export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl/wrappers:/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/dx10/include
|
||||
export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl/wrappers:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
|
||||
|
||||
## libs: win8 sdk x86 (32-bit) libs, msvc 10 (32-bit) std library, msvc 10 atl libs, directx sdk (32-bit) for d3d9 ##
|
||||
export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x86:/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
|
||||
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x86:/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
|
||||
export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
|
||||
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
|
||||
|
||||
## paths: win8 sdk x86 (32-bit) tools, msvc 10 (32-bit) build toolchain, moz tools ##
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x86:/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:/c/mozilla-build/moztools:${PATH}"
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x86:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:/c/mozilla-build/moztools:${PATH}"
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs2010-common
|
||||
|
||||
|
@ -1,15 +1,22 @@
|
||||
|
||||
if [ -d "/c/Program Files (x86)/Microsoft Visual Studio 10.0" ]; then
|
||||
_VSPATH="/c/Program Files (x86)/Microsoft Visual Studio 10.0"
|
||||
else
|
||||
_VSPATH="/c/tools/msvs10"
|
||||
fi
|
||||
|
||||
## SDK redist ##
|
||||
export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x64/Microsoft.VC100.CRT
|
||||
export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x64/Microsoft.VC100.CRT
|
||||
|
||||
## includes: win8 sdk includes, winrt headers for metro, msvc 10 std library, directx sdk for d3d9 ##
|
||||
export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl/wrappers:/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/dx10/include
|
||||
export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl/wrappers:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
|
||||
|
||||
## libs: win8 sdk x64 (64-bit) libs, msvc 10 (64-bit) std library, msvc 10 atl libs, directx sdk (64-bit) for d3d9 ##
|
||||
export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x64:/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
|
||||
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x64:/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
|
||||
export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
|
||||
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
|
||||
|
||||
## paths: win8 sdk x64 (64-bit) tools, msvc 10 (64-bit) build toolchain, moz tools ##
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x64:/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN/amd64:/c/tools/msvs10/VC/BIN/x86_amd64:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:${PATH}"
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x64:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/VC/BIN/x86_amd64:${_VSPATH}/VC/BIN:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:${PATH}"
|
||||
|
||||
# Use 32bit linker for PGO crash bug.
|
||||
# https://connect.microsoft.com/VisualStudio/feedback/details/686117/
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPrincipal.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
||||
class nsIURI;
|
||||
|
||||
@ -53,6 +54,7 @@ public:
|
||||
virtual ~nsNullPrincipal();
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
|
||||
};
|
||||
|
||||
#endif // nsNullPrincipal_h__
|
||||
|
@ -149,8 +149,7 @@ nsNullPrincipal::GetHashValue(uint32_t *aResult)
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::GetSecurityPolicy(void** aSecurityPolicy)
|
||||
{
|
||||
// We don't actually do security policy caching. And it's not like anyone
|
||||
// can set a security policy for us anyway.
|
||||
// We don't actually do security policy caching.
|
||||
*aSecurityPolicy = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -158,8 +157,7 @@ nsNullPrincipal::GetSecurityPolicy(void** aSecurityPolicy)
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::SetSecurityPolicy(void* aSecurityPolicy)
|
||||
{
|
||||
// We don't actually do security policy caching. And it's not like anyone
|
||||
// can set a security policy for us anyway.
|
||||
// We don't actually do security policy caching.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -172,16 +170,20 @@ nsNullPrincipal::GetURI(nsIURI** aURI)
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
|
||||
{
|
||||
// CSP on a null principal makes no sense
|
||||
*aCsp = nullptr;
|
||||
NS_IF_ADDREF(*aCsp = mCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
|
||||
{
|
||||
// CSP on a null principal makes no sense
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
// If CSP was already set, it should not be destroyed! Instead, it should
|
||||
// get set anew when a new principal is created.
|
||||
if (mCSP)
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
|
||||
mCSP = aCsp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -49,9 +49,9 @@ function ContentSecurityPolicy() {
|
||||
|
||||
this._request = "";
|
||||
this._requestOrigin = "";
|
||||
this._requestPrincipal = "";
|
||||
this._weakRequestPrincipal = null;
|
||||
this._referrer = "";
|
||||
this._docRequest = null;
|
||||
this._weakDocRequest = { get : function() { return null; } };
|
||||
CSPdebug("CSP object initialized, no policies to enforce yet");
|
||||
|
||||
this._cache = { };
|
||||
@ -249,7 +249,7 @@ ContentSecurityPolicy.prototype = {
|
||||
return;
|
||||
|
||||
// Save the docRequest for fetching a policy-uri
|
||||
this._docRequest = aChannel;
|
||||
this._weakDocRequest = Cu.getWeakReference(aChannel);
|
||||
|
||||
// save the document URI (minus <fragment>) and referrer for reporting
|
||||
let uri = aChannel.URI.cloneIgnoringRef();
|
||||
@ -260,8 +260,9 @@ ContentSecurityPolicy.prototype = {
|
||||
this._requestOrigin = uri;
|
||||
|
||||
//store a reference to the principal, that can later be used in shouldLoad
|
||||
this._requestPrincipal = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Components.interfaces.nsIScriptSecurityManager).getChannelPrincipal(aChannel);
|
||||
this._weakRequestPrincipal = Cu.getWeakReference(Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager)
|
||||
.getChannelPrincipal(aChannel));
|
||||
|
||||
if (aChannel.referrer) {
|
||||
let referrer = aChannel.referrer.cloneIgnoringRef();
|
||||
@ -310,13 +311,13 @@ ContentSecurityPolicy.prototype = {
|
||||
if (aSpecCompliant) {
|
||||
newpolicy = CSPRep.fromStringSpecCompliant(aPolicy,
|
||||
selfURI,
|
||||
this._docRequest,
|
||||
this._weakDocRequest.get(),
|
||||
this,
|
||||
aReportOnly);
|
||||
} else {
|
||||
newpolicy = CSPRep.fromString(aPolicy,
|
||||
selfURI,
|
||||
this._docRequest,
|
||||
this._weakDocRequest.get(),
|
||||
this,
|
||||
aReportOnly);
|
||||
}
|
||||
@ -434,8 +435,8 @@ ContentSecurityPolicy.prototype = {
|
||||
// we need to set an nsIChannelEventSink on the channel object
|
||||
// so we can tell it to not follow redirects when posting the reports
|
||||
chan.notificationCallbacks = new CSPReportRedirectSink(policy);
|
||||
if (this._docRequest) {
|
||||
chan.loadGroup = this._docRequest.loadGroup;
|
||||
if (this._weakDocRequest.get()) {
|
||||
chan.loadGroup = this._weakDocRequest.get().loadGroup;
|
||||
}
|
||||
|
||||
chan.QueryInterface(Ci.nsIUploadChannel)
|
||||
@ -454,7 +455,7 @@ ContentSecurityPolicy.prototype = {
|
||||
.getService(Ci.nsIContentPolicy);
|
||||
if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_CSP_REPORT,
|
||||
chan.URI, this._requestOrigin,
|
||||
null, null, null, this._requestPrincipal)
|
||||
null, null, null, this._weakRequestPrincipal.get())
|
||||
!= Ci.nsIContentPolicy.ACCEPT) {
|
||||
continue; // skip unauthorized URIs
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "mozilla/dom/FileListBinding.h"
|
||||
using namespace mozilla;
|
||||
|
@ -2681,7 +2681,8 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
||||
if (csp) {
|
||||
// Copy into principal
|
||||
nsIPrincipal* principal = GetPrincipal();
|
||||
principal->SetCsp(csp);
|
||||
rv = principal->SetCsp(csp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef PR_LOGGING
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Inserted CSP into principal %p", principal));
|
||||
|
@ -53,7 +53,6 @@
|
||||
#include "pldhash.h"
|
||||
#include "nsAttrAndChildArray.h"
|
||||
#include "nsDOMAttributeMap.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDOMXPathNSResolver.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
@ -97,6 +97,19 @@ MOCHITEST_FILES := \
|
||||
file_bug836922_npolicies.html^headers^ \
|
||||
file_bug836922_npolicies_violation.sjs \
|
||||
file_bug836922_npolicies_ro_violation.sjs \
|
||||
test_bug886164.html \
|
||||
file_bug886164.html \
|
||||
file_bug886164.html^headers^ \
|
||||
file_bug886164_2.html \
|
||||
file_bug886164_2.html^headers^ \
|
||||
file_bug886164_3.html \
|
||||
file_bug886164_3.html^headers^ \
|
||||
file_bug886164_4.html \
|
||||
file_bug886164_4.html^headers^ \
|
||||
file_bug886164_5.html \
|
||||
file_bug886164_5.html^headers^ \
|
||||
file_bug886164_6.html \
|
||||
file_bug886164_6.html^headers^ \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES := \
|
||||
|
15
content/base/test/csp/file_bug886164.html
Normal file
15
content/base/test/csp/file_bug886164.html
Normal file
@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox="allow-same-origin" -->
|
||||
<!-- Content-Security-Policy: default-src 'self' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=img_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/content/base/test/csp/file_CSP.sjs?testid=img_good&type=img/png" />
|
||||
<script src='/tests/content/base/test/csp/file_CSP.sjs?testid=scripta_bad&type=text/javascript'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
1
content/base/test/csp/file_bug886164.html^headers^
Normal file
1
content/base/test/csp/file_bug886164.html^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src 'self'
|
14
content/base/test/csp/file_bug886164_2.html
Normal file
14
content/base/test/csp/file_bug886164_2.html
Normal file
@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox -->
|
||||
<!-- Content-Security-Policy: default-src 'self' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=img2_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/content/base/test/csp/file_CSP.sjs?testid=img2a_good&type=img/png" />
|
||||
|
||||
</body>
|
||||
</html>
|
1
content/base/test/csp/file_bug886164_2.html^headers^
Normal file
1
content/base/test/csp/file_bug886164_2.html^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src 'self'
|
12
content/base/test/csp/file_bug886164_3.html
Normal file
12
content/base/test/csp/file_bug886164_3.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox -->
|
||||
<!-- Content-Security-Policy: default-src 'none' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=img3_bad&type=img/png"> </img>
|
||||
<img src="/tests/content/base/test/csp/file_CSP.sjs?testid=img3a_bad&type=img/png" />
|
||||
|
||||
</body>
|
||||
</html>
|
1
content/base/test/csp/file_bug886164_3.html^headers^
Normal file
1
content/base/test/csp/file_bug886164_3.html^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src 'none'
|
12
content/base/test/csp/file_bug886164_4.html
Normal file
12
content/base/test/csp/file_bug886164_4.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox -->
|
||||
<!-- Content-Security-Policy: default-src 'none' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=img4_bad&type=img/png"> </img>
|
||||
<img src="/tests/content/base/test/csp/file_CSP.sjs?testid=img4a_bad&type=img/png" />
|
||||
|
||||
</body>
|
||||
</html>
|
1
content/base/test/csp/file_bug886164_4.html^headers^
Normal file
1
content/base/test/csp/file_bug886164_4.html^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src 'none'
|
26
content/base/test/csp/file_bug886164_5.html
Normal file
26
content/base/test/csp/file_bug886164_5.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
}
|
||||
</script>
|
||||
<script src='file_iframe_sandbox_pass.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with only inline "allow-scripts"
|
||||
|
||||
<!-- sandbox="allow-scripts" -->
|
||||
<!-- Content-Security-Policy: default-src 'none' 'unsafe-inline'-->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="/tests/content/base/test/csp/file_CSP.sjs?testid=img5_bad&type=img/png" />
|
||||
<img src="http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=img5a_bad&type=img/png"> </img>
|
||||
<script src='/tests/content/base/test/csp/file_CSP.sjs?testid=script5_bad&type=text/javascript'></script>
|
||||
<script src='http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=script5a_bad&type=text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
1
content/base/test/csp/file_bug886164_5.html^headers^
Normal file
1
content/base/test/csp/file_bug886164_5.html^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src 'none' 'unsafe-inline';
|
35
content/base/test/csp/file_bug886164_6.html
Normal file
35
content/base/test/csp/file_bug886164_6.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
|
||||
document.getElementById('a_form').submit();
|
||||
|
||||
// trigger the javascript: url test
|
||||
sendMouseEvent({type:'click'}, 'a_link');
|
||||
}
|
||||
</script>
|
||||
<script src='file_iframe_sandbox_pass.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with "allow-scripts"
|
||||
<img src="http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=img6_bad&type=img/png"> </img>
|
||||
<script src='http://example.org/tests/content/base/test/csp/file_CSP.sjs?testid=script6_bad&type=text/javascript'></script>
|
||||
|
||||
<form method="get" action="file_iframe_sandbox_form_fail.html" id="a_form">
|
||||
First name: <input type="text" name="firstname">
|
||||
Last name: <input type="text" name="lastname">
|
||||
<input type="submit" onclick="doSubmit()" id="a_button">
|
||||
</form>
|
||||
|
||||
<a href = 'javascript:ok(true, "documents sandboxed with allow-scripts should be able to run script from javascript: URLs");' id='a_link'>click me</a>
|
||||
</body>
|
||||
</html>
|
1
content/base/test/csp/file_bug886164_6.html^headers^
Normal file
1
content/base/test/csp/file_bug886164_6.html^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src 'self' 'unsafe-inline';
|
185
content/base/test/csp/test_bug886164.html
Normal file
185
content/base/test/csp/test_bug886164.html
Normal file
@ -0,0 +1,185 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 886164 - Enforce CSP in sandboxed iframe</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<iframe style="width:200px;height:200px;" id='cspframe' sandbox="allow-same-origin"></iframe>
|
||||
<iframe style="width:200px;height:200px;" id='cspframe2' sandbox></iframe>
|
||||
<iframe style="width:200px;height:200px;" id='cspframe3' sandbox="allow-same-origin"></iframe>
|
||||
<iframe style="width:200px;height:200px;" id='cspframe4' sandbox></iframe>
|
||||
<iframe style="width:200px;height:200px;" id='cspframe5' sandbox="allow-scripts"></iframe>
|
||||
<iframe style="width:200px;height:200px;" id='cspframe6' sandbox="allow-same-origin allow-scripts"></iframe>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
|
||||
var path = "/tests/content/base/test/csp/";
|
||||
|
||||
// These are test results: -1 means it hasn't run,
|
||||
// true/false is the pass/fail result.
|
||||
window.tests = {
|
||||
// sandbox allow-same-origin; 'self'
|
||||
img_good: -1, // same origin
|
||||
img_bad: -1, //example.com
|
||||
|
||||
// sandbox; 'self'
|
||||
img2_bad: -1, //example.com
|
||||
img2a_good: -1, // same origin & is image
|
||||
|
||||
// sandbox allow-same-origin; 'none'
|
||||
img3_bad: -1,
|
||||
img3a_bad: -1,
|
||||
|
||||
// sandbox; 'none'
|
||||
img4_bad: -1,
|
||||
img4a_bad: -1,
|
||||
|
||||
// sandbox allow-scripts; 'none' 'unsafe-inline'
|
||||
img5_bad: -1,
|
||||
img5a_bad: -1,
|
||||
script5_bad: -1,
|
||||
script5a_bad: -1,
|
||||
|
||||
// sandbox allow-same-origin allow-scripts; 'self' 'unsafe-inline'
|
||||
img6_bad: -1,
|
||||
script6_bad: -1,
|
||||
};
|
||||
|
||||
// a postMessage handler that is used by sandboxed iframes without
|
||||
// 'allow-same-origin' to communicate pass/fail back to this main page.
|
||||
// it expects to be called with an object like {ok: true/false, desc:
|
||||
// <description of the test> which it then forwards to ok()
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
|
||||
function receiveMessage(event)
|
||||
{
|
||||
ok_wrapper(event.data.ok, event.data.desc);
|
||||
}
|
||||
|
||||
var cspTestsDone = false;
|
||||
var iframeSandboxTestsDone = false;
|
||||
|
||||
// iframe related
|
||||
var completedTests = 0;
|
||||
var passedTests = 0;
|
||||
|
||||
function ok_wrapper(result, desc) {
|
||||
ok(result, desc);
|
||||
|
||||
completedTests++;
|
||||
|
||||
if (result) {
|
||||
passedTests++;
|
||||
}
|
||||
|
||||
if (completedTests === 5) {
|
||||
iframeSandboxTestsDone = true;
|
||||
if (cspTestsDone) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//csp related
|
||||
|
||||
// This is used to watch the blocked data bounce off CSP and allowed data
|
||||
// get sent out to the wire.
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "http-on-modify-request", false);
|
||||
}
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
// subject should be an nsURI, and should be either allowed or blocked.
|
||||
if (!SpecialPowers.can_QI(subject))
|
||||
return;
|
||||
|
||||
var testpat = new RegExp("testid=([a-z0-9_]+)");
|
||||
|
||||
//_good things better be allowed!
|
||||
//_bad things better be stopped!
|
||||
|
||||
if (topic === "http-on-modify-request") {
|
||||
//these things were allowed by CSP
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
|
||||
if (!testpat.test(asciiSpec)) return;
|
||||
var testid = testpat.exec(asciiSpec)[1];
|
||||
|
||||
window.testResult(testid,
|
||||
/_good/.test(testid),
|
||||
asciiSpec + " allowed by csp");
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
//these were blocked... record that they were blocked
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
|
||||
if (!testpat.test(asciiSpec)) return;
|
||||
var testid = testpat.exec(asciiSpec)[1];
|
||||
window.testResult(testid,
|
||||
/_bad/.test(testid),
|
||||
asciiSpec + " blocked by \"" + data + "\"");
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
window.testResult = function(testname, result, msg) {
|
||||
//test already complete.... forget it... remember the first result.
|
||||
if (window.tests[testname] != -1)
|
||||
return;
|
||||
|
||||
window.tests[testname] = result;
|
||||
is(result, true, testname + ' test: ' + msg);
|
||||
|
||||
// if any test is incomplete, keep waiting
|
||||
for (var v in window.tests)
|
||||
if(tests[v] == -1) {
|
||||
console.log(v + " is not complete");
|
||||
return;
|
||||
}
|
||||
|
||||
// ... otherwise, finish
|
||||
window.examiner.remove();
|
||||
cspTestsDone = true;
|
||||
if (iframeSandboxTestsDone) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set':[["security.csp.speccompliant", true]]},
|
||||
function() {
|
||||
// save this for last so that our listeners are registered.
|
||||
// ... this loads the testbed of good and bad requests.
|
||||
document.getElementById('cspframe').src = 'file_bug886164.html';
|
||||
document.getElementById('cspframe2').src = 'file_bug886164_2.html';
|
||||
document.getElementById('cspframe3').src = 'file_bug886164_3.html';
|
||||
document.getElementById('cspframe4').src = 'file_bug886164_4.html';
|
||||
document.getElementById('cspframe5').src = 'file_bug886164_5.html';
|
||||
document.getElementById('cspframe6').src = 'file_bug886164_6.html';
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -13,7 +13,7 @@
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsEventListenerManager.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "MediaDecoderOwner.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsILoadGroup.h"
|
||||
@ -45,6 +44,7 @@ class MediaDecoder;
|
||||
|
||||
class nsITimer;
|
||||
class nsRange;
|
||||
class nsIRunnable;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -15,6 +15,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
struct ThreeDPoint;
|
||||
class AudioParamTimeline;
|
||||
class DelayNodeEngine;
|
||||
}
|
||||
|
||||
class AudioNodeStream;
|
||||
@ -206,6 +207,8 @@ public:
|
||||
MOZ_COUNT_DTOR(AudioNodeEngine);
|
||||
}
|
||||
|
||||
virtual dom::DelayNodeEngine* AsDelayNodeEngine() { return nullptr; }
|
||||
|
||||
virtual void SetStreamTimeParameter(uint32_t aIndex, TrackTicks aParam)
|
||||
{
|
||||
NS_ERROR("Invalid SetStreamTimeParameter index");
|
||||
|
@ -286,6 +286,20 @@ AudioNodeStream::ObtainInputBlock(AudioChunk& aTmpChunk, uint32_t aPortIndex)
|
||||
a->IsAudioParamStream()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is possible for mLastChunks to be empty here, because `a` might be a
|
||||
// AudioNodeStream that has not been scheduled yet, because it is further
|
||||
// down the graph _but_ as a connection to this node. Because we enforce the
|
||||
// presence of at least one DelayNode, with at least one block of delay, and
|
||||
// because the output of a DelayNode when it has been fed less that
|
||||
// `delayTime` amount of audio is silence, we can simply continue here,
|
||||
// because this input would not influence the output of this node. Next
|
||||
// iteration, a->mLastChunks.IsEmpty() will be false, and everthing will
|
||||
// work as usual.
|
||||
if (a->mLastChunks.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AudioChunk* chunk = &a->mLastChunks[mInputs[i]->OutputNumber()];
|
||||
MOZ_ASSERT(chunk);
|
||||
if (chunk->IsNull() || chunk->mChannelData.IsEmpty()) {
|
||||
@ -412,8 +426,7 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo)
|
||||
uint16_t outputCount = std::max(uint16_t(1), mEngine->OutputCount());
|
||||
mLastChunks.SetLength(outputCount);
|
||||
|
||||
if (mInCycle) {
|
||||
// XXX DelayNode not supported yet so just produce silence
|
||||
if (mMuted) {
|
||||
for (uint16_t i = 0; i < outputCount; ++i) {
|
||||
mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
struct ThreeDPoint;
|
||||
class AudioParamTimeline;
|
||||
class DelayNodeEngine;
|
||||
}
|
||||
|
||||
class ThreadSharedFloatArrayBufferList;
|
||||
@ -54,7 +55,8 @@ public:
|
||||
mKind(aKind),
|
||||
mNumberOfInputChannels(2),
|
||||
mMarkAsFinishedAfterThisBlock(false),
|
||||
mAudioParamStream(false)
|
||||
mAudioParamStream(false),
|
||||
mMuted(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mChannelCountMode = dom::ChannelCountMode::Max;
|
||||
@ -103,6 +105,14 @@ public:
|
||||
{
|
||||
return mAudioParamStream;
|
||||
}
|
||||
void Mute() {
|
||||
mMuted = true;
|
||||
}
|
||||
|
||||
void Unmute() {
|
||||
mMuted = false;
|
||||
}
|
||||
|
||||
const OutputChunks& LastChunks() const
|
||||
{
|
||||
return mLastChunks;
|
||||
@ -153,6 +163,8 @@ protected:
|
||||
bool mMarkAsFinishedAfterThisBlock;
|
||||
// Whether the stream is an AudioParamHelper stream.
|
||||
bool mAudioParamStream;
|
||||
// Whether the stream is muted. Access only on the MediaStreamGraph thread.
|
||||
bool mMuted;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -472,12 +472,39 @@ MediaStreamGraphImpl::UpdateStreamOrderForStream(mozilla::LinkedList<MediaStream
|
||||
NS_ASSERTION(!stream->mHasBeenOrdered, "stream should not have already been ordered");
|
||||
if (stream->mIsOnOrderingStack) {
|
||||
MediaStream* iter = aStack->getLast();
|
||||
AudioNodeStream* ns = stream->AsAudioNodeStream();
|
||||
bool delayNodePresent = ns ? ns->Engine()->AsDelayNodeEngine() != nullptr : false;
|
||||
bool cycleFound = false;
|
||||
if (iter) {
|
||||
do {
|
||||
cycleFound = true;
|
||||
iter->AsProcessedStream()->mInCycle = true;
|
||||
AudioNodeStream* ns = iter->AsAudioNodeStream();
|
||||
if (ns && ns->Engine()->AsDelayNodeEngine()) {
|
||||
delayNodePresent = true;
|
||||
}
|
||||
iter = iter->getPrevious();
|
||||
} while (iter && iter != stream);
|
||||
}
|
||||
if (cycleFound && !delayNodePresent) {
|
||||
// If we have detected a cycle, the previous loop should exit with stream
|
||||
// == iter, or the node is connected to itself. Go back in the cycle and
|
||||
// mute all nodes we find, or just mute the node itself.
|
||||
if (!iter) {
|
||||
// The node is connected to itself.
|
||||
iter = aStack->getLast();
|
||||
iter->AsAudioNodeStream()->Mute();
|
||||
} else {
|
||||
MOZ_ASSERT(iter);
|
||||
do {
|
||||
// There can't be non-AudioNodeStream here, MediaStreamAudio{Source,
|
||||
// Destination}Node are connected to regular MediaStreams, but they can't be
|
||||
// in a cycle (there is no content API to do so).
|
||||
MOZ_ASSERT(iter->AsAudioNodeStream());
|
||||
iter->AsAudioNodeStream()->Mute();
|
||||
} while((iter = iter->getNext()));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
ProcessedMediaStream* ps = stream->AsProcessedStream();
|
||||
@ -513,6 +540,10 @@ MediaStreamGraphImpl::UpdateStreamOrder()
|
||||
ProcessedMediaStream* ps = stream->AsProcessedStream();
|
||||
if (ps) {
|
||||
ps->mInCycle = false;
|
||||
AudioNodeStream* ns = ps->AsAudioNodeStream();
|
||||
if (ns) {
|
||||
ns->Unmute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2293,6 +2324,7 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(bool aRealtime)
|
||||
, mPostedRunInStableState(false)
|
||||
, mRealtime(aRealtime)
|
||||
, mNonRealtimeProcessing(false)
|
||||
, mStreamOrderDirty(false)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaStreamGraphLog) {
|
||||
@ -2446,4 +2478,11 @@ MediaStreamGraph::StartNonRealtimeProcessing(uint32_t aTicksToProcess)
|
||||
graph->EnsureRunInStableState();
|
||||
}
|
||||
|
||||
void
|
||||
ProcessedMediaStream::AddInput(MediaInputPort* aPort)
|
||||
{
|
||||
mInputs.AppendElement(aPort);
|
||||
GraphImpl()->SetStreamOrderDirty();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,9 @@
|
||||
#include "TimeVarying.h"
|
||||
#include "VideoFrameContainer.h"
|
||||
#include "VideoSegment.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
||||
class nsIRunnable;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -917,10 +919,7 @@ public:
|
||||
friend class MediaStreamGraphImpl;
|
||||
|
||||
// Do not call these from outside MediaStreamGraph.cpp!
|
||||
virtual void AddInput(MediaInputPort* aPort)
|
||||
{
|
||||
mInputs.AppendElement(aPort);
|
||||
}
|
||||
virtual void AddInput(MediaInputPort* aPort);
|
||||
virtual void RemoveInput(MediaInputPort* aPort)
|
||||
{
|
||||
mInputs.RemoveElement(aPort);
|
||||
@ -946,6 +945,9 @@ public:
|
||||
*/
|
||||
virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) {};
|
||||
|
||||
bool InCycle() const { return mInCycle; }
|
||||
|
||||
|
||||
protected:
|
||||
// This state is all accessed only on the media graph thread.
|
||||
|
||||
|
@ -365,6 +365,13 @@ public:
|
||||
* Remove aPort from the graph and release it.
|
||||
*/
|
||||
void DestroyPort(MediaInputPort* aPort);
|
||||
/**
|
||||
* Mark the media stream order as dirty.
|
||||
*/
|
||||
void SetStreamOrderDirty()
|
||||
{
|
||||
mStreamOrderDirty = true;
|
||||
}
|
||||
|
||||
// Data members
|
||||
|
||||
@ -554,6 +561,11 @@ public:
|
||||
* value is only accessed on the main thread.
|
||||
*/
|
||||
bool mNonRealtimeProcessing;
|
||||
/**
|
||||
* True when a change has happened which requires us to recompute the stream
|
||||
* blocking order.
|
||||
*/
|
||||
bool mStreamOrderDirty;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "DASHReader.h"
|
||||
|
||||
|
@ -25,6 +25,10 @@
|
||||
# make the test first check canPlayType for the type, and if it's not
|
||||
# supported, just do ok(true, "Type not supported") and stop the test.
|
||||
|
||||
|
||||
# Disabled for too many intermittent failures (bug 897108)
|
||||
# test_playback_rate_playpause.html \
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
allowed.sjs \
|
||||
can_play_type_ogg.js \
|
||||
@ -141,7 +145,6 @@ MOCHITEST_FILES = \
|
||||
test_VideoPlaybackQuality.html \
|
||||
test_VideoPlaybackQuality_disabled.html \
|
||||
test_webvtt_disabled.html \
|
||||
test_playback_rate_playpause.html \
|
||||
test_bug895305.html \
|
||||
$(NULL)
|
||||
|
||||
|
@ -130,6 +130,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual const DelayNode* AsDelayNode() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioContext* GetParentObject() const
|
||||
{
|
||||
return mContext;
|
||||
|
@ -44,6 +44,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual DelayNodeEngine* AsDelayNodeEngine()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
@ -123,18 +128,28 @@ public:
|
||||
float* const* outputChannels = reinterpret_cast<float* const*>
|
||||
(const_cast<void* const*>(aOutput->mChannelData.Elements()));
|
||||
|
||||
|
||||
bool inCycle = aStream->AsProcessedStream()->InCycle();
|
||||
double sampleRate = aStream->SampleRate();
|
||||
if (mDelay.HasSimpleValue()) {
|
||||
double delayFrames = mDelay.GetValue() * sampleRate;
|
||||
mProcessor.Process(delayFrames, inputChannels, outputChannels,
|
||||
// If this DelayNode is in a cycle, make sure the delay value is at least
|
||||
// one block.
|
||||
float delayFrames = mDelay.GetValue() * sampleRate;
|
||||
float delayFramesClamped = inCycle ? std::max(static_cast<float>(WEBAUDIO_BLOCK_SIZE), delayFrames) :
|
||||
delayFrames;
|
||||
mProcessor.Process(delayFramesClamped, inputChannels, outputChannels,
|
||||
numChannels, WEBAUDIO_BLOCK_SIZE);
|
||||
} else {
|
||||
// Compute the delay values for the duration of the input AudioChunk
|
||||
// If this DelayNode is in a cycle, make sure the delay value is at least
|
||||
// one block.
|
||||
double computedDelay[WEBAUDIO_BLOCK_SIZE];
|
||||
TrackTicks tick = aStream->GetCurrentPosition();
|
||||
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
|
||||
computedDelay[counter] =
|
||||
mDelay.GetValueAtTime(tick, counter) * sampleRate;
|
||||
float delayAtTick = mDelay.GetValueAtTime(tick, counter) * sampleRate;
|
||||
float delayAtTickClamped = inCycle ? std::max(static_cast<float>(WEBAUDIO_BLOCK_SIZE), delayAtTick) :
|
||||
delayAtTick;
|
||||
computedDelay[counter] = delayAtTickClamped;
|
||||
}
|
||||
mProcessor.Process(computedDelay, inputChannels, outputChannels,
|
||||
numChannels, WEBAUDIO_BLOCK_SIZE);
|
||||
|
@ -32,6 +32,11 @@ public:
|
||||
return mDelay;
|
||||
}
|
||||
|
||||
virtual const DelayNode* AsDelayNode() const MOZ_OVERRIDE
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void NotifyInputConnected() MOZ_OVERRIDE
|
||||
{
|
||||
mMediaStreamGraphUpdateIndexAtLastInputConnection =
|
||||
|
@ -57,6 +57,7 @@ MOCHITEST_FILES := \
|
||||
test_delayNodeAtMax.html \
|
||||
test_delayNodeSmallMaxDelay.html \
|
||||
test_delayNodeWithGain.html \
|
||||
test_delayNodeCycles.html \
|
||||
test_dynamicsCompressorNode.html \
|
||||
test_gainNode.html \
|
||||
test_gainNodeInLoop.html \
|
||||
|
170
content/media/webaudio/test/test_delayNodeCycles.html
Normal file
170
content/media/webaudio/test/test_delayNodeCycles.html
Normal file
@ -0,0 +1,170 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test the support of cycles.</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script src="webaudio.js" type="text/javascript"></script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
function getSineBuffer(ctx) {
|
||||
var buffer = ctx.createBuffer(1, 2048, ctx.sampleRate);
|
||||
var b = buffer.getChannelData(0);
|
||||
for (var i = 0; i < 2048; i++) {
|
||||
b[i] = Math.sin(440 * 2 * Math.PI * i / ctx.sampleRate);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createAndPlayWithCycleAndDelayNode(ctx) {
|
||||
var source = ctx.createBufferSource();
|
||||
source.loop = true;
|
||||
source.buffer = getSineBuffer(ctx);
|
||||
|
||||
var gain = ctx.createGain();
|
||||
var delay = ctx.createDelay();
|
||||
delay.delayTime = 0.5;
|
||||
|
||||
source.connect(gain);
|
||||
gain.connect(delay);
|
||||
delay.connect(ctx.destination);
|
||||
// cycle
|
||||
delay.connect(gain);
|
||||
|
||||
source.start(0);
|
||||
}
|
||||
|
||||
function createAndPlayWithCycleAndDelayNodeButNullDelayTime(ctx) {
|
||||
var source = ctx.createBufferSource();
|
||||
source.loop = true;
|
||||
source.buffer = getSineBuffer(ctx);
|
||||
|
||||
var gain = ctx.createGain();
|
||||
var delay = ctx.createDelay();
|
||||
delay.delayTime = 0.0;
|
||||
|
||||
source.connect(gain);
|
||||
gain.connect(delay);
|
||||
delay.connect(ctx.destination);
|
||||
// cycle
|
||||
delay.connect(gain);
|
||||
|
||||
source.start(0);
|
||||
}
|
||||
|
||||
function createAndPlayWithCycleAndNoDelayNode(ctx) {
|
||||
var source = ctx.createBufferSource();
|
||||
source.loop = true;
|
||||
source.buffer = getSineBuffer(ctx);
|
||||
|
||||
var gain = ctx.createGain();
|
||||
var gain2 = ctx.createGain();
|
||||
|
||||
source.connect(gain);
|
||||
gain.connect(gain2);
|
||||
// cycle
|
||||
gain2.connect(gain);
|
||||
gain2.connect(ctx.destination);
|
||||
|
||||
source.start(0);
|
||||
}
|
||||
|
||||
function createAndPlayWithCycleAndNoDelayNodeInCycle(ctx) {
|
||||
var source = ctx.createBufferSource();
|
||||
source.loop = true;
|
||||
source.buffer = getSineBuffer(ctx);
|
||||
|
||||
var delay = ctx.createDelay();
|
||||
var gain = ctx.createGain();
|
||||
var gain2 = ctx.createGain();
|
||||
|
||||
// Their is a cycle, a delay, but the delay is not in the cycle.
|
||||
source.connect(delay);
|
||||
delay.connect(gain);
|
||||
gain.connect(gain2);
|
||||
// cycle
|
||||
gain2.connect(gain);
|
||||
gain2.connect(ctx.destination);
|
||||
|
||||
source.start(0);
|
||||
}
|
||||
|
||||
var remainingTests = 0;
|
||||
function finish() {
|
||||
if (--remainingTests == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function getOfflineContext(oncomplete) {
|
||||
var ctx = new OfflineAudioContext(1, 48000, 48000);
|
||||
ctx.oncomplete = oncomplete;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
function checkSilentBuffer(e) {
|
||||
var buffer = e.renderedBuffer.getChannelData(0);
|
||||
for (var i = 0; i < buffer.length; i++) {
|
||||
if (buffer[i] != 0.0) {
|
||||
ok(false, "buffer should be silent.");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
ok(true, "buffer should be silent.");
|
||||
finish();
|
||||
}
|
||||
|
||||
function checkNoisyBuffer(e) {
|
||||
var buffer = e.renderedBuffer.getChannelData(0);
|
||||
for (var i = 0; i < buffer.length; i++) {
|
||||
if (buffer[i] != 0.0) {
|
||||
ok(true, "buffer should be noisy.");
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ok(false, "buffer should be noisy.");
|
||||
finish();
|
||||
return false;
|
||||
}
|
||||
|
||||
function expectSilentOutput(f) {
|
||||
remainingTests++;
|
||||
var ctx = getOfflineContext(checkSilentBuffer);
|
||||
f(ctx);
|
||||
ctx.startRendering();
|
||||
}
|
||||
|
||||
function expectNoisyOutput(f) {
|
||||
remainingTests++;
|
||||
var ctx = getOfflineContext(checkNoisyBuffer);
|
||||
f(ctx);
|
||||
ctx.startRendering();
|
||||
}
|
||||
|
||||
// This is trying to make a graph with a cycle and no DelayNode in the graph.
|
||||
// The cycle subgraph should be muted, in this graph the output should be silent.
|
||||
expectSilentOutput(createAndPlayWithCycleAndNoDelayNode);
|
||||
// This is trying to make a graph with a cycle and a DelayNode in the graph, but
|
||||
// not part of the cycle.
|
||||
// The cycle subgraph should be muted, in this graph the output should be silent.
|
||||
expectSilentOutput(createAndPlayWithCycleAndNoDelayNodeInCycle);
|
||||
// Those are making legal graphs, with at least one DelayNode in the cycle.
|
||||
// There should be some non-silent output.
|
||||
expectNoisyOutput(createAndPlayWithCycleAndDelayNode);
|
||||
// DelayNode.delayTime will be clamped to 128/ctx.sampleRate.
|
||||
// There should be some non-silent output.
|
||||
expectNoisyOutput(createAndPlayWithCycleAndDelayNodeButNullDelayTime);
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -3,6 +3,9 @@
|
||||
# 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/.
|
||||
|
||||
# Disabled for too many intermittent failures (bug 719186)
|
||||
# test_bug413310.html \
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
test_bug123696.html \
|
||||
bug123696-subframe.html \
|
||||
@ -13,7 +16,6 @@ MOCHITEST_FILES = \
|
||||
test_bug387979.html \
|
||||
test_bug404548.html \
|
||||
bug404548-subframe.html \
|
||||
test_bug413310.html \
|
||||
bug413310-subframe.html \
|
||||
bug413310-post.sjs \
|
||||
test_bug402210.html \
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsThreadUtils.h" // Hacky work around for some bindings needing NS_IsMainThread.
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "qsObjectHelper.h"
|
||||
#include "xpcpublic.h"
|
||||
|
@ -19,7 +19,6 @@
|
||||
#define NAN std::numeric_limits<double>::quiet_NaN()
|
||||
#endif
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMCameraManager.h"
|
||||
#include "prlog.h"
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "FileRequest.h"
|
||||
#include "FileService.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
USING_FILE_NAMESPACE
|
||||
|
||||
@ -209,3 +210,17 @@ FileHelper::Finish()
|
||||
mRequest), "Subclass didn't call FileHelper::ReleaseObjects!");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::OnStreamClose()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
Finish();
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::OnStreamDestroy()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
Finish();
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "FileCommon.h"
|
||||
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsIFileStorage;
|
||||
|
||||
@ -58,18 +57,10 @@ public:
|
||||
OnStreamProgress(uint64_t aProgress, uint64_t aProgressMax);
|
||||
|
||||
void
|
||||
OnStreamClose()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
Finish();
|
||||
}
|
||||
OnStreamClose();
|
||||
|
||||
void
|
||||
OnStreamDestroy()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
Finish();
|
||||
}
|
||||
OnStreamDestroy();
|
||||
|
||||
static LockedFile*
|
||||
GetCurrentLockedFile();
|
||||
|
@ -1,8 +1,10 @@
|
||||
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
|
||||
|
||||
# Disabled due to bug 859075
|
||||
# test_window-named-properties.html.json \
|
||||
|
||||
MOCHITEST_FILES := \
|
||||
test_window-indexed-properties-strict.html.json \
|
||||
test_window-named-properties.html.json \
|
||||
test_window-properties.html.json \
|
||||
test_window-prototype-chain.html.json \
|
||||
$(NULL)
|
||||
|
@ -1,9 +1,11 @@
|
||||
# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
|
||||
|
||||
# Disabled due to bug 859075
|
||||
# test_window-named-properties.html \
|
||||
|
||||
MOCHITEST_FILES := \
|
||||
test_window-indexed-properties.html \
|
||||
test_window-indexed-properties-strict.html \
|
||||
test_window-named-properties.html \
|
||||
test_window-properties.html \
|
||||
test_window-prototype-chain.html \
|
||||
$(NULL)
|
||||
|
@ -5,7 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FileInfo.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "FileManager.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
|
||||
|
@ -191,10 +191,8 @@ IDBFactory::Create(JSContext* aCx,
|
||||
nsCString origin;
|
||||
StoragePrivilege privilege;
|
||||
PersistenceType defaultPersistenceType;
|
||||
nsresult rv =
|
||||
QuotaManager::GetInfoFromWindow(nullptr, &group, &origin, &privilege,
|
||||
&defaultPersistenceType);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
QuotaManager::GetInfoForChrome(&group, &origin, &privilege,
|
||||
&defaultPersistenceType);
|
||||
|
||||
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
||||
factory->mGroup = group;
|
||||
@ -231,6 +229,15 @@ IDBFactory::Create(ContentParent* aContentParent,
|
||||
|
||||
NS_ASSERTION(!nsContentUtils::GetCurrentJSContext(), "Should be called from C++");
|
||||
|
||||
// We need to get this information before we push a null principal to avoid
|
||||
// IsCallerChrome() assertion in quota manager.
|
||||
nsCString group;
|
||||
nsCString origin;
|
||||
StoragePrivilege privilege;
|
||||
PersistenceType defaultPersistenceType;
|
||||
QuotaManager::GetInfoForChrome(&group, &origin, &privilege,
|
||||
&defaultPersistenceType);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1");
|
||||
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
|
||||
@ -253,9 +260,13 @@ IDBFactory::Create(ContentParent* aContentParent,
|
||||
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
rv = Create(cx, global, aContentParent, getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
||||
factory->mGroup = group;
|
||||
factory->mASCIIOrigin = origin;
|
||||
factory->mPrivilege = privilege;
|
||||
factory->mDefaultPersistenceType = defaultPersistenceType;
|
||||
factory->mOwningObject = global;
|
||||
factory->mContentParent = aContentParent;
|
||||
|
||||
mozilla::HoldJSObjects(factory.get());
|
||||
factory->mRootedOwningObject = true;
|
||||
@ -609,12 +620,7 @@ IDBFactory::OpenInternal(const nsAString& aName,
|
||||
rv = openHelper->WaitForOpenAllowed();
|
||||
}
|
||||
else {
|
||||
StoragePrivilege openerPrivilege;
|
||||
rv = QuotaManager::GetInfoFromWindow(window, nullptr, nullptr,
|
||||
&openerPrivilege, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (openerPrivilege != Chrome &&
|
||||
if (mPrivilege != Chrome &&
|
||||
aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
|
||||
nsRefPtr<CheckPermissionsHelper> permissionHelper =
|
||||
new CheckPermissionsHelper(openHelper, window);
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "mozilla/dom/IDBIndexBinding.h"
|
||||
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
#include "mozilla/dom/indexedDB/IDBTransaction.h"
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsITimer.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsIWinTaskbar.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "WidgetUtils.h"
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prlog.h"
|
||||
#include "nsHashKeys.h"
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
|
@ -925,27 +925,6 @@ GetTemporaryStorageLimit(nsIFile* aDirectory, uint64_t aCurrentUsage,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
GetInfoForChrome(nsACString* aGroup, nsACString* aASCIIOrigin,
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType)
|
||||
{
|
||||
static const char kChromeOrigin[] = "chrome";
|
||||
|
||||
if (aGroup) {
|
||||
aGroup->AssignLiteral(kChromeOrigin);
|
||||
}
|
||||
if (aASCIIOrigin) {
|
||||
aASCIIOrigin->AssignLiteral(kChromeOrigin);
|
||||
}
|
||||
if (aPrivilege) {
|
||||
*aPrivilege = Chrome;
|
||||
}
|
||||
if (aDefaultPersistenceType) {
|
||||
*aDefaultPersistenceType = PERSISTENCE_TYPE_PERSISTENT;
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
QuotaManager::QuotaManager()
|
||||
@ -2163,13 +2142,7 @@ QuotaManager::GetInfoFromWindow(nsPIDOMWindow* aWindow,
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"We're about to touch a window off the main thread!");
|
||||
|
||||
if (!aWindow) {
|
||||
NS_ASSERTION(nsContentUtils::IsCallerChrome(),
|
||||
"Null window but not chrome!");
|
||||
GetInfoForChrome(aGroup, aASCIIOrigin, aPrivilege, aDefaultPersistenceType);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ASSERTION(aWindow, "Don't hand me a null window!");
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
|
||||
NS_ENSURE_TRUE(sop, NS_ERROR_FAILURE);
|
||||
@ -2184,6 +2157,31 @@ QuotaManager::GetInfoFromWindow(nsPIDOMWindow* aWindow,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
QuotaManager::GetInfoForChrome(nsACString* aGroup,
|
||||
nsACString* aASCIIOrigin,
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType)
|
||||
{
|
||||
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
|
||||
|
||||
static const char kChromeOrigin[] = "chrome";
|
||||
|
||||
if (aGroup) {
|
||||
aGroup->AssignLiteral(kChromeOrigin);
|
||||
}
|
||||
if (aASCIIOrigin) {
|
||||
aASCIIOrigin->AssignLiteral(kChromeOrigin);
|
||||
}
|
||||
if (aPrivilege) {
|
||||
*aPrivilege = Chrome;
|
||||
}
|
||||
if (aDefaultPersistenceType) {
|
||||
*aDefaultPersistenceType = PERSISTENCE_TYPE_PERSISTENT;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(QuotaManager, nsIQuotaManager, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "ArrayCluster.h"
|
||||
#include "Client.h"
|
||||
@ -33,6 +32,7 @@ class nsIThread;
|
||||
class nsITimer;
|
||||
class nsIURI;
|
||||
class nsPIDOMWindow;
|
||||
class nsIRunnable;
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
@ -314,6 +314,12 @@ public:
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType);
|
||||
|
||||
static void
|
||||
GetInfoForChrome(nsACString* aGroup,
|
||||
nsACString* aASCIIOrigin,
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType);
|
||||
|
||||
static void
|
||||
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
||||
const nsACString& aOrigin, nsAutoCString& _retval)
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsSize.h" // for nsIntSize
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
class nsMainThreadSurfaceRef;
|
||||
@ -817,7 +816,6 @@ public:
|
||||
|
||||
virtual already_AddRefed<gfxASurface> GetAsSurface()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
|
||||
nsRefPtr<gfxASurface> surface = mSurface.get();
|
||||
return surface.forget();
|
||||
}
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
#include "nsITimer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -239,12 +239,6 @@ IsBinaryArray(JSContext *cx, HandleObject obj)
|
||||
return IsBlockOfKind(cx, obj, TypeRepresentation::Array);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsBinaryStruct(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
return IsBlockOfKind(cx, obj, TypeRepresentation::Struct);
|
||||
}
|
||||
|
||||
const Class js::DataClass = {
|
||||
"Data",
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Data),
|
||||
|
@ -605,8 +605,6 @@ EmitNonLocalJumpFixup(ExclusiveContext *cx, BytecodeEmitter *bce, StmtInfoBCE *t
|
||||
#undef FLUSH_POPS
|
||||
}
|
||||
|
||||
static const jsatomid INVALID_ATOMID = -1;
|
||||
|
||||
static ptrdiff_t
|
||||
EmitGoto(ExclusiveContext *cx, BytecodeEmitter *bce, StmtInfoBCE *toStmt, ptrdiff_t *lastp,
|
||||
SrcNoteType noteType = SRC_NULL)
|
||||
|
@ -564,6 +564,9 @@ new Uint8Array(buf)[0xfffff] = 0xAA;
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf)(0),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf)(0xfffff),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf)(0x100000),0);
|
||||
var buf = new ArrayBuffer(0x104000);
|
||||
new Uint8Array(buf)[0x103fff] = 0xAA;
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x103fff]|0; } return f'), this, null, buf)(),0xAA);
|
||||
var buf = new ArrayBuffer(0x3f8000);
|
||||
new Uint8Array(buf)[0x3f7fff] = 0xAA;
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf)(0),0);
|
||||
@ -576,6 +579,9 @@ assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'functi
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf)(0x3fc000),0);
|
||||
var buf = new ArrayBuffer(0x3fe000);
|
||||
assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf);
|
||||
var buf = new ArrayBuffer(0x410000);
|
||||
new Uint8Array(buf)[0x40ffff] = 0xAA;
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x40ffff]|0; } return f'), this, null, buf)(),0xAA);
|
||||
// The rest are getting too large for regular testing.
|
||||
//var buf = new ArrayBuffer(0xfe8000);
|
||||
//assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf);
|
||||
@ -604,6 +610,9 @@ assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'funct
|
||||
//assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf)(0xff00000),0);
|
||||
//var buf = new ArrayBuffer(0xff80000);
|
||||
//assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf);
|
||||
//var buf = new ArrayBuffer(0x10400000);
|
||||
//new Uint8Array(buf)[0x103fffff] = 0xAA;
|
||||
//assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x103fffff]|0; } return f'), this, null, buf)(),0xAA);
|
||||
//var buf = new ArrayBuffer(0x3fa00000);
|
||||
//assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'), this, null, buf);
|
||||
//var buf = new ArrayBuffer(0x3fc00000); // 1020M
|
||||
|
@ -164,13 +164,6 @@ CaseBody(ParseNode *pn)
|
||||
return BinaryRight(pn);
|
||||
}
|
||||
|
||||
static inline JSAtom *
|
||||
StringAtom(ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_STRING));
|
||||
return pn->pn_atom;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsExpressionStatement(ParseNode *pn)
|
||||
{
|
||||
@ -285,19 +278,6 @@ FunctionStatementList(ParseNode *fn)
|
||||
return last;
|
||||
}
|
||||
|
||||
static inline ParseNode *
|
||||
FunctionLastReturnStatementOrNull(ParseNode *fn)
|
||||
{
|
||||
ParseNode *listIter = ListHead(FunctionStatementList(fn));
|
||||
ParseNode *lastReturn = NULL;
|
||||
while (listIter) {
|
||||
if (listIter->isKind(PNK_RETURN))
|
||||
lastReturn = listIter;
|
||||
listIter = listIter->pn_next;
|
||||
}
|
||||
return lastReturn;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsNormalObjectField(ExclusiveContext *cx, ParseNode *pn)
|
||||
{
|
||||
@ -960,7 +940,7 @@ js::RoundUpToNextValidAsmJSHeapLength(uint32_t length)
|
||||
return (length + 0x0003ffff) & ~0x0003ffff;
|
||||
if (length < 0x10000000u) // < 256M quanta 1M
|
||||
return (length + 0x000fffff) & ~0x000fffff;
|
||||
if (length < 0x10000000u) // < 1024M quanta 4M
|
||||
if (length < 0x40000000u) // < 1024M quanta 4M
|
||||
return (length + 0x003fffff) & ~0x003fffff;
|
||||
// < 4096M quanta 16M. Note zero is returned if over 0xff000000 but such
|
||||
// lengths are not currently valid.
|
||||
@ -1766,15 +1746,28 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
}
|
||||
}
|
||||
|
||||
// Global-data-section accesses
|
||||
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
|
||||
#if defined(JS_CPU_X86)
|
||||
// Global data accesses in x86 need to be patched with the absolute
|
||||
// address of the global. Globals are allocated sequentially after the
|
||||
// code section so we can just use an RelativeLink.
|
||||
for (unsigned i = 0; i < globalAccesses_.length(); i++) {
|
||||
AsmJSGlobalAccess a = globalAccesses_[i];
|
||||
AsmJSStaticLinkData::RelativeLink link;
|
||||
link.patchAtOffset = masm_.labelOffsetToPatchOffset(a.patchAt.offset());
|
||||
link.targetOffset = module_->offsetOfGlobalData() + a.globalDataOffset;
|
||||
if (!linkData->relativeLinks.append(link))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(JS_CPU_X64)
|
||||
// Global data accesses on x64 use rip-relative addressing and thus do
|
||||
// not need patching after deserialization.
|
||||
uint8_t *code = module_->codeBase();
|
||||
for (unsigned i = 0; i < globalAccesses_.length(); i++) {
|
||||
AsmJSGlobalAccess a = globalAccesses_[i];
|
||||
masm_.patchAsmJSGlobalAccess(a.offset, code, module_->globalData(), a.globalDataOffset);
|
||||
masm_.patchAsmJSGlobalAccess(a.patchAt, code, module_->globalData(), a.globalDataOffset);
|
||||
}
|
||||
#else
|
||||
JS_ASSERT(globalAccesses_.empty());
|
||||
#endif
|
||||
|
||||
*module = module_.forget();
|
||||
|
@ -224,8 +224,10 @@ DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
|
||||
// This check is sufficient without considering the size of the loaded datum because heap
|
||||
// loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
|
||||
JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
|
||||
if (heap->byteLength() < module.minHeapLength())
|
||||
return LinkFail(cx, "ArrayBuffer byteLength less than the largest source code heap length constraint.");
|
||||
if (heap->byteLength() < module.minHeapLength()) {
|
||||
return LinkFail(cx, JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the largest constant heap access offset rounded up to the next valid heap size).",
|
||||
heap->byteLength(), module.minHeapLength()));
|
||||
}
|
||||
|
||||
if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
|
||||
return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "jit/ParallelFunctions.h"
|
||||
#include "jit/ParallelSafetyAnalysis.h"
|
||||
#include "jit/PerfSpewer.h"
|
||||
#include "jit/RangeAnalysis.h"
|
||||
#include "vm/ForkJoin.h"
|
||||
|
||||
#include "jsboolinlines.h"
|
||||
|
@ -1180,19 +1180,6 @@ jit::BuildPhiReverseMapping(MIRGraph &graph)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline MBasicBlock *
|
||||
SkipContainedLoop(MBasicBlock *block, MBasicBlock *header)
|
||||
{
|
||||
while (block->loopHeader() || block->isLoopHeader()) {
|
||||
if (block->loopHeader())
|
||||
block = block->loopHeader();
|
||||
if (block == header)
|
||||
break;
|
||||
block = block->loopPredecessor();
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool
|
||||
CheckSuccessorImpliesPredecessor(MBasicBlock *A, MBasicBlock *B)
|
||||
|
@ -695,6 +695,7 @@ MarkCalleeToken(JSTracer *trc, CalleeToken token)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JS_NUNBOX32
|
||||
static inline uintptr_t
|
||||
ReadAllocation(const IonFrameIterator &frame, const LAllocation *a)
|
||||
{
|
||||
@ -710,6 +711,7 @@ ReadAllocation(const IonFrameIterator &frame, const LAllocation *a)
|
||||
uint8_t *argv = reinterpret_cast<uint8_t *>(frame.jsFrame()->argv());
|
||||
return *reinterpret_cast<uintptr_t *>(argv + index);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
MarkActualArguments(JSTracer *trc, const IonFrameIterator &frame)
|
||||
@ -725,6 +727,7 @@ MarkActualArguments(JSTracer *trc, const IonFrameIterator &frame)
|
||||
gc::MarkValueRoot(trc, &argv[i], "ion-argv");
|
||||
}
|
||||
|
||||
#ifdef JS_NUNBOX32
|
||||
static inline void
|
||||
WriteAllocation(const IonFrameIterator &frame, const LAllocation *a, uintptr_t value)
|
||||
{
|
||||
@ -742,6 +745,7 @@ WriteAllocation(const IonFrameIterator &frame, const LAllocation *a, uintptr_t v
|
||||
uint8_t *argv = reinterpret_cast<uint8_t *>(frame.jsFrame()->argv());
|
||||
*reinterpret_cast<uintptr_t *>(argv + index) = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
MarkIonJSFrame(JSTracer *trc, const IonFrameIterator &frame)
|
||||
|
@ -54,7 +54,7 @@ FilterContainsLocation(HandleScript function)
|
||||
|
||||
const char *filename = function->filename();
|
||||
const size_t line = function->lineno;
|
||||
static size_t filelen = strlen(filename);
|
||||
const size_t filelen = strlen(filename);
|
||||
const char *index = strstr(filter, filename);
|
||||
while (index) {
|
||||
if (index == filter || index[-1] == ',') {
|
||||
|
@ -7,7 +7,6 @@
|
||||
#ifndef jit_LIR_Common_h
|
||||
#define jit_LIR_Common_h
|
||||
|
||||
#include "jit/RangeAnalysis.h"
|
||||
#include "jit/shared/Assembler-shared.h"
|
||||
|
||||
// This file declares LIR instructions that are common to every platform.
|
||||
@ -15,6 +14,8 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class Range;
|
||||
|
||||
template <size_t Temps, size_t ExtraUses = 0>
|
||||
class LBinaryMath : public LInstructionHelper<1, 2 + ExtraUses, Temps>
|
||||
{
|
||||
|
@ -2663,7 +2663,7 @@ LIRGenerator::visitAssertRange(MAssertRange *ins)
|
||||
|
||||
switch (input->type()) {
|
||||
case MIRType_Int32:
|
||||
lir = new LAssertRangeI(useRegisterAtStart(input));
|
||||
lir = new LAssertRangeI(useRegisterAtStart(input));
|
||||
break;
|
||||
|
||||
case MIRType_Double:
|
||||
|
@ -1328,14 +1328,6 @@ MMod::canBePowerOfTwoDivisor() const
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline MDefinition *
|
||||
TryFold(MDefinition *original, MDefinition *replacement)
|
||||
{
|
||||
if (original->type() == replacement->type())
|
||||
return replacement;
|
||||
return original;
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
MMod::foldsTo(bool useValueNumbers)
|
||||
{
|
||||
@ -2381,24 +2373,15 @@ MNot::foldsTo(bool useValueNumbers)
|
||||
return this;
|
||||
}
|
||||
|
||||
bool
|
||||
MBoundsCheckLower::fallible()
|
||||
{
|
||||
return !range() || range()->lower() < minimum_;
|
||||
}
|
||||
|
||||
void
|
||||
MBeta::printOpcode(FILE *fp) const
|
||||
{
|
||||
PrintOpcodeName(fp, op());
|
||||
fprintf(fp, " ");
|
||||
getOperand(0)->printName(fp);
|
||||
fprintf(fp, " ");
|
||||
MDefinition::printOpcode(fp);
|
||||
|
||||
Sprinter sp(GetIonContext()->cx);
|
||||
sp.init();
|
||||
comparison_->print(sp);
|
||||
fprintf(fp, "%s", sp.string());
|
||||
fprintf(fp, " %s", sp.string());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4974,9 +4974,10 @@ class MBoundsCheckLower
|
||||
: public MUnaryInstruction
|
||||
{
|
||||
int32_t minimum_;
|
||||
bool fallible_;
|
||||
|
||||
MBoundsCheckLower(MDefinition *index)
|
||||
: MUnaryInstruction(index), minimum_(0)
|
||||
: MUnaryInstruction(index), minimum_(0), fallible_(true)
|
||||
{
|
||||
setGuard();
|
||||
setMovable();
|
||||
@ -5002,7 +5003,10 @@ class MBoundsCheckLower
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
bool fallible();
|
||||
bool fallible() const {
|
||||
return fallible_;
|
||||
}
|
||||
void collectRangeInfo();
|
||||
};
|
||||
|
||||
// Load a value from a dense array's element vector and does a hole check if the
|
||||
@ -8455,7 +8459,7 @@ class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
||||
class MAsmJSLoadGlobalVar : public MNullaryInstruction
|
||||
{
|
||||
MAsmJSLoadGlobalVar(MIRType type, unsigned globalDataOffset, bool isConstant)
|
||||
: globalDataOffset_(globalDataOffset), isConstant_(isConstant)
|
||||
: globalDataOffset_(globalDataOffset)
|
||||
{
|
||||
JS_ASSERT(type == MIRType_Int32 || type == MIRType_Double);
|
||||
setResultType(type);
|
||||
@ -8463,7 +8467,6 @@ class MAsmJSLoadGlobalVar : public MNullaryInstruction
|
||||
}
|
||||
|
||||
unsigned globalDataOffset_;
|
||||
bool isConstant_;
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSLoadGlobalVar);
|
||||
|
@ -28,18 +28,6 @@ class MBasicBlock;
|
||||
class MIRGraph;
|
||||
class MStart;
|
||||
|
||||
struct AsmJSGlobalAccess
|
||||
{
|
||||
unsigned offset;
|
||||
unsigned globalDataOffset;
|
||||
|
||||
AsmJSGlobalAccess(unsigned offset, unsigned globalDataOffset)
|
||||
: offset(offset), globalDataOffset(globalDataOffset)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef Vector<AsmJSGlobalAccess, 0, IonAllocPolicy> AsmJSGlobalAccessVector;
|
||||
|
||||
class MIRGenerator
|
||||
{
|
||||
public:
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "jit/LIR.h"
|
||||
#include "jit/MIR.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "jit/RangeAnalysis.h"
|
||||
|
||||
// perf expects its data to be in a file /tmp/perf-PID.map, but for Android
|
||||
// and B2G the map files are written to /data/local/tmp/perf-PID.map
|
||||
|
@ -269,11 +269,11 @@ Range::print(Sprinter &sp) const
|
||||
JS_ASSERT_IF(lower_infinite_, lower_ == JSVAL_INT_MIN);
|
||||
JS_ASSERT_IF(upper_infinite_, upper_ == JSVAL_INT_MAX);
|
||||
|
||||
// Real or Natural subset.
|
||||
// Floating-point or Integer subset.
|
||||
if (canHaveFractionalPart_)
|
||||
sp.printf("R");
|
||||
sp.printf("F");
|
||||
else
|
||||
sp.printf("N");
|
||||
sp.printf("I");
|
||||
|
||||
sp.printf("[");
|
||||
|
||||
@ -352,21 +352,21 @@ Range::intersect(const Range *lhs, const Range *rhs, bool *emptyRange)
|
||||
void
|
||||
Range::unionWith(const Range *other)
|
||||
{
|
||||
bool canHaveFractionalPart = canHaveFractionalPart_ | other->canHaveFractionalPart_;
|
||||
uint16_t max_exponent = Max(max_exponent_, other->max_exponent_);
|
||||
bool canHaveFractionalPart = canHaveFractionalPart_ | other->canHaveFractionalPart_;
|
||||
uint16_t max_exponent = Max(max_exponent_, other->max_exponent_);
|
||||
|
||||
if (lower_infinite_ || other->lower_infinite_)
|
||||
makeLowerInfinite();
|
||||
else
|
||||
setLowerInit(Min(lower_, other->lower_));
|
||||
if (lower_infinite_ || other->lower_infinite_)
|
||||
makeLowerInfinite();
|
||||
else
|
||||
setLowerInit(Min(lower_, other->lower_));
|
||||
|
||||
if (upper_infinite_ || other->upper_infinite_)
|
||||
makeUpperInfinite();
|
||||
else
|
||||
setUpperInit(Max(upper_, other->upper_));
|
||||
if (upper_infinite_ || other->upper_infinite_)
|
||||
makeUpperInfinite();
|
||||
else
|
||||
setUpperInit(Max(upper_, other->upper_));
|
||||
|
||||
canHaveFractionalPart_ = canHaveFractionalPart;
|
||||
max_exponent_ = max_exponent;
|
||||
canHaveFractionalPart_ = canHaveFractionalPart;
|
||||
max_exponent_ = max_exponent;
|
||||
}
|
||||
|
||||
static const int64_t RANGE_INF_MAX = int64_t(JSVAL_INT_MAX) + 1;
|
||||
@ -824,10 +824,8 @@ MConstant::computeRange()
|
||||
int exp = Range::MaxDoubleExponent;
|
||||
|
||||
// NaN is estimated as a Double which covers everything.
|
||||
if (IsNaN(d)) {
|
||||
setRange(new Range(RANGE_INF_MIN, RANGE_INF_MAX, true, exp));
|
||||
if (IsNaN(d))
|
||||
return;
|
||||
}
|
||||
|
||||
// Infinity is used to set both lower and upper to the range boundaries.
|
||||
if (IsInfinite(d)) {
|
||||
@ -1540,6 +1538,7 @@ ConvertLinearSum(MBasicBlock *block, const LinearSum &sum)
|
||||
def = MAdd::New(def, term.term);
|
||||
def->toAdd()->setInt32();
|
||||
block->insertBefore(block->lastIns(), def->toInstruction());
|
||||
def->computeRange();
|
||||
} else {
|
||||
def = term.term;
|
||||
}
|
||||
@ -1547,10 +1546,12 @@ ConvertLinearSum(MBasicBlock *block, const LinearSum &sum)
|
||||
if (!def) {
|
||||
def = MConstant::New(Int32Value(0));
|
||||
block->insertBefore(block->lastIns(), def->toInstruction());
|
||||
def->computeRange();
|
||||
}
|
||||
def = MSub::New(def, term.term);
|
||||
def->toSub()->setInt32();
|
||||
block->insertBefore(block->lastIns(), def->toInstruction());
|
||||
def->computeRange();
|
||||
} else {
|
||||
JS_ASSERT(term.scale != 0);
|
||||
MConstant *factor = MConstant::New(Int32Value(term.scale));
|
||||
@ -1558,10 +1559,12 @@ ConvertLinearSum(MBasicBlock *block, const LinearSum &sum)
|
||||
MMul *mul = MMul::New(term.term, factor);
|
||||
mul->setInt32();
|
||||
block->insertBefore(block->lastIns(), mul);
|
||||
mul->computeRange();
|
||||
if (def) {
|
||||
def = MAdd::New(def, mul);
|
||||
def->toAdd()->setInt32();
|
||||
block->insertBefore(block->lastIns(), def->toInstruction());
|
||||
def->computeRange();
|
||||
} else {
|
||||
def = mul;
|
||||
}
|
||||
@ -1571,6 +1574,7 @@ ConvertLinearSum(MBasicBlock *block, const LinearSum &sum)
|
||||
if (!def) {
|
||||
def = MConstant::New(Int32Value(0));
|
||||
block->insertBefore(block->lastIns(), def->toInstruction());
|
||||
def->computeRange();
|
||||
}
|
||||
|
||||
return def;
|
||||
@ -1623,8 +1627,6 @@ RangeAnalysis::tryHoistBoundsCheck(MBasicBlock *header, MBoundsCheck *ins)
|
||||
return false;
|
||||
if (!SafeSub(lowerConstant, lower->sum.constant(), &lowerConstant))
|
||||
return false;
|
||||
MBoundsCheckLower *lowerCheck = MBoundsCheckLower::New(lowerTerm);
|
||||
lowerCheck->setMinimum(lowerConstant);
|
||||
|
||||
// We are checking that index < boundsLength, and know that
|
||||
// index <= upperTerm + upperConstant. Thus, check that:
|
||||
@ -1634,6 +1636,10 @@ RangeAnalysis::tryHoistBoundsCheck(MBasicBlock *header, MBoundsCheck *ins)
|
||||
int32_t upperConstant = index.constant;
|
||||
if (!SafeAdd(upper->sum.constant(), upperConstant, &upperConstant))
|
||||
return false;
|
||||
|
||||
MBoundsCheckLower *lowerCheck = MBoundsCheckLower::New(lowerTerm);
|
||||
lowerCheck->setMinimum(lowerConstant);
|
||||
|
||||
MBoundsCheck *upperCheck = MBoundsCheck::New(upperTerm, ins->length());
|
||||
upperCheck->setMinimum(upperConstant);
|
||||
upperCheck->setMaximum(upperConstant);
|
||||
@ -2143,3 +2149,9 @@ MMod::collectRangeInfo()
|
||||
{
|
||||
canBeNegativeDividend_ = !lhs()->range() || lhs()->range()->lower() < 0;
|
||||
}
|
||||
|
||||
void
|
||||
MBoundsCheckLower::collectRangeInfo()
|
||||
{
|
||||
fallible_ = !index()->range() || index()->range()->lower() < minimum_;
|
||||
}
|
||||
|
@ -204,9 +204,6 @@ class Range : public TempObject {
|
||||
|
||||
void print(Sprinter &sp) const;
|
||||
bool update(const Range *other);
|
||||
bool update(const Range &other) {
|
||||
return update(&other);
|
||||
}
|
||||
|
||||
// Unlike the other operations, unionWith is an in-place
|
||||
// modification. This is to avoid a bunch of useless extra
|
||||
@ -233,67 +230,62 @@ class Range : public TempObject {
|
||||
|
||||
static bool negativeZeroMul(const Range *lhs, const Range *rhs);
|
||||
|
||||
inline void makeLowerInfinite() {
|
||||
void makeLowerInfinite() {
|
||||
lower_infinite_ = true;
|
||||
lower_ = JSVAL_INT_MIN;
|
||||
if (max_exponent_ < MaxInt32Exponent)
|
||||
max_exponent_ = MaxInt32Exponent;
|
||||
}
|
||||
inline void makeUpperInfinite() {
|
||||
void makeUpperInfinite() {
|
||||
upper_infinite_ = true;
|
||||
upper_ = JSVAL_INT_MAX;
|
||||
if (max_exponent_ < MaxInt32Exponent)
|
||||
max_exponent_ = MaxInt32Exponent;
|
||||
}
|
||||
inline void makeRangeInfinite() {
|
||||
makeLowerInfinite();
|
||||
makeUpperInfinite();
|
||||
max_exponent_ = MaxDoubleExponent;
|
||||
}
|
||||
|
||||
inline bool isLowerInfinite() const {
|
||||
bool isLowerInfinite() const {
|
||||
return lower_infinite_;
|
||||
}
|
||||
inline bool isUpperInfinite() const {
|
||||
bool isUpperInfinite() const {
|
||||
return upper_infinite_;
|
||||
}
|
||||
|
||||
inline bool isInt32() const {
|
||||
bool isInt32() const {
|
||||
return !isLowerInfinite() && !isUpperInfinite();
|
||||
}
|
||||
inline bool isBoolean() const {
|
||||
bool isBoolean() const {
|
||||
return lower() >= 0 && upper() <= 1;
|
||||
}
|
||||
|
||||
inline bool hasRoundingErrors() const {
|
||||
bool hasRoundingErrors() const {
|
||||
return canHaveFractionalPart() || exponent() >= MaxTruncatableExponent;
|
||||
}
|
||||
|
||||
inline bool isInfinite() const {
|
||||
bool isInfinite() const {
|
||||
return exponent() >= MaxDoubleExponent;
|
||||
}
|
||||
|
||||
inline bool canHaveFractionalPart() const {
|
||||
bool canHaveFractionalPart() const {
|
||||
return canHaveFractionalPart_;
|
||||
}
|
||||
|
||||
inline uint16_t exponent() const {
|
||||
uint16_t exponent() const {
|
||||
return max_exponent_;
|
||||
}
|
||||
|
||||
inline uint16_t numBits() const {
|
||||
uint16_t numBits() const {
|
||||
return max_exponent_ + 1; // 2^0 -> 1
|
||||
}
|
||||
|
||||
inline int32_t lower() const {
|
||||
int32_t lower() const {
|
||||
return lower_;
|
||||
}
|
||||
|
||||
inline int32_t upper() const {
|
||||
int32_t upper() const {
|
||||
return upper_;
|
||||
}
|
||||
|
||||
inline void setLowerInit(int64_t x) {
|
||||
void setLowerInit(int64_t x) {
|
||||
if (x > JSVAL_INT_MAX) { // c.c
|
||||
lower_ = JSVAL_INT_MAX;
|
||||
lower_infinite_ = false;
|
||||
@ -304,12 +296,12 @@ class Range : public TempObject {
|
||||
lower_infinite_ = false;
|
||||
}
|
||||
}
|
||||
inline void setLower(int64_t x) {
|
||||
void setLower(int64_t x) {
|
||||
setLowerInit(x);
|
||||
rectifyExponent();
|
||||
JS_ASSERT_IF(lower_infinite_, lower_ == JSVAL_INT_MIN);
|
||||
}
|
||||
inline void setUpperInit(int64_t x) {
|
||||
void setUpperInit(int64_t x) {
|
||||
if (x > JSVAL_INT_MAX) {
|
||||
makeUpperInfinite();
|
||||
} else if (x < JSVAL_INT_MIN) { // c.c
|
||||
@ -320,20 +312,20 @@ class Range : public TempObject {
|
||||
upper_infinite_ = false;
|
||||
}
|
||||
}
|
||||
inline void setUpper(int64_t x) {
|
||||
void setUpper(int64_t x) {
|
||||
setUpperInit(x);
|
||||
rectifyExponent();
|
||||
JS_ASSERT_IF(upper_infinite_, upper_ == JSVAL_INT_MAX);
|
||||
}
|
||||
|
||||
inline void setInt32() {
|
||||
void setInt32() {
|
||||
lower_infinite_ = false;
|
||||
upper_infinite_ = false;
|
||||
canHaveFractionalPart_ = false;
|
||||
max_exponent_ = MaxInt32Exponent;
|
||||
}
|
||||
|
||||
inline void set(int64_t l, int64_t h, bool f = false, uint16_t e = MaxInt32Exponent) {
|
||||
void set(int64_t l, int64_t h, bool f = false, uint16_t e = MaxInt32Exponent) {
|
||||
max_exponent_ = e;
|
||||
setLowerInit(l);
|
||||
setUpperInit(h);
|
||||
@ -374,7 +366,7 @@ class Range : public TempObject {
|
||||
// Note:
|
||||
// exponent of JSVAL_INT_MIN == 32
|
||||
// exponent of JSVAL_INT_MAX == 31
|
||||
inline void rectifyExponent() {
|
||||
void rectifyExponent() {
|
||||
if (!isInt32()) {
|
||||
JS_ASSERT(max_exponent_ >= MaxInt32Exponent);
|
||||
return;
|
||||
@ -394,10 +386,10 @@ class Range : public TempObject {
|
||||
return symbolicUpper_;
|
||||
}
|
||||
|
||||
inline void setSymbolicLower(SymbolicBound *bound) {
|
||||
void setSymbolicLower(SymbolicBound *bound) {
|
||||
symbolicLower_ = bound;
|
||||
}
|
||||
inline void setSymbolicUpper(SymbolicBound *bound) {
|
||||
void setSymbolicUpper(SymbolicBound *bound) {
|
||||
symbolicUpper_ = bound;
|
||||
}
|
||||
};
|
||||
|
@ -613,6 +613,18 @@ class CodeLocationLabel
|
||||
}
|
||||
};
|
||||
|
||||
struct AsmJSGlobalAccess
|
||||
{
|
||||
CodeOffsetLabel patchAt;
|
||||
unsigned globalDataOffset;
|
||||
|
||||
AsmJSGlobalAccess(CodeOffsetLabel patchAt, unsigned globalDataOffset)
|
||||
: patchAt(patchAt), globalDataOffset(globalDataOffset)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef Vector<AsmJSGlobalAccess, 0, IonAllocPolicy> AsmJSGlobalAccessVector;
|
||||
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -1174,10 +1174,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
}
|
||||
|
||||
// See CodeGeneratorX64 calls to noteAsmJSGlobalAccess.
|
||||
void patchAsmJSGlobalAccess(unsigned offset, uint8_t *code, uint8_t *globalData,
|
||||
void patchAsmJSGlobalAccess(CodeOffsetLabel patchAt, uint8_t *code, uint8_t *globalData,
|
||||
unsigned globalDataOffset)
|
||||
{
|
||||
uint8_t *nextInsn = code + offset;
|
||||
uint8_t *nextInsn = code + patchAt.offset();
|
||||
JS_ASSERT(nextInsn <= globalData);
|
||||
uint8_t *target = globalData + globalDataOffset;
|
||||
((int32_t *)nextInsn)[-1] = target - nextInsn;
|
||||
|
@ -1065,16 +1065,6 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
call(code);
|
||||
addl(Imm32(sizeof(uintptr_t) * 2), esp);
|
||||
}
|
||||
|
||||
// See CodeGeneratorX86 calls to noteAsmJSGlobalAccess.
|
||||
void patchAsmJSGlobalAccess(unsigned offset, uint8_t *code, uint8_t *globalData,
|
||||
unsigned globalDataOffset)
|
||||
{
|
||||
uint8_t *nextInsn = code + offset;
|
||||
JS_ASSERT(nextInsn <= globalData);
|
||||
uint8_t *target = globalData + globalDataOffset;
|
||||
((int32_t *)nextInsn)[-1] = uintptr_t(target);
|
||||
}
|
||||
};
|
||||
|
||||
typedef MacroAssemblerX86 MacroAssemblerSpecific;
|
||||
|
@ -15,10 +15,10 @@
|
||||
using namespace js;
|
||||
using namespace js::crash;
|
||||
|
||||
static const int stack_snapshot_max_size = 32768;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
static const int stack_snapshot_max_size = 32768;
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static bool
|
||||
|
@ -52,11 +52,6 @@ id_prototype(JSContext *cx) {
|
||||
return NameToId(cx->names().classPrototype);
|
||||
}
|
||||
|
||||
static inline jsid
|
||||
id_length(JSContext *cx) {
|
||||
return NameToId(cx->names().length);
|
||||
}
|
||||
|
||||
static inline jsid
|
||||
id___proto__(JSContext *cx) {
|
||||
return NameToId(cx->names().proto);
|
||||
@ -2737,24 +2732,6 @@ TypeObject::print()
|
||||
// Type Analysis
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline TypeObject *
|
||||
GetInitializerType(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
if (!script->compileAndGo)
|
||||
return NULL;
|
||||
|
||||
JSOp op = JSOp(*pc);
|
||||
JS_ASSERT(op == JSOP_NEWARRAY || op == JSOP_NEWOBJECT || op == JSOP_NEWINIT);
|
||||
|
||||
bool isArray = (op == JSOP_NEWARRAY || (op == JSOP_NEWINIT && GET_UINT8(pc) == JSProto_Array));
|
||||
JSProtoKey key = isArray ? JSProto_Array : JSProto_Object;
|
||||
|
||||
if (UseNewTypeForInitializer(cx, script, pc, key))
|
||||
return NULL;
|
||||
|
||||
return TypeScript::InitObject(cx, script, pc, key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Persistent constraint clearing out newScript and definite properties from
|
||||
* an object should a property on another object get a getter or setter.
|
||||
@ -3200,78 +3177,6 @@ types::UseNewTypeForClone(JSFunction *fun)
|
||||
// TypeScript
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Returns true if we don't expect to compute the correct types for some value
|
||||
* pushed by the specified bytecode.
|
||||
*/
|
||||
static inline bool
|
||||
IgnorePushed(const jsbytecode *pc, unsigned index)
|
||||
{
|
||||
switch (JSOp(*pc)) {
|
||||
/* We keep track of the scopes pushed by BINDNAME separately. */
|
||||
case JSOP_BINDNAME:
|
||||
case JSOP_BINDGNAME:
|
||||
case JSOP_BINDINTRINSIC:
|
||||
return true;
|
||||
|
||||
/* Stack not consistent in TRY_BRANCH_AFTER_COND. */
|
||||
case JSOP_IN:
|
||||
case JSOP_EQ:
|
||||
case JSOP_NE:
|
||||
case JSOP_LT:
|
||||
case JSOP_LE:
|
||||
case JSOP_GT:
|
||||
case JSOP_GE:
|
||||
return (index == 0);
|
||||
|
||||
/* Value not determining result is not pushed by OR/AND. */
|
||||
case JSOP_OR:
|
||||
case JSOP_AND:
|
||||
return (index == 0);
|
||||
|
||||
/* Holes tracked separately. */
|
||||
case JSOP_HOLE:
|
||||
return (index == 0);
|
||||
|
||||
/* Storage for 'with' and 'let' blocks not monitored. */
|
||||
case JSOP_ENTERWITH:
|
||||
case JSOP_ENTERBLOCK:
|
||||
case JSOP_ENTERLET0:
|
||||
case JSOP_ENTERLET1:
|
||||
return true;
|
||||
|
||||
/* We don't keep track of the iteration state for 'for in' or 'for each in' loops. */
|
||||
case JSOP_ITER:
|
||||
case JSOP_ITERNEXT:
|
||||
case JSOP_MOREITER:
|
||||
case JSOP_ENDITER:
|
||||
return true;
|
||||
|
||||
/* Ops which can manipulate values pushed by opcodes we don't model. */
|
||||
case JSOP_DUP:
|
||||
case JSOP_DUP2:
|
||||
case JSOP_SWAP:
|
||||
case JSOP_PICK:
|
||||
return true;
|
||||
|
||||
/* We don't keep track of state indicating whether there is a pending exception. */
|
||||
case JSOP_FINALLY:
|
||||
return true;
|
||||
|
||||
/*
|
||||
* We don't treat GETLOCAL immediately followed by a pop as a use-before-def,
|
||||
* and while the type will have been inferred correctly the method JIT
|
||||
* may not have written the local's initial undefined value to the stack,
|
||||
* leaving a stale value.
|
||||
*/
|
||||
case JSOP_GETLOCAL:
|
||||
return JSOp(pc[JSOP_GETLOCAL_LENGTH]) == JSOP_POP;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::makeTypes(JSContext *cx)
|
||||
{
|
||||
|
@ -1963,7 +1963,6 @@ JSScript::finalize(FreeOp *fop)
|
||||
}
|
||||
|
||||
static const uint32_t GSN_CACHE_THRESHOLD = 100;
|
||||
static const uint32_t GSN_CACHE_MAP_INIT_SIZE = 20;
|
||||
|
||||
void
|
||||
GSNCache::purge()
|
||||
|
@ -2718,13 +2718,6 @@ GetScriptReferent(JSObject *obj)
|
||||
return static_cast<JSScript *>(obj->getPrivate());
|
||||
}
|
||||
|
||||
static inline void
|
||||
SetScriptReferent(JSObject *obj, JSScript *script)
|
||||
{
|
||||
JS_ASSERT(obj->getClass() == &DebuggerScript_class);
|
||||
obj->setPrivateGCThing(script);
|
||||
}
|
||||
|
||||
static void
|
||||
DebuggerScript_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
|
@ -60,17 +60,6 @@ using namespace js::types;
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::PodCopy;
|
||||
|
||||
/* Some objects (e.g., With) delegate 'this' to another object. */
|
||||
static inline JSObject *
|
||||
CallThisObjectHook(JSContext *cx, HandleObject obj, Value *argv)
|
||||
{
|
||||
JSObject *thisp = JSObject::thisObject(cx, obj);
|
||||
if (!thisp)
|
||||
return NULL;
|
||||
argv[-1].setObject(*thisp);
|
||||
return thisp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: when Clang 3.2 (32-bit) inlines the two functions below in Interpret,
|
||||
* the conservative stack scanner leaks a ton of memory and this negatively
|
||||
|
@ -1302,11 +1302,6 @@ template<> inline const int TypeIDOfType<float>() { return ScalarTypeRepresentat
|
||||
template<> inline const int TypeIDOfType<double>() { return ScalarTypeRepresentation::TYPE_FLOAT64; }
|
||||
template<> inline const int TypeIDOfType<uint8_clamped>() { return ScalarTypeRepresentation::TYPE_UINT8_CLAMPED; }
|
||||
|
||||
template<typename NativeType> static inline const bool ElementTypeMayBeDouble() { return false; }
|
||||
template<> inline const bool ElementTypeMayBeDouble<uint32_t>() { return true; }
|
||||
template<> inline const bool ElementTypeMayBeDouble<float>() { return true; }
|
||||
template<> inline const bool ElementTypeMayBeDouble<double>() { return true; }
|
||||
|
||||
template<typename ElementType>
|
||||
static inline JSObject *
|
||||
NewArray(JSContext *cx, uint32_t nelements);
|
||||
@ -1334,7 +1329,6 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
||||
static const int ArrayTypeID() { return TypeIDOfType<NativeType>(); }
|
||||
static const bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
|
||||
static const bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
|
||||
static const bool ArrayElementTypeMayBeDouble() { return ElementTypeMayBeDouble<NativeType>(); }
|
||||
|
||||
static const size_t BYTES_PER_ELEMENT = sizeof(ThisType);
|
||||
|
||||
|
@ -127,7 +127,7 @@
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsIJSEngineTelemetryStats.h"
|
||||
|
||||
#include "nsIConsoleService.h"
|
||||
|
@ -6,7 +6,9 @@
|
||||
#define nsLayoutStatics_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
// This isn't really a class, it's a namespace for static methods.
|
||||
// Documents and other objects can hold a reference to the layout static
|
||||
|
@ -16,7 +16,12 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
setTimeout(focusing, 0);
|
||||
if (navigator.userAgent.indexOf("Windows NT 6.2") >= 0) {
|
||||
todo(false, "Too many intermittent failures on Windows 8 (bug 886781)");
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
setTimeout(focusing, 0);
|
||||
}
|
||||
|
||||
function focusing() {
|
||||
document.getElementById("editor").focus();
|
||||
|
@ -1490,7 +1490,7 @@ skip-if(B2G) fuzzy-if(Android&&AndroidVersion>=15,12,300) == 551463-1.html 55146
|
||||
# 553571 depends on MS Indic shaping behavior and Win7 font support;
|
||||
# not expected to be reliable on XP or non-Windows platforms
|
||||
random-if(!winWidget) random-if(/^Windows\x20NT\x205/.test(http.oscpu)) != 553571-1.html 553571-1-notref.html # expect dotted circle in test, not in ref
|
||||
fuzzy-if(!contentSameGfxBackendAsCanvas,2,91) random-if(d2d) skip-if(azureSkiaGL) == 555388-1.html 555388-1-ref.html
|
||||
fuzzy-if(!contentSameGfxBackendAsCanvas,128,91) random-if(d2d) skip-if(azureSkiaGL) == 555388-1.html 555388-1-ref.html
|
||||
== 556661-1.html 556661-1-ref.html
|
||||
skip-if(B2G) fails-if(Android) == 557087-1.html 557087-ref.html
|
||||
skip-if(B2G) fails-if(Android) == 557087-2.html 557087-ref.html
|
||||
@ -1715,8 +1715,8 @@ skip-if(B2G) == 751012-1a.html 751012-1-ref.html
|
||||
skip-if(B2G) == 751012-1b.html 751012-1-ref.html
|
||||
random-if(Android) == 753329-1.html about:blank
|
||||
== 758561-1.html 758561-1-ref.html
|
||||
fuzzy-if(true,1,19) fails-if(d2d) == 759036-1.html 759036-1-ref.html
|
||||
fuzzy-if(true,17,5860) == 759036-2.html 759036-2-ref.html
|
||||
fuzzy-if(true,1,19) fails-if(d2d) random-if(Android&&AndroidVersion<15) == 759036-1.html 759036-1-ref.html
|
||||
fuzzy-if(true,17,5860) random-if(Android&&AndroidVersion<15) == 759036-2.html 759036-2-ref.html
|
||||
== 776265-1a.html 776265-1-ref.html
|
||||
== 776265-1b.html 776265-1-ref.html
|
||||
== 776265-1c.html 776265-1-ref.html
|
||||
|
@ -213,7 +213,7 @@ class ReftestServer:
|
||||
self._process = self._automation.Process([xpcshell] + args, env = env)
|
||||
pid = self._process.pid
|
||||
if pid < 0:
|
||||
print "Error starting server."
|
||||
print "TEST-UNEXPECTED-FAIL | remotereftests.py | Error starting server."
|
||||
return 2
|
||||
self._automation.log.info("INFO | remotereftests.py | Server pid: %d", pid)
|
||||
|
||||
@ -233,7 +233,7 @@ class ReftestServer:
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
else:
|
||||
print "Timed out while waiting for server startup."
|
||||
print "TEST-UNEXPECTED-FAIL | remotereftests.py | Timed out while waiting for server startup."
|
||||
self.stop()
|
||||
return 1
|
||||
|
||||
@ -369,6 +369,9 @@ class RemoteReftest(RefTest):
|
||||
# Make sure that opening the plugins check page won't hit the network
|
||||
prefs["plugins.update.url"] = "http://127.0.0.1:8888/plugins-dummy/updateCheckURL"
|
||||
|
||||
# Disable skia-gl: see bug 907351
|
||||
prefs["gfx.canvas.azure.accelerated"] = False
|
||||
|
||||
# Set the extra prefs.
|
||||
profile.set_preferences(prefs)
|
||||
|
||||
@ -438,7 +441,7 @@ def main(args):
|
||||
else:
|
||||
dm = droid.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
|
||||
except devicemanager.DMError:
|
||||
print "Error: exception while initializing devicemanager. Most likely the device is not in a testable state."
|
||||
print "Automation Error: exception while initializing devicemanager. Most likely the device is not in a testable state."
|
||||
return 1
|
||||
|
||||
automation.setDeviceManager(dm)
|
||||
|
@ -584,7 +584,7 @@ pulse_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
*latency = (r_usec * stm->sample_spec.rate) / PR_NSEC_PER_SEC;
|
||||
*latency = r_usec * stm->sample_spec.rate / PA_USEC_PER_SEC;
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <algorithm>
|
||||
#include <mozilla/Scoped.h>
|
||||
#include <m_cpp_utils.h>
|
||||
#include <nsISupportsImpl.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -31,6 +31,10 @@
|
||||
#include "nrinterfaceprioritizer.h"
|
||||
#include "mtransport_test_utils.h"
|
||||
#include "runnable_utils.h"
|
||||
#include "stunserver.h"
|
||||
// TODO(bcampen@mozilla.com): Big fat hack since the build system doesn't give
|
||||
// us a clean way to add object files to a single executable.
|
||||
#include "stunserver.cpp"
|
||||
|
||||
#define GTEST_HAS_RTTI 0
|
||||
#include "gtest/gtest.h"
|
||||
@ -187,6 +191,7 @@ class IceTestPeer : public sigslot::has_slots<> {
|
||||
PRNetAddr addr;
|
||||
PRStatus status = PR_StringToNetAddr(kDefaultStunServerAddress.c_str(),
|
||||
&addr);
|
||||
addr.inet.port = kDefaultStunServerPort;
|
||||
ASSERT_EQ(PR_SUCCESS, status);
|
||||
fake_resolver_.SetAddr(kDefaultStunServerHostname, addr);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
|
||||
@ -586,6 +591,9 @@ class IceTestPeer : public sigslot::has_slots<> {
|
||||
class IceGatherTest : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() {
|
||||
test_utils->sts_target()->Dispatch(WrapRunnable(TestStunServer::GetInstance(),
|
||||
&TestStunServer::Reset),
|
||||
NS_DISPATCH_SYNC);
|
||||
peer_ = new IceTestPeer("P1", true, false);
|
||||
peer_->AddStream(1);
|
||||
}
|
||||
@ -595,6 +603,28 @@ class IceGatherTest : public ::testing::Test {
|
||||
|
||||
ASSERT_TRUE_WAIT(peer_->gathering_complete(), 10000);
|
||||
}
|
||||
|
||||
void UseFakeStunServerWithResponse(const std::string& fake_addr,
|
||||
uint16_t fake_port) {
|
||||
TestStunServer::GetInstance()->SetResponseAddr(fake_addr, fake_port);
|
||||
// Sets an additional stun server
|
||||
peer_->SetStunServer(TestStunServer::GetInstance()->addr(),
|
||||
TestStunServer::GetInstance()->port());
|
||||
}
|
||||
|
||||
// NB: Only does substring matching, watch out for stuff like "1.2.3.4"
|
||||
// matching "21.2.3.47". " 1.2.3.4 " should not have false positives.
|
||||
bool StreamHasMatchingCandidate(unsigned int stream,
|
||||
const std::string& match) {
|
||||
std::vector<std::string> candidates = peer_->GetCandidates(stream);
|
||||
for (size_t c = 0; c < candidates.size(); ++c) {
|
||||
if (std::string::npos != candidates[c].find(match)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
mozilla::ScopedDeletePtr<IceTestPeer> peer_;
|
||||
};
|
||||
@ -869,6 +899,30 @@ TEST_F(IceGatherTest, TestBogusCandidate) {
|
||||
peer_->ParseCandidate(0, kBogusIceCandidate);
|
||||
}
|
||||
|
||||
TEST_F(IceGatherTest, VerifyTestStunServer) {
|
||||
UseFakeStunServerWithResponse("192.0.2.133", 3333);
|
||||
Gather();
|
||||
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
|
||||
}
|
||||
|
||||
TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddr) {
|
||||
UseFakeStunServerWithResponse("0.0.0.0", 3333);
|
||||
Gather();
|
||||
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 "));
|
||||
}
|
||||
|
||||
TEST_F(IceGatherTest, TestStunServerReturnsPort0) {
|
||||
UseFakeStunServerWithResponse("192.0.2.133", 0);
|
||||
Gather();
|
||||
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.2.133 0 "));
|
||||
}
|
||||
|
||||
TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) {
|
||||
UseFakeStunServerWithResponse("127.0.0.133", 3333);
|
||||
Gather();
|
||||
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
|
||||
}
|
||||
|
||||
TEST_F(IceConnectTest, TestGather) {
|
||||
AddStream("first", 1);
|
||||
ASSERT_TRUE(Gather(true));
|
||||
@ -1148,7 +1202,14 @@ int main(int argc, char **argv)
|
||||
// Start the tests
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
test_utils->sts_target()->Dispatch(
|
||||
WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC);
|
||||
|
||||
int rv = RUN_ALL_TESTS();
|
||||
|
||||
test_utils->sts_target()->Dispatch(
|
||||
WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC);
|
||||
|
||||
delete test_utils;
|
||||
return rv;
|
||||
}
|
||||
|
430
media/mtransport/test/stunserver.cpp
Normal file
430
media/mtransport/test/stunserver.cpp
Normal file
@ -0,0 +1,430 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Original author: ekr@rtfm.com
|
||||
|
||||
/*
|
||||
Original code from nICEr and nrappkit.
|
||||
|
||||
nICEr copyright:
|
||||
|
||||
Copyright (c) 2007, Adobe Systems, Incorporated
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Adobe Systems, Network Resonance nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
nrappkit copyright:
|
||||
|
||||
Copyright (C) 2001-2003, Network Resonance, Inc.
|
||||
Copyright (C) 2006, Network Resonance, Inc.
|
||||
All Rights Reserved
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Network Resonance, Inc. nor the name of any
|
||||
contributors to this software may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
ekr@rtfm.com Thu Dec 20 20:14:49 2001
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
#include "databuffer.h"
|
||||
|
||||
extern "C" {
|
||||
#include "nr_api.h"
|
||||
#include "async_wait.h"
|
||||
#include "async_timer.h"
|
||||
#include "nr_socket.h"
|
||||
#include "nr_socket_local.h"
|
||||
#include "transport_addr.h"
|
||||
#include "addrs.h"
|
||||
#include "local_addr.h"
|
||||
#include "stun_util.h"
|
||||
#include "registry.h"
|
||||
}
|
||||
|
||||
#include "stunserver.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
MOZ_MTLOG_MODULE("stunserver");
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Wrapper nr_socket which allows us to lie to the stun server about the
|
||||
// IP address.
|
||||
struct nr_socket_wrapped {
|
||||
nr_socket *sock_;
|
||||
nr_transport_addr addr_;
|
||||
};
|
||||
|
||||
static int nr_socket_wrapped_destroy(void **objp) {
|
||||
if (!objp || !*objp)
|
||||
return 0;
|
||||
|
||||
nr_socket_wrapped *wrapped = static_cast<nr_socket_wrapped *>(*objp);
|
||||
*objp = 0;
|
||||
|
||||
delete wrapped;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nr_socket_wrapped_sendto(void *obj, const void *msg, size_t len, int flags,
|
||||
nr_transport_addr *addr) {
|
||||
nr_socket_wrapped *wrapped = static_cast<nr_socket_wrapped *>(obj);
|
||||
|
||||
return nr_socket_sendto(wrapped->sock_, msg, len, flags, &wrapped->addr_);
|
||||
}
|
||||
|
||||
static int nr_socket_wrapped_recvfrom(void *obj, void * restrict buf, size_t maxlen,
|
||||
size_t *len, int flags, nr_transport_addr *addr) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
static int nr_socket_wrapped_getfd(void *obj, NR_SOCKET *fd) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
static int nr_socket_wrapped_getaddr(void *obj, nr_transport_addr *addrp) {
|
||||
nr_socket_wrapped *wrapped = static_cast<nr_socket_wrapped *>(obj);
|
||||
|
||||
return nr_socket_getaddr(wrapped->sock_, addrp);
|
||||
}
|
||||
|
||||
static int nr_socket_wrapped_close(void *obj) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
static int nr_socket_wrapped_set_send_addr(nr_socket *sock, nr_transport_addr *addr) {
|
||||
nr_socket_wrapped *wrapped = static_cast<nr_socket_wrapped *>(sock->obj);
|
||||
|
||||
return nr_transport_addr_copy(&wrapped->addr_, addr);
|
||||
}
|
||||
|
||||
static nr_socket_vtbl nr_socket_wrapped_vtbl = {
|
||||
nr_socket_wrapped_destroy,
|
||||
nr_socket_wrapped_sendto,
|
||||
nr_socket_wrapped_recvfrom,
|
||||
nr_socket_wrapped_getfd,
|
||||
nr_socket_wrapped_getaddr,
|
||||
nr_socket_wrapped_close
|
||||
};
|
||||
|
||||
int nr_socket_wrapped_create(nr_socket *inner, nr_socket **outp) {
|
||||
ScopedDeletePtr<nr_socket_wrapped> wrapped(new nr_socket_wrapped());
|
||||
|
||||
wrapped->sock_ = inner;
|
||||
|
||||
int r = nr_socket_create_int(wrapped.get(), &nr_socket_wrapped_vtbl, outp);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
wrapped.forget();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Instance static.
|
||||
// Note: Calling Create() at static init time is not going to be safe, since
|
||||
// we have no reason to expect this will be initted to a nullptr yet.
|
||||
TestStunServer* TestStunServer::instance;
|
||||
uint16_t TestStunServer::instance_port = 3478;
|
||||
|
||||
TestStunServer::~TestStunServer() {
|
||||
// TODO(ekr@rtfm.com): Put this on the right thread.
|
||||
|
||||
// Unhook callback from our listen socket.
|
||||
NR_SOCKET fd;
|
||||
if (!nr_socket_getfd(listen_sock_, &fd)) {
|
||||
NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
|
||||
}
|
||||
|
||||
// Free up stun context and network resources
|
||||
nr_stun_server_ctx_destroy(&stun_server_);
|
||||
nr_socket_destroy(&listen_sock_);
|
||||
nr_socket_destroy(&send_sock_);
|
||||
|
||||
// Make sure we aren't still waiting on a deferred response timer to pop
|
||||
if (timer_handle_)
|
||||
NR_async_timer_cancel(timer_handle_);
|
||||
|
||||
delete response_addr_;
|
||||
}
|
||||
|
||||
TestStunServer* TestStunServer::Create() {
|
||||
NR_reg_init(NR_REG_MODE_LOCAL);
|
||||
|
||||
ScopedDeletePtr<TestStunServer> server(new TestStunServer());
|
||||
|
||||
nr_local_addr addrs[100];
|
||||
int addr_ct;
|
||||
int r;
|
||||
|
||||
r = nr_stun_find_local_addresses(addrs, 100, &addr_ct);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't retrieve addresses");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (addr_ct < 1) {
|
||||
MOZ_MTLOG(ML_ERROR, "No local addresses");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Bind to the first address (arbitrarily) on configured port (default 3478)
|
||||
r = nr_transport_addr_set_port(&addrs[0].addr, instance_port);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't set port");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
r = nr_transport_addr_fmt_addr_string(&addrs[0].addr);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't re-set addr string");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
r = nr_socket_local_create(&addrs[0].addr, &server->listen_sock_);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't create listen socket");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NR_SOCKET fd;
|
||||
r = nr_socket_getfd(server->listen_sock_, &fd);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't get fd");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
r = nr_socket_wrapped_create(server->listen_sock_, &server->send_sock_);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't create send socket");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
r = nr_stun_server_ctx_create(const_cast<char *>("Test STUN server"),
|
||||
server->send_sock_,
|
||||
&server->stun_server_);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't create STUN server");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Cache the address and port.
|
||||
char addr_string[INET6_ADDRSTRLEN];
|
||||
r = nr_transport_addr_get_addrstring(&addrs[0].addr, addr_string,
|
||||
sizeof(addr_string));
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Failed to convert listen addr to a string representation");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
server->listen_addr_ = addr_string;
|
||||
server->listen_port_ = instance_port;
|
||||
|
||||
NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, &TestStunServer::readable_cb, server.get());
|
||||
|
||||
return server.forget();
|
||||
}
|
||||
|
||||
void TestStunServer::ConfigurePort(uint16_t port) {
|
||||
instance_port = port;
|
||||
}
|
||||
|
||||
TestStunServer* TestStunServer::GetInstance() {
|
||||
if (!instance)
|
||||
instance = Create();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void TestStunServer::ShutdownInstance() {
|
||||
delete instance;
|
||||
|
||||
instance = nullptr;
|
||||
}
|
||||
|
||||
|
||||
struct DeferredStunOperation {
|
||||
DeferredStunOperation(TestStunServer *server,
|
||||
const char *data, size_t len,
|
||||
nr_transport_addr *addr) :
|
||||
server_(server),
|
||||
buffer_(reinterpret_cast<const uint8_t *>(data), len) {
|
||||
nr_transport_addr_copy(&addr_, addr);
|
||||
}
|
||||
|
||||
TestStunServer *server_;
|
||||
DataBuffer buffer_;
|
||||
nr_transport_addr addr_;
|
||||
};
|
||||
|
||||
void TestStunServer::Process(const uint8_t *msg, size_t len, nr_transport_addr *addr) {
|
||||
// Set the wrapped address so that the response goes to the right place.
|
||||
nr_socket_wrapped_set_send_addr(send_sock_, addr);
|
||||
nr_stun_server_process_request(stun_server_, send_sock_,
|
||||
const_cast<char *>(reinterpret_cast<const char *>(msg)),
|
||||
len,
|
||||
response_addr_ ?
|
||||
response_addr_ : addr,
|
||||
NR_STUN_AUTH_RULE_OPTIONAL);
|
||||
}
|
||||
|
||||
void TestStunServer::process_cb(NR_SOCKET s, int how, void *cb_arg) {
|
||||
DeferredStunOperation *op = static_cast<DeferredStunOperation *>(cb_arg);
|
||||
op->server_->timer_handle_ = nullptr;
|
||||
op->server_->Process(op->buffer_.data(), op->buffer_.len(), &op->addr_);
|
||||
|
||||
delete op;
|
||||
}
|
||||
|
||||
void TestStunServer::readable_cb(NR_SOCKET s, int how, void *cb_arg) {
|
||||
TestStunServer* server = static_cast<TestStunServer*>(cb_arg);
|
||||
|
||||
char message[4096];
|
||||
size_t message_len;
|
||||
nr_transport_addr addr;
|
||||
|
||||
int r = nr_socket_recvfrom(server->listen_sock_, message, sizeof(message),
|
||||
&message_len, 0, &addr);
|
||||
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't read STUN message");
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_MTLOG(ML_DEBUG, "Received data of length " << message_len);
|
||||
|
||||
// Re-arm.
|
||||
NR_ASYNC_WAIT(s, NR_ASYNC_WAIT_READ, &TestStunServer::readable_cb, server);
|
||||
|
||||
|
||||
// If we have initial dropping set, check at this point.
|
||||
std::string key(addr.as_string);
|
||||
|
||||
if (server->received_ct_.count(key) == 0) {
|
||||
server->received_ct_[key] = 0;
|
||||
}
|
||||
|
||||
++server->received_ct_[key];
|
||||
|
||||
if (!server->active_ || (server->received_ct_[key] <= server->initial_ct_)) {
|
||||
MOZ_MTLOG(ML_DEBUG, "Dropping message #"
|
||||
<< server->received_ct_[key] << " from " << key);
|
||||
return;
|
||||
}
|
||||
|
||||
if (server->delay_ms_) {
|
||||
NR_ASYNC_TIMER_SET(server->delay_ms_,
|
||||
process_cb,
|
||||
new DeferredStunOperation(
|
||||
server,
|
||||
message, message_len,
|
||||
&addr),
|
||||
&server->timer_handle_);
|
||||
} else {
|
||||
server->Process(reinterpret_cast<const uint8_t *>(message), message_len, &addr);
|
||||
}
|
||||
}
|
||||
|
||||
void TestStunServer::SetActive(bool active) {
|
||||
active_ = active;
|
||||
}
|
||||
|
||||
void TestStunServer::SetDelay(uint32_t delay_ms) {
|
||||
delay_ms_ = delay_ms;
|
||||
}
|
||||
|
||||
void TestStunServer::SetDropInitialPackets(uint32_t count) {
|
||||
initial_ct_ = count;
|
||||
}
|
||||
|
||||
nsresult TestStunServer::SetResponseAddr(nr_transport_addr *addr) {
|
||||
delete response_addr_;
|
||||
|
||||
response_addr_ = new nr_transport_addr();
|
||||
|
||||
int r = nr_transport_addr_copy(response_addr_, addr);
|
||||
if (r)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TestStunServer::SetResponseAddr(const std::string& addr,
|
||||
uint16_t port) {
|
||||
nr_transport_addr addr2;
|
||||
|
||||
int r = nr_ip4_str_port_to_transport_addr(addr.c_str(),
|
||||
port, IPPROTO_UDP,
|
||||
&addr2);
|
||||
if (r)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return SetResponseAddr(&addr2);
|
||||
}
|
||||
|
||||
void TestStunServer::Reset() {
|
||||
delay_ms_ = 0;
|
||||
if (timer_handle_) {
|
||||
NR_async_timer_cancel(timer_handle_);
|
||||
timer_handle_ = nullptr;
|
||||
}
|
||||
delete response_addr_;
|
||||
response_addr_ = nullptr;
|
||||
}
|
||||
|
||||
} // close namespace
|
83
media/mtransport/test/stunserver.h
Normal file
83
media/mtransport/test/stunserver.h
Normal file
@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Original author: ekr@rtfm.com
|
||||
|
||||
#ifndef stunserver_h__
|
||||
#define stunserver_h__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "prio.h"
|
||||
#include "nsError.h"
|
||||
|
||||
typedef struct nr_stun_server_ctx_ nr_stun_server_ctx;
|
||||
typedef struct nr_socket_ nr_socket;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class TestStunServer {
|
||||
public:
|
||||
// Generally, you should only call API in this class from the same thread that
|
||||
// the initial |GetInstance| call was made from.
|
||||
static TestStunServer *GetInstance();
|
||||
static void ShutdownInstance();
|
||||
// |ConfigurePort| will only have an effect if called before the first call
|
||||
// to |GetInstance| (possibly following a |ShutdownInstance| call)
|
||||
static void ConfigurePort(uint16_t port);
|
||||
static TestStunServer *Create();
|
||||
|
||||
~TestStunServer();
|
||||
|
||||
void SetActive(bool active);
|
||||
void SetDelay(uint32_t delay_ms);
|
||||
void SetDropInitialPackets(uint32_t count);
|
||||
const std::string& addr() const { return listen_addr_; }
|
||||
uint16_t port() const { return listen_port_; }
|
||||
|
||||
// These should only be called from the same thread as the initial
|
||||
// |GetInstance| call.
|
||||
nsresult SetResponseAddr(nr_transport_addr *addr);
|
||||
nsresult SetResponseAddr(const std::string& addr, uint16_t port);
|
||||
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
TestStunServer()
|
||||
: listen_sock_(nullptr),
|
||||
send_sock_(nullptr),
|
||||
stun_server_(nullptr),
|
||||
active_(true),
|
||||
delay_ms_(0),
|
||||
initial_ct_(0),
|
||||
response_addr_(nullptr),
|
||||
timer_handle_(nullptr),
|
||||
listen_port_(0) {}
|
||||
|
||||
void Process(const uint8_t *msg, size_t len, nr_transport_addr *addr_in);
|
||||
|
||||
static void readable_cb(NR_SOCKET sock, int how, void *cb_arg);
|
||||
static void process_cb(NR_SOCKET sock, int how, void *cb_arg);
|
||||
|
||||
nr_socket *listen_sock_;
|
||||
nr_socket *send_sock_;
|
||||
nr_stun_server_ctx *stun_server_;
|
||||
bool active_;
|
||||
uint32_t delay_ms_;
|
||||
uint32_t initial_ct_;
|
||||
nr_transport_addr *response_addr_;
|
||||
void *timer_handle_;
|
||||
std::map<std::string, uint32_t> received_ct_;
|
||||
std::string listen_addr_;
|
||||
uint16_t listen_port_;
|
||||
|
||||
static TestStunServer* instance;
|
||||
static uint16_t instance_port;
|
||||
};
|
||||
|
||||
} // End of namespace mozilla
|
||||
|
||||
#endif
|
@ -18,6 +18,7 @@
|
||||
#include "mozilla/Scoped.h"
|
||||
#include "transportlayer.h"
|
||||
#include "m_cpp_utils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
// A stack of transport layers acts as a flow.
|
||||
// Generally, one reads and writes to the top layer.
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "logging.h"
|
||||
#include "transportflow.h"
|
||||
#include "transportlayer.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// Logging context
|
||||
namespace mozilla {
|
||||
@ -46,4 +47,19 @@ void TransportLayer::SetState(State state) {
|
||||
}
|
||||
}
|
||||
|
||||
nsresult TransportLayer::RunOnThread(nsIRunnable *event) {
|
||||
if (target_) {
|
||||
nsIThread *thr;
|
||||
|
||||
DebugOnly<nsresult> rv = NS_GetCurrentThread(&thr);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
if (target_ != thr) {
|
||||
return target_->Dispatch(event, NS_DISPATCH_SYNC);
|
||||
}
|
||||
}
|
||||
|
||||
return event->Run();
|
||||
}
|
||||
|
||||
} // close namespace
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "m_cpp_utils.h"
|
||||
|
||||
@ -62,20 +61,7 @@ class TransportLayer : public sigslot::has_slots<> {
|
||||
|
||||
// Dispatch a call onto our thread (or run on the same thread if
|
||||
// thread is not set). This is always synchronous.
|
||||
nsresult RunOnThread(nsIRunnable *event) {
|
||||
if (target_) {
|
||||
nsIThread *thr;
|
||||
|
||||
DebugOnly<nsresult> rv = NS_GetCurrentThread(&thr);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
if (target_ != thr) {
|
||||
return target_->Dispatch(event, NS_DISPATCH_SYNC);
|
||||
}
|
||||
}
|
||||
|
||||
return event->Run();
|
||||
}
|
||||
nsresult RunOnThread(nsIRunnable *event);
|
||||
|
||||
// Get the state
|
||||
State state() const { return state_; }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user