зеркало из https://github.com/mozilla/pjs.git
Bug 466256 - 'Workers: Prevent cross-site workers and properly resolve relative URIs.' r+sr=jst, a=blocking1.9.1+.
This commit is contained in:
Родитель
c528abc245
Коммит
039b848f40
|
@ -51,6 +51,7 @@
|
|||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsDOMThreadService.h"
|
||||
|
@ -252,7 +253,7 @@ nsDOMWorkerFunctions::LoadScripts(JSContext* aCx,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
rv = loader->LoadScripts(aCx, urls);
|
||||
rv = loader->LoadScripts(aCx, urls, PR_FALSE);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (!JS_IsExceptionPending(aCx)) {
|
||||
JS_ReportError(aCx, "Failed to load scripts");
|
||||
|
@ -780,6 +781,21 @@ nsDOMWorker::~nsDOMWorker()
|
|||
}
|
||||
|
||||
NS_ASSERTION(!mFeatures.Length(), "Live features!");
|
||||
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
|
||||
nsIPrincipal* principal;
|
||||
mPrincipal.forget(&principal);
|
||||
if (principal) {
|
||||
NS_ProxyRelease(mainThread, principal, PR_FALSE);
|
||||
}
|
||||
|
||||
nsIURI* uri;
|
||||
mURI.forget(&uri);
|
||||
if (uri) {
|
||||
NS_ProxyRelease(mainThread, uri, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
|
@ -1111,7 +1127,7 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
rv = loader->LoadScript(aCx, mScriptURL);
|
||||
rv = loader->LoadScript(aCx, mScriptURL, PR_TRUE);
|
||||
|
||||
JS_ReportPendingException(aCx);
|
||||
|
||||
|
@ -1121,6 +1137,8 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mPrincipal && mURI, "Script loader didn't set our principal!");
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMWorkers.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
@ -162,6 +164,22 @@ private:
|
|||
void ResumeFeatures();
|
||||
void CancelFeatures();
|
||||
|
||||
nsIPrincipal* GetPrincipal() {
|
||||
return mPrincipal;
|
||||
}
|
||||
|
||||
void SetPrincipal(nsIPrincipal* aPrincipal) {
|
||||
mPrincipal = aPrincipal;
|
||||
}
|
||||
|
||||
nsIURI* GetURI() {
|
||||
return mURI;
|
||||
}
|
||||
|
||||
void SetURI(nsIURI* aURI) {
|
||||
mURI = aURI;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// mParent will live as long as mParentWN but only mParentWN will keep the JS
|
||||
|
@ -190,6 +208,9 @@ private:
|
|||
|
||||
nsIXPConnectWrappedNative* mWrappedNative;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
||||
PRPackedBool mCanceled;
|
||||
PRPackedBool mSuspended;
|
||||
PRPackedBool mCompileAttempted;
|
||||
|
|
|
@ -69,7 +69,8 @@ nsDOMWorkerScriptLoader::nsDOMWorkerScriptLoader(nsDOMWorker* aWorker)
|
|||
: nsDOMWorkerFeature(aWorker),
|
||||
mTarget(nsnull),
|
||||
mScriptCount(0),
|
||||
mCanceled(PR_FALSE)
|
||||
mCanceled(PR_FALSE),
|
||||
mForWorker(PR_FALSE)
|
||||
{
|
||||
// Created on worker thread.
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
@ -82,7 +83,8 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsDOMWorkerScriptLoader, nsDOMWorkerFeature,
|
|||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
|
||||
const nsTArray<nsString>& aURLs)
|
||||
const nsTArray<nsString>& aURLs,
|
||||
PRBool aForWorker)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
|
@ -94,6 +96,8 @@ nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
|
|||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
mForWorker = aForWorker;
|
||||
|
||||
mScriptCount = aURLs.Length();
|
||||
if (!mScriptCount) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -147,12 +151,13 @@ nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
|
|||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::LoadScript(JSContext* aCx,
|
||||
const nsString& aURL)
|
||||
const nsString& aURL,
|
||||
PRBool aForWorker)
|
||||
{
|
||||
nsAutoTArray<nsString, 1> url;
|
||||
url.AppendElement(aURL);
|
||||
|
||||
return LoadScripts(aCx, url);
|
||||
return LoadScripts(aCx, url, aForWorker);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -414,9 +419,36 @@ nsDOMWorkerScriptLoader::RunInternal()
|
|||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsIPrincipal* principal;
|
||||
nsIURI* baseURI;
|
||||
|
||||
if (mForWorker) {
|
||||
NS_ASSERTION(mScriptCount == 1, "Bad state!");
|
||||
|
||||
nsRefPtr<nsDOMWorker> parentWorker = mWorker->GetParent();
|
||||
if (parentWorker) {
|
||||
principal = parentWorker->GetPrincipal();
|
||||
NS_ENSURE_STATE(principal);
|
||||
|
||||
baseURI = parentWorker->GetURI();
|
||||
NS_ENSURE_STATE(baseURI);
|
||||
}
|
||||
else {
|
||||
principal = parentDoc->NodePrincipal();
|
||||
NS_ENSURE_STATE(principal);
|
||||
|
||||
baseURI = parentDoc->GetBaseURI();
|
||||
}
|
||||
}
|
||||
else {
|
||||
principal = mWorker->GetPrincipal();
|
||||
baseURI = mWorker->GetURI();
|
||||
|
||||
NS_ASSERTION(principal && baseURI, "Should have been set already!");
|
||||
}
|
||||
|
||||
// All of these can potentially be null, but that should be ok. We'll either
|
||||
// succeed without them or fail below.
|
||||
nsIURI* parentBaseURI = parentDoc->GetBaseURI();
|
||||
nsCOMPtr<nsILoadGroup> loadGroup(parentDoc->GetDocumentLoadGroup());
|
||||
nsCOMPtr<nsIIOService> ios(do_GetIOService());
|
||||
|
||||
|
@ -427,7 +459,7 @@ nsDOMWorkerScriptLoader::RunInternal()
|
|||
nsCOMPtr<nsIURI>& uri = loadInfo.finalURI;
|
||||
rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
|
||||
loadInfo.url, parentDoc,
|
||||
parentBaseURI);
|
||||
baseURI);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -435,21 +467,12 @@ nsDOMWorkerScriptLoader::RunInternal()
|
|||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
|
||||
|
||||
rv = secMan->CheckLoadURIWithPrincipal(parentDoc->NodePrincipal(), uri, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT,
|
||||
uri,
|
||||
parentDoc->NodePrincipal(),
|
||||
parentDoc,
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, uri,
|
||||
principal, parentDoc,
|
||||
NS_LITERAL_CSTRING("text/javascript"),
|
||||
nsnull,
|
||||
&shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
secMan);
|
||||
nsnull, &shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(), secMan);
|
||||
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
||||
if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
|
@ -457,6 +480,22 @@ nsDOMWorkerScriptLoader::RunInternal()
|
|||
return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
|
||||
}
|
||||
|
||||
// If this script loader is being used to make a new worker then we need to
|
||||
// do a same-origin check. Otherwise we need to clear the load with the
|
||||
// security manager.
|
||||
if (mForWorker) {
|
||||
rv = principal->CheckMayLoad(uri, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set the principal and URI on the new worker.
|
||||
mWorker->SetPrincipal(principal);
|
||||
mWorker->SetURI(uri);
|
||||
}
|
||||
else {
|
||||
rv = secMan->CheckLoadURIWithPrincipal(principal, uri, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// We need to know which index we're on in OnStreamComplete so we know where
|
||||
// to put the result.
|
||||
nsCOMPtr<nsISupportsPRUint32> indexSupports =
|
||||
|
|
|
@ -102,10 +102,12 @@ public:
|
|||
nsDOMWorkerScriptLoader(nsDOMWorker* aWorker);
|
||||
|
||||
nsresult LoadScripts(JSContext* aCx,
|
||||
const nsTArray<nsString>& aURLs);
|
||||
const nsTArray<nsString>& aURLs,
|
||||
PRBool aForWorker);
|
||||
|
||||
nsresult LoadScript(JSContext* aCx,
|
||||
const nsString& aURL);
|
||||
const nsString& aURL,
|
||||
PRBool aForWorker);
|
||||
|
||||
virtual void Cancel();
|
||||
|
||||
|
@ -216,6 +218,7 @@ private:
|
|||
nsTArray<ScriptLoaderRunnable*> mPendingRunnables;
|
||||
|
||||
PRPackedBool mCanceled;
|
||||
PRPackedBool mForWorker;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERSCRIPTLOADER_H__ */
|
||||
|
|
|
@ -41,7 +41,7 @@ topsrcdir = @top_srcdir@
|
|||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
relativesrcdir = dom/src/threads/tests
|
||||
relativesrcdir = dom/src/threads/test
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -61,6 +61,10 @@ _TEST_FILES = \
|
|||
recursion_worker.js \
|
||||
test_regExpStatics.html \
|
||||
regExpStatics_worker.js \
|
||||
test_relativeLoad.html \
|
||||
relativeLoad_worker.js \
|
||||
relativeLoad_worker2.js \
|
||||
relativeLoad_import.js \
|
||||
test_simpleThread.html \
|
||||
simpleThread_worker.js \
|
||||
test_terminate.html \
|
||||
|
@ -81,5 +85,14 @@ _TEST_FILES = \
|
|||
fibonacci_worker.js \
|
||||
$(NULL)
|
||||
|
||||
_SUBDIR_TEST_FILES = \
|
||||
relativeLoad_sub_worker.js \
|
||||
relativeLoad_sub_worker2.js \
|
||||
relativeLoad_sub_import.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
||||
libs:: $(_SUBDIR_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)/subdir
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
const workerURL = "relativeLoad_worker.js";
|
|
@ -0,0 +1 @@
|
|||
const workerSubURL = "subdir/relativeLoad_sub_worker.js";
|
|
@ -0,0 +1,15 @@
|
|||
const importSubURL = "relativeLoad_sub_import.js";
|
||||
|
||||
onmessage = function(event) {
|
||||
importScripts(importSubURL);
|
||||
var worker = new Worker("relativeLoad_sub_worker2.js");
|
||||
worker.onerror = function(event) {
|
||||
throw event.data;
|
||||
};
|
||||
worker.onmessage = function(event) {
|
||||
if (event.data != workerSubURL) {
|
||||
throw "Bad data!";
|
||||
}
|
||||
postMessage(workerSubURL);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
const importSubURL = "relativeLoad_sub_import.js";
|
||||
|
||||
importScripts(importSubURL);
|
||||
|
||||
postMessage(workerSubURL);
|
|
@ -0,0 +1,15 @@
|
|||
const importURL = "relativeLoad_import.js";
|
||||
|
||||
onmessage = function(event) {
|
||||
importScripts(importURL);
|
||||
var worker = new Worker("relativeLoad_worker2.js");
|
||||
worker.onerror = function(event) {
|
||||
throw event.data;
|
||||
};
|
||||
worker.onmessage = function(event) {
|
||||
if (event.data != workerURL) {
|
||||
throw "Bad data!";
|
||||
}
|
||||
postMessage(workerURL);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
const importURL = "relativeLoad_import.js";
|
||||
|
||||
importScripts(importURL);
|
||||
|
||||
postMessage(workerURL);
|
|
@ -22,7 +22,7 @@ Tests of DOM Worker Threads
|
|||
worker.onerror = function(event) {
|
||||
is(event.data,
|
||||
'[JavaScript Error: "too much recursion" {file: "http://localhost:8888' +
|
||||
'/tests/dom/src/threads/tests/recursion_worker.js" line: 2}]');
|
||||
'/tests/dom/src/threads/test/recursion_worker.js" line: 2}]');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads relative load
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<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 class="testbody" type="text/javascript">
|
||||
|
||||
var index = -1;
|
||||
|
||||
var urls = [
|
||||
"relativeLoad_worker.js",
|
||||
"subdir/relativeLoad_sub_worker.js"
|
||||
];
|
||||
|
||||
function messageHandler(event) {
|
||||
if (index >= 0) {
|
||||
is(event.data, urls[index], "Bad url!");
|
||||
if (index == urls.length - 1) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var worker = new Worker(urls[++index]);
|
||||
worker.onmessage = messageHandler;
|
||||
worker.onerror = function(event) {
|
||||
ok(false, "Worker had an error: " + event.data);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
worker.postMessage("start");
|
||||
}
|
||||
|
||||
messageHandler();
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче