mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 761227 - Support XMLHttpRequestParameters in workers. r=bent
This commit is contained in:
parent
156073c088
commit
13e87ce3ba
@ -457,6 +457,10 @@ nsXMLHttpRequest::InitParameters(JSContext* aCx, const jsval* aParams)
|
||||
void
|
||||
nsXMLHttpRequest::InitParameters(bool aAnon, bool aSystem)
|
||||
{
|
||||
if (!aAnon && !aSystem) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for permissions.
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetOwner());
|
||||
if (!window || !window->GetDocShell()) {
|
||||
@ -485,8 +489,7 @@ nsXMLHttpRequest::InitParameters(bool aAnon, bool aSystem)
|
||||
}
|
||||
}
|
||||
|
||||
mIsAnon = aAnon;
|
||||
mIsSystem = aSystem;
|
||||
SetParameters(aAnon, aSystem);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -203,6 +203,12 @@ public:
|
||||
nsresult InitParameters(JSContext* aCx, const jsval* aParams);
|
||||
void InitParameters(bool aAnon, bool aSystem);
|
||||
|
||||
void SetParameters(bool aAnon, bool aSystem)
|
||||
{
|
||||
mIsAnon = aAnon;
|
||||
mIsSystem = aSystem;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIXMLHttpRequest
|
||||
|
@ -5,14 +5,14 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for XMLHttpRequest with system privileges</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.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 onload="runTests();">
|
||||
<p id="display">
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
|
@ -497,8 +497,11 @@ public:
|
||||
|
||||
mWorkerPrivate->SetPrincipal(channelPrincipal);
|
||||
|
||||
// Set Eval and ContentSecurityPolicy
|
||||
if (parent) {
|
||||
// XHR Params Allowed
|
||||
mWorkerPrivate->SetXHRParamsAllowed(parent->XHRParamsAllowed());
|
||||
|
||||
// Set Eval and ContentSecurityPolicy
|
||||
mWorkerPrivate->SetCSP(parent->GetCSP());
|
||||
mWorkerPrivate->SetEvalAllowed(parent->IsEvalAllowed());
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
@ -2458,7 +2459,8 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx, JSObject* aObject,
|
||||
nsCOMPtr<nsIURI>& aBaseURI,
|
||||
nsCOMPtr<nsIPrincipal>& aPrincipal,
|
||||
nsCOMPtr<nsIContentSecurityPolicy>& aCSP,
|
||||
bool aEvalAllowed)
|
||||
bool aEvalAllowed,
|
||||
bool aXHRParamsAllowed)
|
||||
: WorkerPrivateParent<WorkerPrivate>(aCx, aObject, aParent, aParentJSContext,
|
||||
aScriptURL, aIsChromeWorker, aDomain,
|
||||
aWindow, aParentScriptContext, aBaseURI,
|
||||
@ -2466,7 +2468,8 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx, JSObject* aObject,
|
||||
mJSContext(nullptr), mErrorHandlerRecursionCount(0), mNextTimeoutId(1),
|
||||
mStatus(Pending), mSuspended(false), mTimerRunning(false),
|
||||
mRunningExpiredTimeouts(false), mCloseHandlerStarted(false),
|
||||
mCloseHandlerFinished(false), mMemoryReporterRunning(false)
|
||||
mCloseHandlerFinished(false), mMemoryReporterRunning(false),
|
||||
mXHRParamsAllowed(aXHRParamsAllowed)
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivate);
|
||||
}
|
||||
@ -2493,6 +2496,8 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
|
||||
|
||||
JSContext* parentContext;
|
||||
|
||||
bool xhrParamsAllowed = false;
|
||||
|
||||
if (aParent) {
|
||||
aParent->AssertIsOnWorkerThread();
|
||||
|
||||
@ -2615,6 +2620,8 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xhrParamsAllowed = CheckXHRParamsAllowed(window);
|
||||
}
|
||||
else {
|
||||
// Not a window
|
||||
@ -2632,6 +2639,8 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
xhrParamsAllowed = true;
|
||||
}
|
||||
|
||||
NS_ASSERTION(principal, "Must have a principal now!");
|
||||
@ -2663,7 +2672,7 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
|
||||
nsRefPtr<WorkerPrivate> worker =
|
||||
new WorkerPrivate(aCx, aObj, aParent, parentContext, scriptURL,
|
||||
aIsChromeWorker, domain, window, scriptContext, baseURI,
|
||||
principal, csp, evalAllowed);
|
||||
principal, csp, evalAllowed, xhrParamsAllowed);
|
||||
|
||||
worker->SetIsDOMBinding();
|
||||
worker->SetWrapper(aObj);
|
||||
@ -3007,6 +3016,36 @@ WorkerPrivate::ProcessAllControlRunnables()
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::CheckXHRParamsAllowed(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
NS_ASSERTION(aWindow, "Wrong cannot be null");
|
||||
|
||||
if (!aWindow->GetDocShell()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aWindow->GetExtantDocument());
|
||||
if (!doc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permMgr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t permission;
|
||||
nsresult rv = permMgr->TestPermissionFromPrincipal(doc->NodePrincipal(),
|
||||
"systemXHR", &permission);
|
||||
if (NS_FAILED(rv) || permission != nsIPermissionManager::ALLOW_ACTION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::Dispatch(WorkerRunnable* aEvent, EventQueue* aQueue)
|
||||
{
|
||||
|
@ -570,6 +570,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
||||
bool mCloseHandlerStarted;
|
||||
bool mCloseHandlerFinished;
|
||||
bool mMemoryReporterRunning;
|
||||
bool mXHRParamsAllowed;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
@ -710,6 +711,18 @@ public:
|
||||
bool
|
||||
DisableMemoryReporter();
|
||||
|
||||
bool
|
||||
XHRParamsAllowed() const
|
||||
{
|
||||
return mXHRParamsAllowed;
|
||||
}
|
||||
|
||||
void
|
||||
SetXHRParamsAllowed(bool aAllowed)
|
||||
{
|
||||
mXHRParamsAllowed = aAllowed;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
void
|
||||
UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal);
|
||||
@ -751,7 +764,8 @@ private:
|
||||
nsCOMPtr<nsPIDOMWindow>& aWindow,
|
||||
nsCOMPtr<nsIScriptContext>& aScriptContext,
|
||||
nsCOMPtr<nsIURI>& aBaseURI, nsCOMPtr<nsIPrincipal>& aPrincipal,
|
||||
nsCOMPtr<nsIContentSecurityPolicy>& aCSP, bool aEvalAllowed);
|
||||
nsCOMPtr<nsIContentSecurityPolicy>& aCSP, bool aEvalAllowed,
|
||||
bool aXHRParamsAllowed);
|
||||
|
||||
static bool
|
||||
GetContentSecurityPolicy(JSContext *aCx,
|
||||
@ -811,6 +825,9 @@ private:
|
||||
|
||||
bool
|
||||
ProcessAllControlRunnables();
|
||||
|
||||
static bool
|
||||
CheckXHRParamsAllowed(nsPIDOMWindow* aWindow);
|
||||
};
|
||||
|
||||
WorkerPrivate*
|
||||
|
@ -90,6 +90,10 @@ public:
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
XMLHttpRequest* mXMLHttpRequestPrivate;
|
||||
|
||||
// XHR Params:
|
||||
bool mMozAnon;
|
||||
bool mMozSystem;
|
||||
|
||||
// Only touched on the main thread.
|
||||
nsRefPtr<nsXMLHttpRequest> mXHR;
|
||||
nsCOMPtr<nsIXMLHttpRequestUpload> mXHRUpload;
|
||||
@ -121,8 +125,9 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
Proxy(XMLHttpRequest* aXHRPrivate)
|
||||
Proxy(XMLHttpRequest* aXHRPrivate, bool aMozAnon, bool aMozSystem)
|
||||
: mWorkerPrivate(nullptr), mXMLHttpRequestPrivate(aXHRPrivate),
|
||||
mMozAnon(aMozAnon), mMozSystem(aMozSystem),
|
||||
mInnerEventStreamId(0), mInnerChannelId(0), mOutstandingSendCount(0),
|
||||
mOuterEventStreamId(0), mOuterChannelId(0), mLastLoaded(0), mLastTotal(0),
|
||||
mLastUploadLoaded(0), mLastUploadTotal(0), mIsSyncXHR(false),
|
||||
@ -158,6 +163,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
mXHR->SetParameters(mMozAnon, mMozSystem);
|
||||
|
||||
if (NS_FAILED(mXHR->GetUpload(getter_AddRefs(mXHRUpload)))) {
|
||||
mXHR = nullptr;
|
||||
return false;
|
||||
@ -1434,7 +1441,7 @@ XMLHttpRequest::XMLHttpRequest(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
mWorkerPrivate(aWorkerPrivate),
|
||||
mResponseType(XMLHttpRequestResponseTypeValues::Text), mTimeout(0),
|
||||
mJSObjectRooted(false), mMultipart(false), mBackgroundRequest(false),
|
||||
mWithCredentials(false), mCanceled(false)
|
||||
mWithCredentials(false), mCanceled(false), mMozAnon(false), mMozSystem(false)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
@ -1479,7 +1486,10 @@ XMLHttpRequest::Constructor(JSContext* aCx,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: process aParams. See bug 761227
|
||||
if (workerPrivate->XHRParamsAllowed()) {
|
||||
xhr->mMozAnon = aParams.mozAnon;
|
||||
xhr->mMozSystem = aParams.mozSystem;
|
||||
}
|
||||
|
||||
xhr->mJSObject = xhr->GetJSObject();
|
||||
return xhr;
|
||||
@ -1744,7 +1754,7 @@ XMLHttpRequest::Open(const nsAString& aMethod, const nsAString& aUrl,
|
||||
}
|
||||
}
|
||||
else {
|
||||
mProxy = new Proxy(this);
|
||||
mProxy = new Proxy(this, mMozAnon, mMozSystem);
|
||||
}
|
||||
|
||||
mProxy->mOuterEventStreamId++;
|
||||
|
@ -59,6 +59,9 @@ private:
|
||||
bool mWithCredentials;
|
||||
bool mCanceled;
|
||||
|
||||
bool mMozAnon;
|
||||
bool mMozSystem;
|
||||
|
||||
protected:
|
||||
XMLHttpRequest(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
virtual ~XMLHttpRequest();
|
||||
@ -262,14 +265,14 @@ public:
|
||||
mStateData.mResponse = JSVAL_NULL;
|
||||
}
|
||||
|
||||
bool MozAnon() {
|
||||
// TODO: bug 761227
|
||||
return false;
|
||||
bool MozAnon() const
|
||||
{
|
||||
return mMozAnon;
|
||||
}
|
||||
|
||||
bool MozSystem() {
|
||||
// TODO: bug 761227
|
||||
return false;
|
||||
bool MozSystem() const
|
||||
{
|
||||
return mMozSystem;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -91,6 +91,10 @@ MOCHITEST_FILES = \
|
||||
test_xhr_implicit_cancel.html \
|
||||
xhr_implicit_cancel_worker.js \
|
||||
test_xhr_timeout.html \
|
||||
test_xhr_parameters.html \
|
||||
test_xhr_parameters.js \
|
||||
test_xhr_system.html \
|
||||
test_xhr_system.js \
|
||||
test_blobConstructor.html \
|
||||
test_csp.html \
|
||||
test_csp.js \
|
||||
|
63
dom/workers/test/test_xhr_parameters.html
Normal file
63
dom/workers/test/test_xhr_parameters.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for XMLHttpRequest with system privileges</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>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
|
||||
function message(event) {
|
||||
if (event.data.test == 'ok')
|
||||
ok(event.data.a, event.data.event);
|
||||
else if(event.data.test == 'is')
|
||||
is(event.data.a, event.data.b, event.data.event);
|
||||
else if(event.data.test == 'finish') {
|
||||
run();
|
||||
}
|
||||
};
|
||||
|
||||
function test1() {
|
||||
var worker = new Worker("test_xhr_parameters.js");
|
||||
worker.onmessage = message;
|
||||
|
||||
// Run the tests once without API privileges...
|
||||
worker.postMessage(false);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
// ...and once with privileges.
|
||||
SpecialPowers.addPermission("systemXHR", true, document);
|
||||
|
||||
var worker = new Worker("test_xhr_parameters.js");
|
||||
worker.onmessage = message;
|
||||
worker.postMessage(true);
|
||||
}
|
||||
|
||||
var tests = [ test1, test2 ];
|
||||
function run() {
|
||||
if (!tests.length) {
|
||||
SpecialPowers.removePermission("systemXHR", document);
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var func = tests.shift();
|
||||
func();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
run();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
75
dom/workers/test/test_xhr_parameters.js
Normal file
75
dom/workers/test/test_xhr_parameters.js
Normal file
@ -0,0 +1,75 @@
|
||||
function ok(what, msg) {
|
||||
postMessage({ event: msg, test: 'ok', a: what });
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
postMessage({ event: msg, test: 'is', a: a, b: b });
|
||||
}
|
||||
|
||||
// This is a copy of content/base/test/test_XHR_parameters.js
|
||||
var validParameters = [
|
||||
undefined,
|
||||
null,
|
||||
{},
|
||||
{mozSystem: ""},
|
||||
{mozSystem: 0},
|
||||
{mozAnon: 1},
|
||||
{mozAnon: []},
|
||||
{get mozAnon() { return true; }},
|
||||
0,
|
||||
7,
|
||||
Math.PI,
|
||||
"string",
|
||||
true,
|
||||
false,
|
||||
];
|
||||
|
||||
var invalidParameters = [
|
||||
{get mozSystem() { throw "Bla"; } },
|
||||
];
|
||||
|
||||
|
||||
function testParameters(havePrivileges) {
|
||||
|
||||
function testValidParameter(value) {
|
||||
var xhr;
|
||||
try {
|
||||
xhr = new XMLHttpRequest(value);
|
||||
} catch (ex) {
|
||||
ok(false, "Got unexpected exception: " + ex);
|
||||
return;
|
||||
}
|
||||
ok(!!xhr, "passed " + JSON.stringify(value));
|
||||
|
||||
// If the page doesnt have privileges to create a system or anon XHR,
|
||||
// these flags will always be false no matter what is passed.
|
||||
var expectedAnon = false;
|
||||
var expectedSystem = false;
|
||||
if (havePrivileges) {
|
||||
expectedAnon = Boolean(value && value.mozAnon);
|
||||
expectedSystem = Boolean(value && value.mozSystem);
|
||||
}
|
||||
is(xhr.mozAnon, expectedAnon, "testing mozAnon");
|
||||
is(xhr.mozSystem, expectedSystem, "testing mozSystem");
|
||||
}
|
||||
|
||||
|
||||
function testInvalidParameter(value) {
|
||||
try {
|
||||
new XMLHttpRequest(value);
|
||||
ok(false, "invalid parameter did not cause exception: " +
|
||||
JSON.stringify(value));
|
||||
} catch (ex) {
|
||||
ok(true, "invalid parameter raised exception as expected: " +
|
||||
JSON.stringify(ex));
|
||||
}
|
||||
}
|
||||
|
||||
validParameters.forEach(testValidParameter);
|
||||
invalidParameters.forEach(testInvalidParameter);
|
||||
}
|
||||
|
||||
self.onmessage = function onmessage(event) {
|
||||
testParameters(event.data);
|
||||
postMessage({test: "finish"});
|
||||
};
|
54
dom/workers/test/test_xhr_system.html
Normal file
54
dom/workers/test/test_xhr_system.html
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for XMLHttpRequest with system privileges</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>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
|
||||
function message(event) {
|
||||
if (event.data.test == 'ok')
|
||||
ok(event.data.a, event.data.event);
|
||||
else if(event.data.test == 'is')
|
||||
is(event.data.a, event.data.b, event.data.event);
|
||||
else if(event.data.test == 'finish') {
|
||||
run();
|
||||
}
|
||||
};
|
||||
|
||||
function test1() {
|
||||
// ...and once with privileges.
|
||||
SpecialPowers.addPermission("systemXHR", true, document);
|
||||
var worker = new Worker("test_xhr_system.js");
|
||||
worker.onmessage = message;
|
||||
worker.postMessage(true);
|
||||
}
|
||||
|
||||
var tests = [ test1 ];
|
||||
function run() {
|
||||
if (!tests.length) {
|
||||
SpecialPowers.removePermission("systemXHR", document);
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var func = tests.shift();
|
||||
func();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
run();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
30
dom/workers/test/test_xhr_system.js
Normal file
30
dom/workers/test/test_xhr_system.js
Normal file
@ -0,0 +1,30 @@
|
||||
function ok(what, msg) {
|
||||
postMessage({ event: msg, test: 'ok', a: what });
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
postMessage({ event: msg, test: 'is', a: a, b: b });
|
||||
}
|
||||
|
||||
self.onmessage = function onmessage(event) {
|
||||
|
||||
// An XHR with system privileges will be able to do cross-site calls.
|
||||
|
||||
const TEST_URL = "http://example.com/tests/content/base/test/test_XHR_system.html";
|
||||
is(location.hostname, "mochi.test", "hostname");
|
||||
|
||||
var xhr = new XMLHttpRequest({mozSystem: true});
|
||||
is(xhr.mozSystem, true, ".mozSystem == true");
|
||||
xhr.open("GET", TEST_URL);
|
||||
xhr.onload = function onload() {
|
||||
is(xhr.status, 200);
|
||||
ok(xhr.responseText != null);
|
||||
ok(xhr.responseText.length);
|
||||
postMessage({test: "finish"});
|
||||
};
|
||||
xhr.onerror = function onerror() {
|
||||
ok(false, "Got an error event!");
|
||||
postMessage({test: "finish"});
|
||||
}
|
||||
xhr.send();
|
||||
};
|
Loading…
Reference in New Issue
Block a user