Bug 1445883 - Port XHR to WorkerRef, r=smaug

This commit is contained in:
Andrea Marchesini 2018-03-16 14:13:04 +01:00
Родитель 692193e3b5
Коммит cc07a166fe
4 изменённых файлов: 208 добавлений и 162 удалений

Просмотреть файл

@ -24,6 +24,7 @@
#include "mozilla/dom/URLSearchParams.h" #include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/WorkerScope.h" #include "mozilla/dom/WorkerScope.h"
#include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRef.h"
#include "mozilla/dom/WorkerRunnable.h" #include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
@ -241,9 +242,8 @@ class SendRunnable final
bool mHasUploadListeners; bool mHasUploadListeners;
public: public:
SendRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, SendRunnable(Proxy* aProxy, const nsAString& aStringBody)
const nsAString& aStringBody) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
, StructuredCloneHolder(CloningSupported, TransferringNotSupported, , StructuredCloneHolder(CloningSupported, TransferringNotSupported,
StructuredCloneScope::SameProcessDifferentThread) StructuredCloneScope::SameProcessDifferentThread)
, mStringBody(aStringBody) , mStringBody(aStringBody)
@ -541,8 +541,8 @@ private:
class SyncTeardownRunnable final : public WorkerThreadProxySyncRunnable class SyncTeardownRunnable final : public WorkerThreadProxySyncRunnable
{ {
public: public:
SyncTeardownRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy) explicit SyncTeardownRunnable(Proxy* aProxy)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy)
{ } { }
private: private:
@ -563,9 +563,8 @@ class SetBackgroundRequestRunnable final :
bool mValue; bool mValue;
public: public:
SetBackgroundRequestRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, SetBackgroundRequestRunnable(Proxy* aProxy, bool aValue)
bool aValue) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
, mValue(aValue) , mValue(aValue)
{ } { }
@ -586,9 +585,8 @@ class SetWithCredentialsRunnable final :
bool mValue; bool mValue;
public: public:
SetWithCredentialsRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, SetWithCredentialsRunnable(Proxy* aProxy, bool aValue)
bool aValue) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
, mValue(aValue) , mValue(aValue)
{ } { }
@ -608,9 +606,9 @@ class SetResponseTypeRunnable final : public WorkerThreadProxySyncRunnable
XMLHttpRequestResponseType mResponseType; XMLHttpRequestResponseType mResponseType;
public: public:
SetResponseTypeRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, SetResponseTypeRunnable(Proxy* aProxy,
XMLHttpRequestResponseType aResponseType) XMLHttpRequestResponseType aResponseType)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy),
mResponseType(aResponseType) mResponseType(aResponseType)
{ } { }
@ -639,9 +637,8 @@ class SetTimeoutRunnable final : public WorkerThreadProxySyncRunnable
uint32_t mTimeout; uint32_t mTimeout;
public: public:
SetTimeoutRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, SetTimeoutRunnable(Proxy* aProxy, uint32_t aTimeout)
uint32_t aTimeout) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy),
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
mTimeout(aTimeout) mTimeout(aTimeout)
{ } { }
@ -659,8 +656,8 @@ private:
class AbortRunnable final : public WorkerThreadProxySyncRunnable class AbortRunnable final : public WorkerThreadProxySyncRunnable
{ {
public: public:
AbortRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy) explicit AbortRunnable(Proxy* aProxy)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy)
{ } { }
private: private:
@ -677,9 +674,8 @@ class GetAllResponseHeadersRunnable final :
nsCString& mResponseHeaders; nsCString& mResponseHeaders;
public: public:
GetAllResponseHeadersRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, GetAllResponseHeadersRunnable(Proxy* aProxy, nsCString& aResponseHeaders)
nsCString& aResponseHeaders) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy),
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
mResponseHeaders(aResponseHeaders) mResponseHeaders(aResponseHeaders)
{ } { }
@ -700,9 +696,9 @@ class GetResponseHeaderRunnable final : public WorkerThreadProxySyncRunnable
nsCString& mValue; nsCString& mValue;
public: public:
GetResponseHeaderRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, GetResponseHeaderRunnable(Proxy* aProxy, const nsACString& aHeader,
const nsACString& aHeader, nsCString& aValue) nsCString& aValue)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy),
mHeader(aHeader), mHeader(aHeader),
mValue(aValue) mValue(aValue)
{ } { }
@ -779,9 +775,10 @@ class SetRequestHeaderRunnable final : public WorkerThreadProxySyncRunnable
nsCString mValue; nsCString mValue;
public: public:
SetRequestHeaderRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, SetRequestHeaderRunnable(Proxy* aProxy,
const nsACString& aHeader, const nsACString& aValue) const nsACString& aHeader,
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), const nsACString& aValue)
: WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy),
mHeader(aHeader), mHeader(aHeader),
mValue(aValue) mValue(aValue)
{ } { }
@ -802,9 +799,8 @@ class OverrideMimeTypeRunnable final : public WorkerThreadProxySyncRunnable
nsString mMimeType; nsString mMimeType;
public: public:
OverrideMimeTypeRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, OverrideMimeTypeRunnable(Proxy* aProxy, const nsAString& aMimeType)
const nsAString& aMimeType) : WorkerThreadProxySyncRunnable(GetCurrentThreadWorkerPrivate(), aProxy),
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
mMimeType(aMimeType) mMimeType(aMimeType)
{ } { }
@ -1307,7 +1303,7 @@ EventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
state->mResponseURL = mResponseURL; state->mResponseURL = mResponseURL;
XMLHttpRequestWorker* xhr = mProxy->mXMLHttpRequestPrivate; XMLHttpRequestWorker* xhr = mProxy->mXMLHttpRequestPrivate;
xhr->UpdateState(*state.get(), mUseCachedArrayBufferResponse); xhr->UpdateState(aCx, *state.get(), mUseCachedArrayBufferResponse);
if (mType.EqualsASCII(sEventStrings[STRING_readystatechange])) { if (mType.EqualsASCII(sEventStrings[STRING_readystatechange])) {
if (mReadyState == 4 && !mUploadEvent && !mProxy->mSeenLoadStart) { if (mReadyState == 4 && !mUploadEvent && !mProxy->mSeenLoadStart) {
@ -1543,24 +1539,27 @@ SendRunnable::RunOnMainThread(ErrorResult& aRv)
} }
} }
XMLHttpRequestWorker::XMLHttpRequestWorker(WorkerPrivate* aWorkerPrivate) XMLHttpRequestWorker::XMLHttpRequestWorker()
: WorkerHolder("XMLHttpRequestWorker"), mWorkerPrivate(aWorkerPrivate), : mResponseType(XMLHttpRequestResponseType::Text)
mResponseType(XMLHttpRequestResponseType::Text), mTimeout(0), , mTimeout(0)
mRooted(false), mBackgroundRequest(false), mWithCredentials(false), , mBackgroundRequest(false)
mCanceled(false), mMozAnon(false), mMozSystem(false) , mWithCredentials(false)
, mCanceled(false)
, mMozAnon(false)
, mMozSystem(false)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); MOZ_ASSERT(IsCurrentThreadRunningWorker());
mozilla::HoldJSObjects(this); mozilla::HoldJSObjects(this);
} }
XMLHttpRequestWorker::~XMLHttpRequestWorker() XMLHttpRequestWorker::~XMLHttpRequestWorker()
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
ReleaseProxy(XHRIsGoingAway); ReleaseProxy(XHRIsGoingAway);
MOZ_ASSERT(!mRooted); MOZ_ASSERT(!mWorkerRef);
mozilla::DropJSObjects(this); mozilla::DropJSObjects(this);
} }
@ -1595,12 +1594,12 @@ XMLHttpRequestWorker::Construct(const GlobalObject& aGlobal,
const MozXMLHttpRequestParameters& aParams, const MozXMLHttpRequestParameters& aParams,
ErrorResult& aRv) ErrorResult& aRv)
{ {
RefPtr<XMLHttpRequestWorker> xhr = new XMLHttpRequestWorker();
JSContext* cx = aGlobal.Context(); JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
MOZ_ASSERT(workerPrivate); MOZ_ASSERT(workerPrivate);
RefPtr<XMLHttpRequestWorker> xhr = new XMLHttpRequestWorker(workerPrivate);
if (workerPrivate->XHRParamsAllowed()) { if (workerPrivate->XHRParamsAllowed()) {
if (aParams.mMozSystem) if (aParams.mMozSystem)
xhr->mMozAnon = true; xhr->mMozAnon = true;
@ -1615,8 +1614,7 @@ XMLHttpRequestWorker::Construct(const GlobalObject& aGlobal,
void void
XMLHttpRequestWorker::ReleaseProxy(ReleaseType aType) XMLHttpRequestWorker::ReleaseProxy(ReleaseType aType)
{ {
// Can't assert that we're on the worker thread here because mWorkerPrivate NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
// may be gone.
if (mProxy) { if (mProxy) {
if (aType == XHRIsGoingAway) { if (aType == XHRIsGoingAway) {
@ -1626,7 +1624,10 @@ XMLHttpRequestWorker::ReleaseProxy(ReleaseType aType)
new AsyncTeardownRunnable(mProxy); new AsyncTeardownRunnable(mProxy);
mProxy = nullptr; mProxy = nullptr;
if (NS_FAILED(mWorkerPrivate->DispatchToMainThread(runnable.forget()))) { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
if (NS_FAILED(workerPrivate->DispatchToMainThread(runnable.forget()))) {
NS_ERROR("Failed to dispatch teardown runnable!"); NS_ERROR("Failed to dispatch teardown runnable!");
} }
} else { } else {
@ -1638,8 +1639,7 @@ XMLHttpRequestWorker::ReleaseProxy(ReleaseType aType)
} }
// We need to make a sync call here. // We need to make a sync call here.
RefPtr<SyncTeardownRunnable> runnable = RefPtr<SyncTeardownRunnable> runnable = new SyncTeardownRunnable(mProxy);
new SyncTeardownRunnable(mWorkerPrivate, mProxy);
mProxy = nullptr; mProxy = nullptr;
IgnoredErrorResult forAssertionsOnly; IgnoredErrorResult forAssertionsOnly;
@ -1650,31 +1650,43 @@ XMLHttpRequestWorker::ReleaseProxy(ReleaseType aType)
} }
} }
void bool
XMLHttpRequestWorker::MaybePin(ErrorResult& aRv) XMLHttpRequestWorker::MaybePin()
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mRooted) { if (mWorkerRef) {
return; return true;
} }
if (!HoldWorker(mWorkerPrivate, Canceling)) { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
aRv.Throw(NS_ERROR_FAILURE); MOZ_ASSERT(workerPrivate);
return;
RefPtr<XMLHttpRequestWorker> self = this;
mWorkerRef =
StrongWorkerRef::Create(workerPrivate, "XMLHttpRequestWorker", [self] {
self->mCanceled = true;
self->ReleaseProxy(WorkerIsGoingAway);
});
if (NS_WARN_IF(!mWorkerRef)) {
return false;
} }
NS_ADDREF_THIS(); NS_ADDREF_THIS();
return true;
mRooted = true;
} }
void void
XMLHttpRequestWorker::MaybeDispatchPrematureAbortEvents(ErrorResult& aRv) XMLHttpRequestWorker::MaybeDispatchPrematureAbortEvents(ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
MOZ_ASSERT(mProxy); MOZ_ASSERT(mProxy);
// The worker can be closed during the dispatching of the following events.
// Let's keep the proxy alive.
RefPtr<Proxy> proxy = mProxy;
// Only send readystatechange event when state changed. // Only send readystatechange event when state changed.
bool isStateChanged = false; bool isStateChanged = false;
if ((mStateData.mReadyState == 1 && mStateData.mFlagSend) || if ((mStateData.mReadyState == 1 && mStateData.mFlagSend) ||
@ -1684,58 +1696,61 @@ XMLHttpRequestWorker::MaybeDispatchPrematureAbortEvents(ErrorResult& aRv)
mStateData.mReadyState = 4; mStateData.mReadyState = 4;
} }
if (mProxy->mSeenUploadLoadStart) { if (proxy->mSeenUploadLoadStart) {
MOZ_ASSERT(mUpload); MOZ_ASSERT(mUpload);
DispatchPrematureAbortEvent(mUpload, NS_LITERAL_STRING("abort"), true, DispatchPrematureAbortEvent(mUpload, proxy, NS_LITERAL_STRING("abort"),
aRv); true, aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return; return;
} }
DispatchPrematureAbortEvent(mUpload, NS_LITERAL_STRING("loadend"), true, DispatchPrematureAbortEvent(mUpload, proxy, NS_LITERAL_STRING("loadend"),
aRv); true, aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return; return;
} }
mProxy->mSeenUploadLoadStart = false; proxy->mSeenUploadLoadStart = false;
} }
if (mProxy->mSeenLoadStart) { if (proxy->mSeenLoadStart) {
if (isStateChanged) { if (isStateChanged) {
DispatchPrematureAbortEvent(this, NS_LITERAL_STRING("readystatechange"), DispatchPrematureAbortEvent(this, proxy,
false, aRv); NS_LITERAL_STRING("readystatechange"), false,
aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return; return;
} }
} }
DispatchPrematureAbortEvent(this, NS_LITERAL_STRING("abort"), false, aRv); DispatchPrematureAbortEvent(this, proxy, NS_LITERAL_STRING("abort"), false,
if (aRv.Failed()) {
return;
}
DispatchPrematureAbortEvent(this, NS_LITERAL_STRING("loadend"), false,
aRv); aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return; return;
} }
mProxy->mSeenLoadStart = false; DispatchPrematureAbortEvent(this, proxy, NS_LITERAL_STRING("loadend"),
false, aRv);
if (aRv.Failed()) {
return;
}
proxy->mSeenLoadStart = false;
} }
} }
void void
XMLHttpRequestWorker::DispatchPrematureAbortEvent(EventTarget* aTarget, XMLHttpRequestWorker::DispatchPrematureAbortEvent(EventTarget* aTarget,
Proxy* aProxy,
const nsAString& aEventType, const nsAString& aEventType,
bool aUploadTarget, bool aUploadTarget,
ErrorResult& aRv) ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
MOZ_ASSERT(aTarget); MOZ_ASSERT(aTarget);
if (!mProxy) { if (!aProxy) {
aRv.Throw(NS_ERROR_FAILURE); aRv.Throw(NS_ERROR_FAILURE);
return; return;
} }
@ -1750,14 +1765,14 @@ XMLHttpRequestWorker::DispatchPrematureAbortEvent(EventTarget* aTarget,
init.mBubbles = false; init.mBubbles = false;
init.mCancelable = false; init.mCancelable = false;
if (aUploadTarget) { if (aUploadTarget) {
init.mLengthComputable = mProxy->mLastUploadLengthComputable; init.mLengthComputable = aProxy->mLastUploadLengthComputable;
init.mLoaded = mProxy->mLastUploadLoaded; init.mLoaded = aProxy->mLastUploadLoaded;
init.mTotal = mProxy->mLastUploadTotal; init.mTotal = aProxy->mLastUploadTotal;
} }
else { else {
init.mLengthComputable = mProxy->mLastLengthComputable; init.mLengthComputable = aProxy->mLastLengthComputable;
init.mLoaded = mProxy->mLastLoaded; init.mLoaded = aProxy->mLastLoaded;
init.mTotal = mProxy->mLastTotal; init.mTotal = aProxy->mLastTotal;
} }
event = ProgressEvent::Constructor(aTarget, aEventType, init); event = ProgressEvent::Constructor(aTarget, aEventType, init);
} }
@ -1776,13 +1791,11 @@ XMLHttpRequestWorker::DispatchPrematureAbortEvent(EventTarget* aTarget,
void void
XMLHttpRequestWorker::Unpin() XMLHttpRequestWorker::Unpin()
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
MOZ_ASSERT(mRooted, "Mismatched calls to Unpin!"); MOZ_ASSERT(mWorkerRef, "Mismatched calls to Unpin!");
ReleaseWorker(); mWorkerRef = nullptr;
mRooted = false;
NS_RELEASE_THIS(); NS_RELEASE_THIS();
} }
@ -1792,7 +1805,7 @@ XMLHttpRequestWorker::SendInternal(SendRunnable* aRunnable,
ErrorResult& aRv) ErrorResult& aRv)
{ {
MOZ_ASSERT(aRunnable); MOZ_ASSERT(aRunnable);
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
// No send() calls when open is running. // No send() calls when open is running.
if (mProxy->mOpenCount) { if (mProxy->mOpenCount) {
@ -1802,18 +1815,21 @@ XMLHttpRequestWorker::SendInternal(SendRunnable* aRunnable,
bool hasUploadListeners = mUpload ? mUpload->HasListeners() : false; bool hasUploadListeners = mUpload ? mUpload->HasListeners() : false;
MaybePin(aRv); if (NS_WARN_IF(!MaybePin())) {
if (aRv.Failed()) { // Worker is shutting down. Let's ignore this send request.
return; return;
} }
AutoUnpinXHR autoUnpin(this); AutoUnpinXHR autoUnpin(this);
Maybe<AutoSyncLoopHolder> autoSyncLoop; Maybe<AutoSyncLoopHolder> autoSyncLoop;
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
nsCOMPtr<nsIEventTarget> syncLoopTarget; nsCOMPtr<nsIEventTarget> syncLoopTarget;
bool isSyncXHR = mProxy->mIsSyncXHR; bool isSyncXHR = mProxy->mIsSyncXHR;
if (isSyncXHR) { if (isSyncXHR) {
autoSyncLoop.emplace(mWorkerPrivate, Terminating); autoSyncLoop.emplace(workerPrivate, Terminating);
syncLoopTarget = autoSyncLoop->GetEventTarget(); syncLoopTarget = autoSyncLoop->GetEventTarget();
if (!syncLoopTarget) { if (!syncLoopTarget) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
@ -1832,7 +1848,7 @@ XMLHttpRequestWorker::SendInternal(SendRunnable* aRunnable,
if (aRv.Failed()) { if (aRv.Failed()) {
// Dispatch() may have spun the event loop and we may have already unrooted. // Dispatch() may have spun the event loop and we may have already unrooted.
// If so we don't want autoUnpin to try again. // If so we don't want autoUnpin to try again.
if (!mRooted) { if (!mWorkerRef) {
autoUnpin.Clear(); autoUnpin.Clear();
} }
return; return;
@ -1859,19 +1875,6 @@ XMLHttpRequestWorker::SendInternal(SendRunnable* aRunnable,
} }
} }
bool
XMLHttpRequestWorker::Notify(WorkerStatus aStatus)
{
mWorkerPrivate->AssertIsOnWorkerThread();
if (aStatus >= Canceling && !mCanceled) {
mCanceled = true;
ReleaseProxy(WorkerIsGoingAway);
}
return true;
}
void void
XMLHttpRequestWorker::Open(const nsACString& aMethod, XMLHttpRequestWorker::Open(const nsACString& aMethod,
const nsAString& aUrl, bool aAsync, const nsAString& aUrl, bool aAsync,
@ -1879,7 +1882,10 @@ XMLHttpRequestWorker::Open(const nsACString& aMethod,
const Optional<nsAString>& aPassword, const Optional<nsAString>& aPassword,
ErrorResult& aRv) ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -1888,19 +1894,19 @@ XMLHttpRequestWorker::Open(const nsACString& aMethod,
if (mProxy) { if (mProxy) {
MaybeDispatchPrematureAbortEvents(aRv); MaybeDispatchPrematureAbortEvents(aRv);
if (aRv.Failed()) { if (aRv.Failed() || !mProxy) {
return; return;
} }
} }
else { else {
mProxy = new Proxy(this, mWorkerPrivate->GetClientInfo(), mProxy = new Proxy(this, workerPrivate->GetClientInfo(),
mWorkerPrivate->GetController(), mMozAnon, mMozSystem); workerPrivate->GetController(), mMozAnon, mMozSystem);
} }
mProxy->mOuterEventStreamId++; mProxy->mOuterEventStreamId++;
RefPtr<OpenRunnable> runnable = RefPtr<OpenRunnable> runnable =
new OpenRunnable(mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword, new OpenRunnable(workerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
mBackgroundRequest, mWithCredentials, mBackgroundRequest, mWithCredentials,
mTimeout, mResponseType); mTimeout, mResponseType);
@ -1928,7 +1934,7 @@ void
XMLHttpRequestWorker::SetRequestHeader(const nsACString& aHeader, XMLHttpRequestWorker::SetRequestHeader(const nsACString& aHeader,
const nsACString& aValue, ErrorResult& aRv) const nsACString& aValue, ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -1941,14 +1947,14 @@ XMLHttpRequestWorker::SetRequestHeader(const nsACString& aHeader,
} }
RefPtr<SetRequestHeaderRunnable> runnable = RefPtr<SetRequestHeaderRunnable> runnable =
new SetRequestHeaderRunnable(mWorkerPrivate, mProxy, aHeader, aValue); new SetRequestHeaderRunnable(mProxy, aHeader, aValue);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
} }
void void
XMLHttpRequestWorker::SetTimeout(uint32_t aTimeout, ErrorResult& aRv) XMLHttpRequestWorker::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -1964,14 +1970,14 @@ XMLHttpRequestWorker::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
} }
RefPtr<SetTimeoutRunnable> runnable = RefPtr<SetTimeoutRunnable> runnable =
new SetTimeoutRunnable(mWorkerPrivate, mProxy, aTimeout); new SetTimeoutRunnable(mProxy, aTimeout);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
} }
void void
XMLHttpRequestWorker::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv) XMLHttpRequestWorker::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -1987,7 +1993,7 @@ XMLHttpRequestWorker::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv
} }
RefPtr<SetWithCredentialsRunnable> runnable = RefPtr<SetWithCredentialsRunnable> runnable =
new SetWithCredentialsRunnable(mWorkerPrivate, mProxy, aWithCredentials); new SetWithCredentialsRunnable(mProxy, aWithCredentials);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
} }
@ -1995,7 +2001,7 @@ void
XMLHttpRequestWorker::SetMozBackgroundRequest(bool aBackgroundRequest, XMLHttpRequestWorker::SetMozBackgroundRequest(bool aBackgroundRequest,
ErrorResult& aRv) ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2011,15 +2017,14 @@ XMLHttpRequestWorker::SetMozBackgroundRequest(bool aBackgroundRequest,
} }
RefPtr<SetBackgroundRequestRunnable> runnable = RefPtr<SetBackgroundRequestRunnable> runnable =
new SetBackgroundRequestRunnable(mWorkerPrivate, mProxy, new SetBackgroundRequestRunnable(mProxy, aBackgroundRequest);
aBackgroundRequest);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
} }
XMLHttpRequestUpload* XMLHttpRequestUpload*
XMLHttpRequestWorker::GetUpload(ErrorResult& aRv) XMLHttpRequestWorker::GetUpload(ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2043,7 +2048,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
const Nullable<DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>& aData, const Nullable<DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>& aData,
ErrorResult& aRv) ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2058,7 +2063,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
RefPtr<SendRunnable> sendRunnable; RefPtr<SendRunnable> sendRunnable;
if (aData.IsNull()) { if (aData.IsNull()) {
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, VoidString()); sendRunnable = new SendRunnable(mProxy, VoidString());
// Nothing to clone. // Nothing to clone.
} }
@ -2084,7 +2089,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
return; return;
} }
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); sendRunnable = new SendRunnable(mProxy, EmptyString());
sendRunnable->Write(aCx, value, aRv); sendRunnable->Write(aCx, value, aRv);
if (NS_WARN_IF(aRv.Failed())) { if (NS_WARN_IF(aRv.Failed())) {
@ -2093,7 +2098,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
} }
else if (aData.Value().IsArrayBuffer()) { else if (aData.Value().IsArrayBuffer()) {
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); sendRunnable = new SendRunnable(mProxy, EmptyString());
JS::Rooted<JS::Value> value(aCx); JS::Rooted<JS::Value> value(aCx);
value.setObject(*aData.Value().GetAsArrayBuffer().Obj()); value.setObject(*aData.Value().GetAsArrayBuffer().Obj());
@ -2114,7 +2119,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
return; return;
} }
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); sendRunnable = new SendRunnable(mProxy, EmptyString());
JS::Rooted<JS::Value> value(aCx); JS::Rooted<JS::Value> value(aCx);
value.setObject(*body.Obj()); value.setObject(*body.Obj());
@ -2133,7 +2138,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
return; return;
} }
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); sendRunnable = new SendRunnable(mProxy, EmptyString());
sendRunnable->Write(aCx, value, aRv); sendRunnable->Write(aCx, value, aRv);
if (NS_WARN_IF(aRv.Failed())) { if (NS_WARN_IF(aRv.Failed())) {
@ -2149,7 +2154,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
return; return;
} }
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); sendRunnable = new SendRunnable(mProxy, EmptyString());
sendRunnable->Write(aCx, value, aRv); sendRunnable->Write(aCx, value, aRv);
if (NS_WARN_IF(aRv.Failed())) { if (NS_WARN_IF(aRv.Failed())) {
@ -2158,8 +2163,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
} }
else if (aData.Value().IsUSVString()) { else if (aData.Value().IsUSVString()) {
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, sendRunnable = new SendRunnable(mProxy, aData.Value().GetAsUSVString());
aData.Value().GetAsUSVString());
// Nothing to clone. // Nothing to clone.
} }
@ -2170,7 +2174,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
void void
XMLHttpRequestWorker::Abort(ErrorResult& aRv) XMLHttpRequestWorker::Abort(ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2203,9 +2207,13 @@ XMLHttpRequestWorker::Abort(ErrorResult& aRv)
mStateData.mReadyState = 0; mStateData.mReadyState = 0;
} }
if (!mProxy) {
return;
}
mProxy->mOuterEventStreamId++; mProxy->mOuterEventStreamId++;
RefPtr<AbortRunnable> runnable = new AbortRunnable(mWorkerPrivate, mProxy); RefPtr<AbortRunnable> runnable = new AbortRunnable(mProxy);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
} }
@ -2213,7 +2221,7 @@ void
XMLHttpRequestWorker::GetResponseHeader(const nsACString& aHeader, XMLHttpRequestWorker::GetResponseHeader(const nsACString& aHeader,
nsACString& aResponseHeader, ErrorResult& aRv) nsACString& aResponseHeader, ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2227,8 +2235,7 @@ XMLHttpRequestWorker::GetResponseHeader(const nsACString& aHeader,
nsCString responseHeader; nsCString responseHeader;
RefPtr<GetResponseHeaderRunnable> runnable = RefPtr<GetResponseHeaderRunnable> runnable =
new GetResponseHeaderRunnable(mWorkerPrivate, mProxy, aHeader, new GetResponseHeaderRunnable(mProxy, aHeader, responseHeader);
responseHeader);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return; return;
@ -2240,7 +2247,7 @@ void
XMLHttpRequestWorker::GetAllResponseHeaders(nsACString& aResponseHeaders, XMLHttpRequestWorker::GetAllResponseHeaders(nsACString& aResponseHeaders,
ErrorResult& aRv) ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2254,7 +2261,7 @@ XMLHttpRequestWorker::GetAllResponseHeaders(nsACString& aResponseHeaders,
nsCString responseHeaders; nsCString responseHeaders;
RefPtr<GetAllResponseHeadersRunnable> runnable = RefPtr<GetAllResponseHeadersRunnable> runnable =
new GetAllResponseHeadersRunnable(mWorkerPrivate, mProxy, responseHeaders); new GetAllResponseHeadersRunnable(mProxy, responseHeaders);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return; return;
@ -2266,7 +2273,7 @@ XMLHttpRequestWorker::GetAllResponseHeaders(nsACString& aResponseHeaders,
void void
XMLHttpRequestWorker::OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv) XMLHttpRequestWorker::OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2286,7 +2293,7 @@ XMLHttpRequestWorker::OverrideMimeType(const nsAString& aMimeType, ErrorResult&
} }
RefPtr<OverrideMimeTypeRunnable> runnable = RefPtr<OverrideMimeTypeRunnable> runnable =
new OverrideMimeTypeRunnable(mWorkerPrivate, mProxy, aMimeType); new OverrideMimeTypeRunnable(mProxy, aMimeType);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
} }
@ -2294,7 +2301,7 @@ void
XMLHttpRequestWorker::SetResponseType(XMLHttpRequestResponseType aResponseType, XMLHttpRequestWorker::SetResponseType(XMLHttpRequestResponseType aResponseType,
ErrorResult& aRv) ErrorResult& aRv)
{ {
mWorkerPrivate->AssertIsOnWorkerThread(); NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (mCanceled) { if (mCanceled) {
aRv.ThrowUncatchableException(); aRv.ThrowUncatchableException();
@ -2322,7 +2329,7 @@ XMLHttpRequestWorker::SetResponseType(XMLHttpRequestResponseType aResponseType,
} }
RefPtr<SetResponseTypeRunnable> runnable = RefPtr<SetResponseTypeRunnable> runnable =
new SetResponseTypeRunnable(mWorkerPrivate, mProxy, aResponseType); new SetResponseTypeRunnable(mProxy, aResponseType);
runnable->Dispatch(Terminating, aRv); runnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return; return;
@ -2332,23 +2339,23 @@ XMLHttpRequestWorker::SetResponseType(XMLHttpRequestResponseType aResponseType,
} }
void void
XMLHttpRequestWorker::GetResponse(JSContext* /* unused */, XMLHttpRequestWorker::GetResponse(JSContext* aCx,
JS::MutableHandle<JS::Value> aResponse, JS::MutableHandle<JS::Value> aResponse,
ErrorResult& aRv) ErrorResult& aRv)
{ {
NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (NS_SUCCEEDED(mStateData.mResponseTextResult) && if (NS_SUCCEEDED(mStateData.mResponseTextResult) &&
mStateData.mResponse.isUndefined()) { mStateData.mResponse.isUndefined()) {
MOZ_ASSERT(NS_SUCCEEDED(mStateData.mResponseResult)); MOZ_ASSERT(NS_SUCCEEDED(mStateData.mResponseResult));
if (mStateData.mResponseText.IsEmpty()) { if (mStateData.mResponseText.IsEmpty()) {
mStateData.mResponse = mStateData.mResponse = JS_GetEmptyStringValue(aCx);
JS_GetEmptyStringValue(mWorkerPrivate->GetJSContext());
} else { } else {
XMLHttpRequestStringSnapshotReaderHelper helper(mStateData.mResponseText); XMLHttpRequestStringSnapshotReaderHelper helper(mStateData.mResponseText);
JSString* str = JSString* str =
JS_NewUCStringCopyN(mWorkerPrivate->GetJSContext(), JS_NewUCStringCopyN(aCx, helper.Buffer(), helper.Length());
helper.Buffer(), helper.Length());
if (!str) { if (!str) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
@ -2378,15 +2385,17 @@ XMLHttpRequestWorker::GetResponseText(DOMString& aResponseText, ErrorResult& aRv
} }
void void
XMLHttpRequestWorker::UpdateState(const StateData& aStateData, XMLHttpRequestWorker::UpdateState(JSContext* aCx,
const StateData& aStateData,
bool aUseCachedArrayBufferResponse) bool aUseCachedArrayBufferResponse)
{ {
NS_ASSERT_OWNINGTHREAD(XMLHttpRequestWorker);
if (aUseCachedArrayBufferResponse) { if (aUseCachedArrayBufferResponse) {
MOZ_ASSERT(mStateData.mResponse.isObject() && MOZ_ASSERT(mStateData.mResponse.isObject() &&
JS_IsArrayBufferObject(&mStateData.mResponse.toObject())); JS_IsArrayBufferObject(&mStateData.mResponse.toObject()));
JS::Rooted<JS::Value> response(mWorkerPrivate->GetJSContext(), JS::Rooted<JS::Value> response(aCx, mStateData.mResponse);
mStateData.mResponse);
mStateData = aStateData; mStateData = aStateData;
mStateData.mResponse = response; mStateData.mResponse = response;
} }

Просмотреть файл

@ -10,7 +10,6 @@
#include "XMLHttpRequest.h" #include "XMLHttpRequest.h"
#include "XMLHttpRequestString.h" #include "XMLHttpRequestString.h"
#include "mozilla/dom/TypedArray.h" #include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/WorkerHolder.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -18,10 +17,9 @@ namespace dom {
class Proxy; class Proxy;
class SendRunnable; class SendRunnable;
class DOMString; class DOMString;
class WorkerPrivate; class StrongWorkerRef;
class XMLHttpRequestWorker final : public XMLHttpRequest, class XMLHttpRequestWorker final : public XMLHttpRequest
public WorkerHolder
{ {
public: public:
struct StateData struct StateData
@ -48,14 +46,13 @@ public:
private: private:
RefPtr<XMLHttpRequestUpload> mUpload; RefPtr<XMLHttpRequestUpload> mUpload;
WorkerPrivate* mWorkerPrivate; RefPtr<StrongWorkerRef> mWorkerRef;
RefPtr<Proxy> mProxy; RefPtr<Proxy> mProxy;
XMLHttpRequestResponseType mResponseType; XMLHttpRequestResponseType mResponseType;
StateData mStateData; StateData mStateData;
uint32_t mTimeout; uint32_t mTimeout;
bool mRooted;
bool mBackgroundRequest; bool mBackgroundRequest;
bool mWithCredentials; bool mWithCredentials;
bool mCanceled; bool mCanceled;
@ -77,9 +74,6 @@ public:
void void
Unpin(); Unpin();
bool
Notify(WorkerStatus aStatus) override;
virtual uint16_t virtual uint16_t
ReadyState() const override ReadyState() const override
{ {
@ -251,7 +245,8 @@ public:
} }
void void
UpdateState(const StateData& aStateData, bool aUseCachedArrayBufferResponse); UpdateState(JSContext* aCx, const StateData& aStateData,
bool aUseCachedArrayBufferResponse);
void void
NullResponseText() NullResponseText()
@ -278,11 +273,11 @@ public:
bool bool
SendInProgress() const SendInProgress() const
{ {
return mRooted; return !!mWorkerRef;
} }
private: private:
explicit XMLHttpRequestWorker(WorkerPrivate* aWorkerPrivate); XMLHttpRequestWorker();
~XMLHttpRequestWorker(); ~XMLHttpRequestWorker();
enum ReleaseType { Default, XHRIsGoingAway, WorkerIsGoingAway }; enum ReleaseType { Default, XHRIsGoingAway, WorkerIsGoingAway };
@ -290,14 +285,14 @@ private:
void void
ReleaseProxy(ReleaseType aType = Default); ReleaseProxy(ReleaseType aType = Default);
void bool
MaybePin(ErrorResult& aRv); MaybePin();
void void
MaybeDispatchPrematureAbortEvents(ErrorResult& aRv); MaybeDispatchPrematureAbortEvents(ErrorResult& aRv);
void void
DispatchPrematureAbortEvent(EventTarget* aTarget, DispatchPrematureAbortEvent(EventTarget* aTarget, Proxy* aProxy,
const nsAString& aEventType, bool aUploadTarget, const nsAString& aEventType, bool aUploadTarget,
ErrorResult& aRv); ErrorResult& aRv);

Просмотреть файл

@ -366430,6 +366430,12 @@
{} {}
] ]
], ],
"xhr/xmlhttprequest-closing-worker.html": [
[
"/xhr/xmlhttprequest-closing-worker.html",
{}
]
],
"xhr/xmlhttprequest-eventtarget.htm": [ "xhr/xmlhttprequest-eventtarget.htm": [
[ [
"/xhr/xmlhttprequest-eventtarget.htm", "/xhr/xmlhttprequest-eventtarget.htm",
@ -601467,6 +601473,10 @@
"a67d1876d6245fb94d60a937b633c87c51a04d21", "a67d1876d6245fb94d60a937b633c87c51a04d21",
"testharness" "testharness"
], ],
"xhr/xmlhttprequest-closing-worker.html": [
"e3ceea784d45a3f89755cad4f60e11fe687b8e5a",
"testharness"
],
"xhr/xmlhttprequest-eventtarget.htm": [ "xhr/xmlhttprequest-eventtarget.htm": [
"40c886f79399108db3ded8a23848905dcf9e0862", "40c886f79399108db3ded8a23848905dcf9e0862",
"testharness" "testharness"

Просмотреть файл

@ -0,0 +1,32 @@
<!--
self.close()
var xhr = new XMLHttpRequest();
xhr.open("GET", "/resources/testharness.js");
xhr.send(42);
postMessage(xhr.readyState)
/*-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>XHR used when worker is closing itself</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<div id="log"></div>
<script>
var test = async_test();
test.step(function() {
var worker = new Worker('#')
worker.onmessage = function(e) {
test.step(function() {
assert_equals(e.data, XMLHttpRequest.OPENED, 'XHR.readyState')
})
test.done()
}
})
</script>
</body>
</html>
<!--*/ //-->