Merge commit '65d6aee9e0d586b5a069c6f816e7fe3d18cc381e' into pm27100-vc2010

This commit is contained in:
2024-07-23 16:55:09 +08:00
119 changed files with 1551 additions and 902 deletions
+2 -1
View File
@@ -14213,7 +14213,8 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
}
}
return swm->DispatchFetchEvent(doc, aChannel);
bool isReload = mLoadType & LOAD_CMD_RELOAD;
return swm->DispatchFetchEvent(doc, aChannel, isReload);
}
NS_IMETHODIMP
+1 -1
View File
@@ -1406,7 +1406,7 @@ nsSHistory::RemoveEntries(nsTArray<uint64_t>& aIDs, int32_t aStartIndex)
--index;
}
if (didRemove && mRootDocShell) {
nsRefPtr<nsIRunnable> ev =
nsCOMPtr<nsIRunnable> ev =
NS_NewRunnableMethod(static_cast<nsDocShell*>(mRootDocShell),
&nsDocShell::FireDummyOnLocationChange);
NS_DispatchToCurrentThread(ev);
+2 -2
View File
@@ -4403,7 +4403,7 @@ nsDocument::SetStyleSheetApplicableState(nsIStyleSheet* aSheet,
}
if (!mSSApplicableStateNotificationPending) {
nsRefPtr<nsIRunnable> notification = NS_NewRunnableMethod(this,
nsCOMPtr<nsIRunnable> notification = NS_NewRunnableMethod(this,
&nsDocument::NotifyStyleSheetApplicableStateChanged);
mSSApplicableStateNotificationPending =
NS_SUCCEEDED(NS_DispatchToCurrentThread(notification));
@@ -5206,7 +5206,7 @@ nsDocument::UnblockDOMContentLoaded()
MOZ_ASSERT(mReadyState == READYSTATE_INTERACTIVE);
if (!mSynchronousDOMContentLoaded) {
nsRefPtr<nsIRunnable> ev =
nsCOMPtr<nsIRunnable> ev =
NS_NewRunnableMethod(this, &nsDocument::DispatchContentLoadedEvents);
NS_DispatchToCurrentThread(ev);
} else {
+1 -1
View File
@@ -2360,7 +2360,7 @@ nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
}
if (mChildMessageManager) {
nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToChild(aCx, this, aMessage,
nsCOMPtr<nsIRunnable> ev = new nsAsyncMessageToChild(aCx, this, aMessage,
aData, aCpows,
aPrincipal);
NS_DispatchToCurrentThread(ev);
+1 -1
View File
@@ -1742,7 +1742,7 @@ public:
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override
{
nsRefPtr<nsIRunnable> ev =
nsCOMPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessChild(aCx, aMessage, aData, aCpows,
aPrincipal);
NS_DispatchToCurrentThread(ev);
+1 -1
View File
@@ -9046,7 +9046,7 @@ private:
void
nsGlobalWindow::NotifyWindowIDDestroyed(const char* aTopic)
{
nsRefPtr<nsIRunnable> runnable = new WindowDestroyedEvent(this, mWindowID, aTopic);
nsCOMPtr<nsIRunnable> runnable = new WindowDestroyedEvent(this, mWindowID, aTopic);
nsresult rv = NS_DispatchToCurrentThread(runnable);
if (NS_SUCCEEDED(rv)) {
mNotifiedIDDestroyed = true;
+1 -1
View File
@@ -162,7 +162,7 @@ FetchPut::DispatchToMainThread()
{
MOZ_ASSERT(!mRunnable);
nsRefPtr<nsIRunnable> runnable = new Runnable(this);
nsCOMPtr<nsIRunnable> runnable = new Runnable(this);
nsresult rv = NS_DispatchToMainThread(runnable, nsIThread::DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
+25 -30
View File
@@ -229,7 +229,7 @@ TypeUtils::ToPCacheResponseWithoutBody(PCacheResponse& aOut,
aOut.status() = aIn.GetStatus();
aOut.statusText() = aIn.GetStatusText();
nsRefPtr<InternalHeaders> headers = aIn.Headers();
nsRefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders();
MOZ_ASSERT(headers);
headers->GetPHeaders(aOut.headers());
aOut.headersGuard() = headers->Guard();
@@ -279,37 +279,14 @@ TypeUtils::ToPCacheQueryParams(PCacheQueryParams& aOut,
already_AddRefed<Response>
TypeUtils::ToResponse(const PCacheResponse& aIn)
{
nsRefPtr<InternalResponse> ir;
switch (aIn.type())
{
case ResponseType::Error:
ir = InternalResponse::NetworkError();
break;
case ResponseType::Opaque:
ir = InternalResponse::OpaqueResponse();
break;
case ResponseType::Default:
ir = new InternalResponse(aIn.status(), aIn.statusText());
break;
case ResponseType::Basic:
{
nsRefPtr<InternalResponse> inner = new InternalResponse(aIn.status(),
aIn.statusText());
ir = InternalResponse::BasicResponse(inner);
break;
}
case ResponseType::Cors:
{
nsRefPtr<InternalResponse> inner = new InternalResponse(aIn.status(),
aIn.statusText());
ir = InternalResponse::CORSResponse(inner);
break;
}
default:
MOZ_CRASH("Unexpected ResponseType!");
if (aIn.type() == ResponseType::Error) {
nsRefPtr<InternalResponse> error = InternalResponse::NetworkError();
nsRefPtr<Response> r = new Response(GetGlobalObject(), error);
return r.forget();
}
MOZ_ASSERT(ir);
nsRefPtr<InternalResponse> ir = new InternalResponse(aIn.status(),
aIn.statusText());
ir->SetUrl(NS_ConvertUTF16toUTF8(aIn.url()));
nsRefPtr<InternalHeaders> internalHeaders =
@@ -325,6 +302,24 @@ TypeUtils::ToResponse(const PCacheResponse& aIn)
nsCOMPtr<nsIInputStream> stream = ReadStream::Create(aIn.body());
ir->SetBody(stream);
switch (aIn.type())
{
case ResponseType::Default:
break;
case ResponseType::Opaque:
ir = ir->OpaqueResponse();
break;
case ResponseType::Basic:
ir = ir->BasicResponse();
break;
case ResponseType::Cors:
ir = ir->CORSResponse();
break;
default:
MOZ_CRASH("Unexpected ResponseType!");
}
MOZ_ASSERT(ir);
nsRefPtr<Response> ref = new Response(GetGlobalObject(), ir);
return ref.forget();
}
+1 -2
View File
@@ -13,8 +13,7 @@
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
"set": [["dom.caches.enabled", true],
["dom.fetch.enabled", true]]
"set": [["dom.caches.enabled", true]]
}, function() {
var frame = document.getElementById("frame");
frame.src = "test_cache_frame.html";
+1 -1
View File
@@ -24,7 +24,7 @@ static const TrackID TRACK_VIDEO = 2;
void
FakeMediaStreamGraph::DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable)
{
nsRefPtr<nsIRunnable> task = aRunnable;
nsCOMPtr<nsIRunnable> task = aRunnable;
NS_DispatchToMainThread(task);
}
+12 -1
View File
@@ -13,6 +13,9 @@
#include "jsapi.h"
#include "nsGlobalWindow.h" // So we can assign an nsGlobalWindow* to mWindowSource
#include "ServiceWorker.h"
#include "ServiceWorkerClient.h"
namespace mozilla {
namespace dom {
@@ -103,12 +106,14 @@ MessageEvent::GetSource(nsIDOMWindow** aSource)
}
void
MessageEvent::GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const
MessageEvent::GetSource(Nullable<OwningWindowProxyOrMessagePortOrClient>& aValue) const
{
if (mWindowSource) {
aValue.SetValue().SetAsWindowProxy() = mWindowSource;
} else if (mPortSource) {
aValue.SetValue().SetAsMessagePort() = mPortSource;
} else if (mClientSource) {
aValue.SetValue().SetAsClient() = mClientSource;
}
}
@@ -206,6 +211,12 @@ MessageEvent::SetSource(mozilla::dom::MessagePort* aPort)
mPortSource = aPort;
}
void
MessageEvent::SetSource(mozilla::dom::workers::ServiceWorkerClient* aClient)
{
mClientSource = aClient;
}
} // namespace dom
} // namespace mozilla
+11 -2
View File
@@ -15,7 +15,13 @@ namespace mozilla {
namespace dom {
struct MessageEventInit;
class OwningWindowProxyOrMessagePort;
class OwningWindowProxyOrMessagePortOrClient;
namespace workers {
class ServiceWorkerClient;
}
/**
* Implements the MessageEvent event, used for cross-document messaging and
@@ -45,7 +51,7 @@ public:
void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData,
ErrorResult& aRv);
void GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const;
void GetSource(Nullable<OwningWindowProxyOrMessagePortOrClient>& aValue) const;
MessagePortList* GetPorts()
{
@@ -57,6 +63,8 @@ public:
// Non WebIDL methods
void SetSource(mozilla::dom::MessagePort* aPort);
void SetSource(workers::ServiceWorkerClient* aClient);
void SetSource(nsPIDOMWindow* aWindow)
{
mWindowSource = aWindow;
@@ -83,6 +91,7 @@ private:
nsString mLastEventId;
nsCOMPtr<nsIDOMWindow> mWindowSource;
nsRefPtr<MessagePortBase> mPortSource;
nsRefPtr<workers::ServiceWorkerClient> mClientSource;
nsRefPtr<MessagePortList> mPorts;
};
+3 -3
View File
@@ -548,13 +548,13 @@ FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse)
nsRefPtr<InternalResponse> filteredResponse;
switch (mRequest->GetResponseTainting()) {
case InternalRequest::RESPONSETAINT_BASIC:
filteredResponse = InternalResponse::BasicResponse(aResponse);
filteredResponse = aResponse->BasicResponse();
break;
case InternalRequest::RESPONSETAINT_CORS:
filteredResponse = InternalResponse::CORSResponse(aResponse);
filteredResponse = aResponse->CORSResponse();
break;
case InternalRequest::RESPONSETAINT_OPAQUE:
filteredResponse = InternalResponse::OpaqueResponse();
filteredResponse = aResponse->OpaqueResponse();
break;
default:
MOZ_CRASH("Unexpected case");
-26
View File
@@ -22,32 +22,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Headers)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
// static
bool
Headers::PrefEnabled(JSContext* aCx, JSObject* aObj)
{
using mozilla::dom::workers::WorkerPrivate;
using mozilla::dom::workers::GetWorkerPrivateFromContext;
if (NS_IsMainThread()) {
static bool sPrefCacheInit = false;
static bool sPrefEnabled = false;
if (sPrefCacheInit) {
return sPrefEnabled;
}
Preferences::AddBoolVarCache(&sPrefEnabled, "dom.fetch.enabled");
sPrefCacheInit = true;
return sPrefEnabled;
}
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
if (!workerPrivate) {
return false;
}
return workerPrivate->DOMFetchEnabled();
}
// static
already_AddRefed<Headers>
Headers::Constructor(const GlobalObject& aGlobal,
+17 -27
View File
@@ -23,25 +23,17 @@ InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusTe
{
}
// Headers are not copied since BasicResponse and CORSResponse both need custom
// header handling. Body is not copied as it cannot be shared directly.
InternalResponse::InternalResponse(const InternalResponse& aOther)
: mType(aOther.mType)
, mTerminationReason(aOther.mTerminationReason)
, mURL(aOther.mURL)
, mFinalURL(aOther.mFinalURL)
, mStatus(aOther.mStatus)
, mStatusText(aOther.mStatusText)
, mContentType(aOther.mContentType)
, mSecurityInfo(aOther.mSecurityInfo)
{
}
already_AddRefed<InternalResponse>
InternalResponse::Clone()
{
nsRefPtr<InternalResponse> clone = new InternalResponse(*this);
nsRefPtr<InternalResponse> clone = CreateIncompleteCopy();
clone->mHeaders = new InternalHeaders(*mHeaders);
if (mWrappedResponse) {
clone->mWrappedResponse = mWrappedResponse->Clone();
MOZ_ASSERT(!mBody);
return clone.forget();
}
if (!mBody) {
return clone.forget();
@@ -62,27 +54,25 @@ InternalResponse::Clone()
return clone.forget();
}
// static
already_AddRefed<InternalResponse>
InternalResponse::BasicResponse(InternalResponse* aInner)
InternalResponse::BasicResponse()
{
MOZ_ASSERT(aInner);
nsRefPtr<InternalResponse> basic = new InternalResponse(*aInner);
MOZ_ASSERT(!mWrappedResponse, "Can't BasicResponse a already wrapped response");
nsRefPtr<InternalResponse> basic = CreateIncompleteCopy();
basic->mType = ResponseType::Basic;
basic->mHeaders = InternalHeaders::BasicHeaders(aInner->mHeaders);
basic->mBody.swap(aInner->mBody);
basic->mHeaders = InternalHeaders::BasicHeaders(Headers());
basic->mWrappedResponse = this;
return basic.forget();
}
// static
already_AddRefed<InternalResponse>
InternalResponse::CORSResponse(InternalResponse* aInner)
InternalResponse::CORSResponse()
{
MOZ_ASSERT(aInner);
nsRefPtr<InternalResponse> cors = new InternalResponse(*aInner);
MOZ_ASSERT(!mWrappedResponse, "Can't CORSResponse a already wrapped response");
nsRefPtr<InternalResponse> cors = CreateIncompleteCopy();
cors->mType = ResponseType::Cors;
cors->mHeaders = InternalHeaders::CORSHeaders(aInner->mHeaders);
cors->mBody.swap(aInner->mBody);
cors->mHeaders = InternalHeaders::CORSHeaders(Headers());
cors->mWrappedResponse = this;
return cors.forget();
}
+60 -13
View File
@@ -35,27 +35,34 @@ public:
return response.forget();
}
static already_AddRefed<InternalResponse>
already_AddRefed<InternalResponse>
OpaqueResponse()
{
MOZ_ASSERT(!mWrappedResponse, "Can't OpaqueResponse a already wrapped response");
nsRefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
response->mType = ResponseType::Opaque;
response->mTerminationReason = mTerminationReason;
response->mURL = mURL;
response->mFinalURL = mFinalURL;
response->mSecurityInfo = mSecurityInfo;
response->mWrappedResponse = this;
return response.forget();
}
// DO NOT use the inner response after filtering it since the filtered
// response will adopt the inner response's body.
static already_AddRefed<InternalResponse>
BasicResponse(InternalResponse* aInner);
already_AddRefed<InternalResponse>
BasicResponse();
// DO NOT use the inner response after filtering it since the filtered
// response will adopt the inner response's body.
static already_AddRefed<InternalResponse>
CORSResponse(InternalResponse* aInner);
already_AddRefed<InternalResponse>
CORSResponse();
ResponseType
Type() const
{
MOZ_ASSERT_IF(mType == ResponseType::Error, !mWrappedResponse);
MOZ_ASSERT_IF(mType == ResponseType::Default, !mWrappedResponse);
MOZ_ASSERT_IF(mType == ResponseType::Basic, mWrappedResponse);
MOZ_ASSERT_IF(mType == ResponseType::Cors, mWrappedResponse);
MOZ_ASSERT_IF(mType == ResponseType::Opaque, mWrappedResponse);
return mType;
}
@@ -108,9 +115,28 @@ public:
return mHeaders;
}
InternalHeaders*
UnfilteredHeaders()
{
if (mWrappedResponse) {
return mWrappedResponse->Headers();
};
return Headers();
}
void
GetBody(nsIInputStream** aStream)
{
if (Type() == ResponseType::Opaque) {
*aStream = nullptr;
return;
}
if (mWrappedResponse) {
MOZ_ASSERT(!mBody);
return mWrappedResponse->GetBody(aStream);
}
nsCOMPtr<nsIInputStream> stream = mBody;
stream.forget(aStream);
}
@@ -118,6 +144,9 @@ public:
void
SetBody(nsIInputStream* aBody)
{
if (mWrappedResponse) {
return mWrappedResponse->SetBody(aBody);
}
// A request's body may not be reset once set.
MOZ_ASSERT(!mBody);
mBody = aBody;
@@ -139,9 +168,22 @@ private:
~InternalResponse()
{ }
// Used to create filtered and cloned responses.
// Does not copy headers or body stream.
explicit InternalResponse(const InternalResponse& aOther);
explicit InternalResponse(const InternalResponse& aOther) = delete;
InternalResponse& operator=(const InternalResponse&) = delete;
// Returns an instance of InternalResponse which is a copy of this
// InternalResponse, except headers, body and wrapped response (if any) which
// are left uninitialized. Used for cloning and filtering.
already_AddRefed<InternalResponse> CreateIncompleteCopy()
{
nsRefPtr<InternalResponse> copy = new InternalResponse(mStatus, mStatusText);
copy->mType = mType;
copy->mTerminationReason = mTerminationReason;
copy->mURL = mURL;
copy->mFinalURL = mFinalURL;
copy->mSecurityInfo = mSecurityInfo;
return copy.forget();
}
ResponseType mType;
nsCString mTerminationReason;
@@ -151,8 +193,13 @@ private:
const nsCString mStatusText;
nsRefPtr<InternalHeaders> mHeaders;
nsCOMPtr<nsIInputStream> mBody;
nsCString mContentType;
nsCString mSecurityInfo;
// For filtered responses.
// Cache, and SW interception should always serialize/access the underlying
// unfiltered headers and when deserializing, create an InternalResponse
// with the unfiltered headers followed by wrapping it.
nsRefPtr<InternalResponse> mWrappedResponse;
};
} // namespace dom
@@ -19,7 +19,7 @@ interface nsIServiceWorkerUnregisterCallback : nsISupports
[noscript] void UnregisterFailed();
};
[builtinclass, uuid(464882c8-81c0-4620-b9c4-44c12085b65b)]
[builtinclass, uuid(e4c8baa5-237a-4bf6-82d4-ea06eb4b76ba)]
interface nsIServiceWorkerManager : nsISupports
{
/**
@@ -30,7 +30,7 @@ interface nsIServiceWorkerManager : nsISupports
*
* Returns a Promise.
*/
nsISupports register(in nsIDOMWindow aWindow, in DOMString aScope, in DOMString aScriptURI);
nsISupports register(in nsIDOMWindow aWindow, in nsIURI aScope, in nsIURI aScriptURI);
/**
* Unregister an existing ServiceWorker registration for `aScope`.
@@ -59,7 +59,8 @@ interface nsIServiceWorkerManager : nsISupports
bool isControlled(in nsIDocument aDocument);
// Cause a fetch event to be dispatched to the worker global associated with the given document.
void dispatchFetchEvent(in nsIDocument aDoc, in nsIInterceptedChannel aChannel);
void dispatchFetchEvent(in nsIDocument aDoc, in nsIInterceptedChannel aChannel,
in boolean aIsReload);
// aTarget MUST be a ServiceWorkerRegistration.
[noscript] void AddRegistrationEventListener(in DOMString aScope, in nsIDOMEventTarget aTarget);
+2 -2
View File
@@ -280,7 +280,7 @@ class MediaRecorder::Session: public nsIObserver
LOG(PR_LOG_DEBUG, ("Session.ExtractRunnable shutdown = %d", mSession->mEncoder->IsShutdown()));
if (!mSession->mEncoder->IsShutdown()) {
mSession->Extract(false);
nsRefPtr<nsIRunnable> event = new ExtractRunnable(mSession);
nsCOMPtr<nsIRunnable> event = new ExtractRunnable(mSession);
if (NS_FAILED(NS_DispatchToCurrentThread(event))) {
NS_WARNING("Failed to dispatch ExtractRunnable to encoder thread");
}
@@ -634,7 +634,7 @@ private:
// shutdown notification and stop Read Thread.
nsContentUtils::RegisterShutdownObserver(this);
nsRefPtr<nsIRunnable> event = new ExtractRunnable(this);
nsCOMPtr<nsIRunnable> event = new ExtractRunnable(this);
if (NS_FAILED(mReadThread->Dispatch(event, NS_DISPATCH_NORMAL))) {
NS_WARNING("Failed to dispatch ExtractRunnable at beginning");
}
+2 -2
View File
@@ -2236,7 +2236,7 @@ MediaStream::RemoveListener(MediaStreamListener* aListener)
}
void
MediaStream::RunAfterPendingUpdates(nsRefPtr<nsIRunnable> aRunnable)
MediaStream::RunAfterPendingUpdates(nsCOMPtr<nsIRunnable> aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MediaStreamGraphImpl* graph = GraphImpl();
@@ -2266,7 +2266,7 @@ MediaStream::RunAfterPendingUpdates(nsRefPtr<nsIRunnable> aRunnable)
NS_DispatchToCurrentThread(mRunnable);
}
private:
nsRefPtr<nsIRunnable> mRunnable;
nsCOMPtr<nsIRunnable> mRunnable;
};
graph->AppendMessage(new Message(this, aRunnable.forget()));
+1 -1
View File
@@ -397,7 +397,7 @@ public:
*
* Main thread only.
*/
void RunAfterPendingUpdates(nsRefPtr<nsIRunnable> aRunnable);
void RunAfterPendingUpdates(nsCOMPtr<nsIRunnable> aRunnable);
// Signal that the client is done with this MediaStream. It will be deleted later.
virtual void Destroy();
+2 -2
View File
@@ -625,7 +625,7 @@ GoannaMediaPluginService::AsyncShutdownComplete(GMPParent* aParent)
if (mAsyncShutdownPlugins.IsEmpty() && mShuttingDownOnGMPThread) {
// The main thread may be waiting for async shutdown of plugins,
// which has completed. Break the main thread out of its waiting loop.
nsRefPtr<nsIRunnable> task(NS_NewRunnableMethod(
nsCOMPtr<nsIRunnable> task(NS_NewRunnableMethod(
this, &GoannaMediaPluginService::SetAsyncShutdownComplete));
NS_DispatchToMainThread(task);
}
@@ -659,7 +659,7 @@ GoannaMediaPluginService::UnloadPlugins()
}
if (mAsyncShutdownPlugins.IsEmpty()) {
nsRefPtr<nsIRunnable> task(NS_NewRunnableMethod(
nsCOMPtr<nsIRunnable> task(NS_NewRunnableMethod(
this, &GoannaMediaPluginService::SetAsyncShutdownComplete));
NS_DispatchToMainThread(task);
}
+5 -5
View File
@@ -221,8 +221,8 @@ public:
private:
virtual ~GMPShutdownObserver() {}
nsRefPtr<nsIRunnable> mShutdownTask;
nsRefPtr<nsIRunnable> mContinuation;
nsCOMPtr<nsIRunnable> mShutdownTask;
nsCOMPtr<nsIRunnable> mContinuation;
const nsString mNodeId;
};
@@ -290,7 +290,7 @@ public:
private:
virtual ~ClearGMPStorageTask() {}
nsRefPtr<nsIRunnable> mContinuation;
nsCOMPtr<nsIRunnable> mContinuation;
nsCOMPtr<nsIThread> mTarget;
const PRTime mSince;
};
@@ -1093,7 +1093,7 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
bool matches = mExpected[0].mMessage.Equals(msg);
EXPECT_STREQ(mExpected[0].mMessage.get(), msg.get());
if (mExpected.Length() > 0 && matches) {
nsRefPtr<nsIRunnable> continuation = mExpected[0].mContinuation;
nsCOMPtr<nsIRunnable> continuation = mExpected[0].mContinuation;
mExpected.RemoveElementAt(0);
if (continuation) {
NS_DispatchToCurrentThread(continuation);
@@ -1134,7 +1134,7 @@ private:
, mContinuation(aContinuation)
{}
nsCString mMessage;
nsRefPtr<nsIRunnable> mContinuation;
nsCOMPtr<nsIRunnable> mContinuation;
};
nsTArray<ExpectedMessage> mExpected;
+1 -1
View File
@@ -529,7 +529,7 @@ MediaSource::QueueInitializationEvent()
}
mFirstSourceBufferInitialized = true;
MSE_DEBUG("");
nsRefPtr<nsIRunnable> task =
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableMethod(this, &MediaSource::InitializationEvent);
NS_DispatchToMainThread(task);
}
@@ -39,7 +39,7 @@ MediaDataDecoderProxy::Input(MediaRawData* aSample)
MOZ_ASSERT(!IsOnProxyThread());
MOZ_ASSERT(!mIsShutdown);
nsRefPtr<nsIRunnable> task(new InputTask(mProxyDecoder, aSample));
nsCOMPtr<nsIRunnable> task(new InputTask(mProxyDecoder, aSample));
nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
@@ -54,7 +54,7 @@ MediaDataDecoderProxy::Flush()
mFlushComplete.Set(false);
nsRefPtr<nsIRunnable> task;
nsCOMPtr<nsIRunnable> task;
task = NS_NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Flush);
nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
@@ -70,7 +70,7 @@ MediaDataDecoderProxy::Drain()
MOZ_ASSERT(!IsOnProxyThread());
MOZ_ASSERT(!mIsShutdown);
nsRefPtr<nsIRunnable> task;
nsCOMPtr<nsIRunnable> task;
task = NS_NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Drain);
nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
@@ -85,7 +85,7 @@ MediaDataDecoderProxy::Shutdown()
#if defined(DEBUG)
mIsShutdown = true;
#endif
nsRefPtr<nsIRunnable> task;
nsCOMPtr<nsIRunnable> task;
task = NS_NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Shutdown);
nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_SYNC);
NS_ENSURE_SUCCESS(rv, rv);
+1 -1
View File
@@ -348,7 +348,7 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
// Remove one instance of 'dest' from mOutputNodes. There could be
// others, and it's not correct to remove them all since some of them
// could be for different output ports.
nsRefPtr<nsIRunnable> runnable =
nsCOMPtr<nsIRunnable> runnable =
new RunnableRelease(mOutputNodes[i].forget());
mOutputNodes.RemoveElementAt(i);
mStream->RunAfterPendingUpdates(runnable.forget());
+3 -3
View File
@@ -385,7 +385,7 @@ bool
Promise::PerformMicroTaskCheckpoint()
{
CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
nsTArray<nsRefPtr<nsIRunnable>>& microtaskQueue =
nsTArray<nsCOMPtr<nsIRunnable>>& microtaskQueue =
runtime->GetPromiseMicroTaskQueue();
if (microtaskQueue.IsEmpty()) {
@@ -393,7 +393,7 @@ Promise::PerformMicroTaskCheckpoint()
}
do {
nsRefPtr<nsIRunnable> runnable = microtaskQueue.ElementAt(0);
nsCOMPtr<nsIRunnable> runnable = microtaskQueue.ElementAt(0);
MOZ_ASSERT(runnable);
// This function can re-enter, so we remove the element before calling.
@@ -1038,7 +1038,7 @@ Promise::DispatchToMicroTask(nsIRunnable* aRunnable)
MOZ_ASSERT(aRunnable);
CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
nsTArray<nsRefPtr<nsIRunnable>>& microtaskQueue =
nsTArray<nsCOMPtr<nsIRunnable>>& microtaskQueue =
runtime->GetPromiseMicroTaskQueue();
microtaskQueue.AppendElement(aRunnable);
@@ -0,0 +1,86 @@
function testScript(script) {
function workerTest() {
return new Promise(function(resolve, reject) {
var worker = new Worker("worker_wrapper.js");
worker.onmessage = function(event) {
if (event.data.type == 'finish') {
resolve();
} else if (event.data.type == 'status') {
ok(event.data.status, "Worker fetch test: " + event.data.msg);
}
}
worker.onerror = function(event) {
reject("Worker error: " + event.message);
};
worker.postMessage({ "script": script });
});
}
function windowTest() {
return new Promise(function(resolve, reject) {
var scriptEl = document.createElement("script");
scriptEl.setAttribute("src", script);
scriptEl.onload = function() {
runTest().then(resolve, reject);
};
document.body.appendChild(scriptEl);
});
}
SimpleTest.waitForExplicitFinish();
// We have to run the window and worker tests sequentially since some tests
// set and compare cookies and running in parallel can lead to conflicting
// values.
windowTest()
.then(function() {
return workerTest();
})
.catch(function(e) {
ok(false, "Some test failed in " + script);
info(e);
info(e.message);
return Promise.resolve();
})
.then(function() {
SimpleTest.finish();
});
}
// Utilities
// =========
// Helper that uses FileReader or FileReaderSync based on context and returns
// a Promise that resolves with the text or rejects with error.
function readAsText(blob) {
if (typeof FileReader !== "undefined") {
return new Promise(function(resolve, reject) {
var fs = new FileReader();
fs.onload = function() {
resolve(fs.result);
}
fs.onerror = reject;
fs.readAsText(blob);
});
} else {
var fs = new FileReaderSync();
return Promise.resolve(fs.readAsText(blob));
}
}
function readAsArrayBuffer(blob) {
if (typeof FileReader !== "undefined") {
return new Promise(function(resolve, reject) {
var fs = new FileReader();
fs.onload = function() {
resolve(fs.result);
}
fs.onerror = reject;
fs.readAsArrayBuffer(blob);
});
} else {
var fs = new FileReaderSync();
return Promise.resolve(fs.readAsArrayBuffer(blob));
}
}
@@ -42,12 +42,8 @@ function testOnWorker(done) {
// Driver
//
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
testOnWorker(function() {
SimpleTest.finish();
});
testOnWorker(function() {
SimpleTest.finish();
});
</script>
</script>
@@ -42,12 +42,8 @@ function testOnWorker(done) {
// Driver
//
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
testOnWorker(function() {
SimpleTest.finish();
});
testOnWorker(function() {
SimpleTest.finish();
});
</script>
</script>
@@ -36,11 +36,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
runTest();
});
runTest();
</script>
</pre>
</body>
@@ -42,12 +42,8 @@ function testOnWorker(done) {
// Driver
//
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
testOnWorker(function() {
SimpleTest.finish();
});
testOnWorker(function() {
SimpleTest.finish();
});
</script>
</script>
+3 -7
View File
@@ -53,13 +53,9 @@ function testOnMainThread(done) {
// Driver
//
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
testOnMainThread(function() {
testOnWorker(function() {
SimpleTest.finish();
});
testOnMainThread(function() {
testOnWorker(function() {
SimpleTest.finish();
});
});
</script>
@@ -0,0 +1,22 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug XXXXXX - Test Request object in worker</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"></pre>
<script type="text/javascript" src="fetch_test_framework.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_request.js");
</script>
</body>
</html>
@@ -0,0 +1,22 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1039846 - Test Response object in worker</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"></pre>
<script type="text/javascript" src="fetch_test_framework.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_response.js");
</script>
</body>
</html>
@@ -437,7 +437,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"HashChangeEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Headers", pref: "dom.fetch.enabled"},
"Headers",
// IMPORTANT: Do not change this list without review from a DOM peer!
"History",
// IMPORTANT: Do not change this list without review from a DOM peer!
@@ -873,9 +873,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"Rect",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Request", pref: "dom.fetch.enabled"},
"Request",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Response", pref: "dom.fetch.enabled"},
"Response",
// IMPORTANT: Do not change this list without review from a DOM peer!
"RGBColor",
// IMPORTANT: Do not change this list without review from a DOM peer!
+1 -1
View File
@@ -27,7 +27,7 @@ interface Body {
[NoInterfaceObject, Exposed=(Window,Worker)]
interface GlobalFetch {
[Throws, Func="mozilla::dom::Headers::PrefEnabled"]
[Throws]
Promise<Response> fetch(RequestInfo input, optional RequestInit init);
};
+1
View File
@@ -18,6 +18,7 @@ interface FetchEvent : Event {
readonly attribute boolean isReload;
[Throws] void respondWith(Promise<Response> r);
[Throws] void respondWith(Response r);
Promise<Response> forwardTo(USVString url);
Promise<Response> default();
};
+1 -2
View File
@@ -19,8 +19,7 @@ enum HeadersGuardEnum {
};
[Constructor(optional HeadersInit init),
Exposed=(Window,Worker),
Func="mozilla::dom::Headers::PrefEnabled"]
Exposed=(Window,Worker)]
interface Headers {
[Throws] void append(ByteString name, ByteString value);
[Throws] void delete(ByteString name);
+5 -2
View File
@@ -31,9 +31,12 @@ interface MessageEvent : Event {
readonly attribute DOMString lastEventId;
/**
* The window or the port which originated this event.
* The window, port or client which originated this event.
* FIXME(catalinb): Update this when the spec changes are implemented.
* https://www.w3.org/Bugs/Public/show_bug.cgi?id=28199
* https://bugzilla.mozilla.org/show_bug.cgi?id=1143717
*/
readonly attribute (WindowProxy or MessagePort)? source;
readonly attribute (WindowProxy or MessagePort or Client)? source;
/**
* Initializes this event with the given data, in a manner analogous to
+1 -2
View File
@@ -10,8 +10,7 @@
typedef (Request or USVString) RequestInfo;
[Constructor(RequestInfo input, optional RequestInit init),
Exposed=(Window,Worker),
Func="mozilla::dom::Headers::PrefEnabled"]
Exposed=(Window,Worker)]
interface Request {
readonly attribute ByteString method;
readonly attribute USVString url;
+1 -2
View File
@@ -8,8 +8,7 @@
*/
[Constructor(optional BodyInit body, optional ResponseInit init),
Exposed=(Window,Worker),
Func="mozilla::dom::Headers::PrefEnabled"]
Exposed=(Window,Worker)]
interface Response {
[NewObject] static Response error();
[Throws,
+3 -3
View File
@@ -21,7 +21,7 @@ interface ServiceWorkerContainer : EventTarget {
[Throws]
Promise<ServiceWorkerRegistration> register(USVString scriptURL,
optional RegistrationOptionList options);
optional RegistrationOptions options);
[Throws]
Promise<ServiceWorkerRegistration> getRegistration(optional USVString documentURL = "");
@@ -47,6 +47,6 @@ partial interface ServiceWorkerContainer {
DOMString getControllingWorkerScriptURLForPath(DOMString path);
};
dictionary RegistrationOptionList {
USVString scope = "/";
dictionary RegistrationOptions {
USVString scope;
};
+11 -75
View File
@@ -59,7 +59,6 @@
#endif
#include "Principal.h"
#include "ServiceWorker.h"
#include "SharedWorker.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
@@ -155,7 +154,6 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_DOM_WINDOW_DUMP_ENABLED "browser.dom.window.dump.enabled"
#endif
#define PREF_DOM_FETCH_ENABLED "dom.fetch.enabled"
#define PREF_DOM_CACHES_ENABLED "dom.caches.enabled"
#define PREF_WORKERS_LATEST_JS_VERSION "dom.workers.latestJSVersion"
#define PREF_INTL_ACCEPT_LANGUAGES "intl.accept_languages"
@@ -1433,6 +1431,13 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
NS_ASSERTION(!sharedWorkerScriptSpec.IsEmpty(), "Empty spec!");
}
bool exemptFromPerDomainMax = false;
if (aWorkerPrivate->IsServiceWorker()) {
AssertIsOnMainThread();
exemptFromPerDomainMax = Preferences::GetBool("dom.serviceWorkers.exemptFromPerDomainMax",
false);
}
const nsCString& domain = aWorkerPrivate->Domain();
WorkerDomainInfo* domainInfo;
@@ -1450,7 +1455,8 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
queued = gMaxWorkersPerDomain &&
domainInfo->ActiveWorkerCount() >= gMaxWorkersPerDomain &&
!domain.IsEmpty();
!domain.IsEmpty() &&
!exemptFromPerDomainMax;
if (queued) {
domainInfo->mQueuedWorkers.AppendElement(aWorkerPrivate);
@@ -1838,10 +1844,6 @@ RuntimeService::Init()
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_FETCH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_FETCH))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_CACHES_ENABLED,
@@ -2039,10 +2041,6 @@ RuntimeService::Cleanup()
WorkerPrefChanged,
PREF_DOM_CACHES_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_CACHES))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_FETCH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_FETCH))) ||
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
@@ -2260,61 +2258,6 @@ RuntimeService::ResumeWorkersForWindow(nsPIDOMWindow* aWindow)
}
}
nsresult
RuntimeService::CreateServiceWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsACString& aScope,
ServiceWorker** aServiceWorker)
{
nsresult rv;
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(window);
nsRefPtr<SharedWorker> sharedWorker;
rv = CreateSharedWorkerInternal(aGlobal, aScriptURL, aScope,
WorkerTypeService,
getter_AddRefs(sharedWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsRefPtr<ServiceWorker> serviceWorker =
new ServiceWorker(window, sharedWorker);
serviceWorker->mURL = aScriptURL;
serviceWorker.forget(aServiceWorker);
return rv;
}
nsresult
RuntimeService::CreateServiceWorkerFromLoadInfo(JSContext* aCx,
WorkerPrivate::LoadInfo* aLoadInfo,
const nsAString& aScriptURL,
const nsACString& aScope,
ServiceWorker** aServiceWorker)
{
nsRefPtr<SharedWorker> sharedWorker;
nsresult rv = CreateSharedWorkerFromLoadInfo(aCx, aLoadInfo, aScriptURL, aScope,
WorkerTypeService,
getter_AddRefs(sharedWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsRefPtr<ServiceWorker> serviceWorker =
new ServiceWorker(nullptr, sharedWorker);
serviceWorker->mURL = aScriptURL;
serviceWorker.forget(aServiceWorker);
return rv;
}
nsresult
RuntimeService::CreateSharedWorkerInternal(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
@@ -2330,7 +2273,7 @@ RuntimeService::CreateSharedWorkerInternal(const GlobalObject& aGlobal,
JSContext* cx = aGlobal.Context();
WorkerPrivate::LoadInfo loadInfo;
WorkerLoadInfo loadInfo;
nsresult rv = WorkerPrivate::GetLoadInfo(cx, window, nullptr, aScriptURL,
false,
WorkerPrivate::OverrideLoadGroup,
@@ -2343,7 +2286,7 @@ RuntimeService::CreateSharedWorkerInternal(const GlobalObject& aGlobal,
nsresult
RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
WorkerPrivate::LoadInfo* aLoadInfo,
WorkerLoadInfo* aLoadInfo,
const nsAString& aScriptURL,
const nsACString& aName,
WorkerType aType,
@@ -2628,18 +2571,11 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
}
#endif
if (key == WORKERPREF_DOM_FETCH) {
key = WORKERPREF_DOM_FETCH;
sDefaultPreferences[WORKERPREF_DOM_FETCH] =
Preferences::GetBool(PREF_DOM_FETCH_ENABLED, false);
}
if (key == WORKERPREF_DOM_CACHES) {
key = WORKERPREF_DOM_CACHES;
sDefaultPreferences[WORKERPREF_DOM_CACHES] =
Preferences::GetBool(PREF_DOM_CACHES_ENABLED, false);
}
// This function should never be registered as a callback for a preference it
// does not handle.
MOZ_ASSERT(key != WORKERPREF_COUNT);
+18 -13
View File
@@ -8,7 +8,6 @@
#define mozilla_dom_workers_runtimeservice_h__
#include "Workers.h"
#include "WorkerPrivate.h" // For the WorkerType enum.
#include "nsIObserver.h"
@@ -16,7 +15,6 @@
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsTArray.h"
#include "WorkerPrivate.h"
class nsIRunnable;
class nsITimer;
@@ -24,7 +22,6 @@ class nsPIDOMWindow;
BEGIN_WORKERS_NAMESPACE
class ServiceWorker;
class SharedWorker;
class WorkerThread;
@@ -148,17 +145,25 @@ public:
}
nsresult
CreateServiceWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsACString& aScope,
ServiceWorker** aServiceWorker);
CreateSharedWorkerForServiceWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsACString& aScope,
SharedWorker** aSharedWorker)
{
return CreateSharedWorkerInternal(aGlobal, aScriptURL, aScope,
WorkerTypeService, aSharedWorker);
}
nsresult
CreateServiceWorkerFromLoadInfo(JSContext* aCx,
WorkerPrivate::LoadInfo* aLoadInfo,
const nsAString& aScriptURL,
const nsACString& aScope,
ServiceWorker** aServiceWorker);
CreateSharedWorkerForServiceWorkerFromLoadInfo(JSContext* aCx,
WorkerLoadInfo* aLoadInfo,
const nsAString& aScriptURL,
const nsACString& aScope,
SharedWorker** aSharedWorker)
{
return CreateSharedWorkerFromLoadInfo(aCx, aLoadInfo, aScriptURL, aScope,
WorkerTypeService, aSharedWorker);
}
void
ForgetSharedWorker(WorkerPrivate* aWorkerPrivate);
@@ -308,7 +313,7 @@ private:
nsresult
CreateSharedWorkerFromLoadInfo(JSContext* aCx,
WorkerPrivate::LoadInfo* aLoadInfo,
WorkerLoadInfo* aLoadInfo,
const nsAString& aScriptURL,
const nsACString& aName,
WorkerType aType,
+31 -2
View File
@@ -6,6 +6,8 @@
#include "ServiceWorker.h"
#include "nsPIDOMWindow.h"
#include "ServiceWorkerClient.h"
#include "ServiceWorkerManager.h"
#include "SharedWorker.h"
#include "WorkerPrivate.h"
@@ -38,18 +40,24 @@ ServiceWorkerVisible(JSContext* aCx, JSObject* aObj)
}
ServiceWorker::ServiceWorker(nsPIDOMWindow* aWindow,
ServiceWorkerInfo* aInfo,
SharedWorker* aSharedWorker)
: DOMEventTargetHelper(aWindow),
mState(ServiceWorkerState::Installing),
mInfo(aInfo),
mSharedWorker(aSharedWorker)
{
AssertIsOnMainThread();
MOZ_ASSERT(aInfo);
MOZ_ASSERT(mSharedWorker);
// This will update our state too.
mInfo->AppendWorker(this);
}
ServiceWorker::~ServiceWorker()
{
AssertIsOnMainThread();
mInfo->RemoveWorker(this);
}
NS_IMPL_ADDREF_INHERITED(ServiceWorker, DOMEventTargetHelper)
@@ -69,6 +77,12 @@ ServiceWorker::WrapObject(JSContext* aCx)
return ServiceWorkerBinding::Wrap(aCx, this);
}
void
ServiceWorker::GetScriptURL(nsString& aURL) const
{
CopyUTF8toUTF16(mInfo->ScriptSpec(), aURL);
}
void
ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
@@ -82,7 +96,12 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
return;
}
workerPrivate->PostMessage(aCx, aMessage, aTransferable, aRv);
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetParentObject());
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(new ServiceWorkerClientInfo(doc));
workerPrivate->PostMessageToServiceWorker(aCx, aMessage, aTransferable,
clientInfo, aRv);
}
WorkerPrivate*
@@ -95,6 +114,16 @@ ServiceWorker::GetWorkerPrivate() const
return mSharedWorker->GetWorkerPrivate();
}
void
ServiceWorker::QueueStateChangeEvent(ServiceWorkerState aState)
{
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableMethodWithArg<ServiceWorkerState>(this,
&ServiceWorker::DispatchStateChange,
aState);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
}
} // namespace workers
} // namespace dom
} // namespace mozilla
+14 -10
View File
@@ -19,6 +19,8 @@ class Promise;
namespace workers {
class ServiceWorkerInfo;
class ServiceWorkerManager;
class SharedWorker;
bool
@@ -26,7 +28,7 @@ ServiceWorkerVisible(JSContext* aCx, JSObject* aObj);
class ServiceWorker final : public DOMEventTargetHelper
{
friend class RuntimeService;
friend class ServiceWorkerManager;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorker, DOMEventTargetHelper)
@@ -50,16 +52,17 @@ public:
}
void
GetScriptURL(nsString& aURL) const
GetScriptURL(nsString& aURL) const;
void
DispatchStateChange(ServiceWorkerState aState)
{
aURL = mURL;
SetState(aState);
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("statechange"));
}
void
DispatchStateChange()
{
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("statechange"));
}
QueueStateChangeEvent(ServiceWorkerState aState);
#ifdef XP_WIN
#undef PostMessage
@@ -74,14 +77,15 @@ public:
GetWorkerPrivate() const;
private:
// This class can only be created from the RuntimeService.
ServiceWorker(nsPIDOMWindow* aWindow, SharedWorker* aSharedWorker);
// This class can only be created from the ServiceWorkerManager.
ServiceWorker(nsPIDOMWindow* aWindow, ServiceWorkerInfo* aInfo,
SharedWorker* aSharedWorker);
// This class is reference-counted and will be destroyed from Release().
~ServiceWorker();
ServiceWorkerState mState;
nsString mURL;
const nsRefPtr<ServiceWorkerInfo> mInfo;
// To allow ServiceWorkers to potentially drop the backing DOMEventTargetHelper and
// re-instantiate it later, they simply own a SharedWorker member that
+33 -2
View File
@@ -73,7 +73,7 @@ ServiceWorkerContainer::WrapObject(JSContext* aCx)
already_AddRefed<Promise>
ServiceWorkerContainer::Register(const nsAString& aScriptURL,
const RegistrationOptionList& aOptions,
const RegistrationOptions& aOptions,
ErrorResult& aRv)
{
nsCOMPtr<nsISupports> promise;
@@ -84,7 +84,38 @@ ServiceWorkerContainer::Register(const nsAString& aScriptURL,
return nullptr;
}
aRv = swm->Register(GetOwner(), aOptions.mScope, aScriptURL, getter_AddRefs(promise));
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
MOZ_ASSERT(window);
nsresult rv;
nsCOMPtr<nsIURI> scriptURI;
rv = NS_NewURI(getter_AddRefs(scriptURI), aScriptURL, nullptr,
window->GetDocBaseURI());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.ThrowTypeError(MSG_INVALID_URL, &aScriptURL);
return nullptr;
}
// In ServiceWorkerContainer.register() the scope argument is parsed against
// different base URLs depending on whether it was passed or not.
nsCOMPtr<nsIURI> scopeURI;
// Step 4. If none passed, parse against script's URL
if (!aOptions.mScope.WasPassed()) {
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), NS_LITERAL_CSTRING("./"),
nullptr, scriptURI);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
} else {
// Step 5. Parse against entry settings object's base URL.
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aOptions.mScope.Value(),
nullptr, window->GetDocBaseURI());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.ThrowTypeError(MSG_INVALID_URL, &aOptions.mScope.Value());
return nullptr;
}
}
aRv = swm->Register(window, scopeURI, scriptURI, getter_AddRefs(promise));
if (aRv.Failed()) {
return nullptr;
}
+2 -2
View File
@@ -15,7 +15,7 @@ namespace mozilla {
namespace dom {
class Promise;
struct RegistrationOptionList;
struct RegistrationOptions;
namespace workers {
class ServiceWorker;
@@ -40,7 +40,7 @@ public:
already_AddRefed<Promise>
Register(const nsAString& aScriptURL,
const RegistrationOptionList& aOptions,
const RegistrationOptions& aOptions,
ErrorResult& aRv);
already_AddRefed<workers::ServiceWorker>
+65 -21
View File
@@ -23,6 +23,8 @@
#include "mozilla/dom/WorkerScope.h"
#include "mozilla/dom/workers/bindings/ServiceWorker.h"
#include "WorkerPrivate.h"
using namespace mozilla::dom;
BEGIN_WORKERS_NAMESPACE
@@ -102,7 +104,7 @@ public:
}
NS_IMETHOD
Run()
Run()
{
AssertIsOnMainThread();
@@ -115,6 +117,14 @@ public:
}
}
mChannel->SynthesizeStatus(mInternalResponse->GetStatus(), mInternalResponse->GetStatusText());
nsAutoTArray<InternalHeaders::Entry, 5> entries;
mInternalResponse->Headers()->GetEntries(entries);
for (uint32_t i = 0; i < entries.Length(); ++i) {
mChannel->SynthesizeHeader(entries[i].mName, entries[i].mValue);
}
rv = mChannel->FinishSynthesizedResponse();
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to finish synthesized response");
return rv;
@@ -203,36 +213,50 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
return;
}
// FIXME(nsm) Bug 1136200 deal with opaque and no-cors (fetch spec 4.2.2.2).
if (response->Type() == ResponseType::Error) {
return;
}
if (NS_WARN_IF(response->BodyUsed())) {
return;
}
nsRefPtr<InternalResponse> ir = response->GetInternalResponse();
if (NS_WARN_IF(!ir)) {
return;
}
nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel, ir));
nsCOMPtr<nsIInputStream> body;
response->GetBody(getter_AddRefs(body));
if (NS_WARN_IF(!body) || NS_WARN_IF(response->BodyUsed())) {
return;
}
response->SetBodyUsed();
// Errors and redirects may not have a body.
if (body) {
response->SetBodyUsed();
nsCOMPtr<nsIOutputStream> responseBody;
rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel, ir));
nsCOMPtr<nsIEventTarget> stsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(!stsThread)) {
return;
}
rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_READSEGMENTS, 4096,
RespondWithCopyComplete, closure.forget());
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
nsCOMPtr<nsIOutputStream> responseBody;
rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIEventTarget> stsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(!stsThread)) {
return;
}
// XXXnsm, Fix for Bug 1141332 means that if we decide to make this
// streaming at some point, we'll need a different solution to that bug.
rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_READSEGMENTS, 4096,
RespondWithCopyComplete, closure.forget());
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
} else {
RespondWithCopyComplete(closure.forget(), NS_OK);
}
MOZ_ASSERT(!closure);
autoCancel.Reset();
}
@@ -264,6 +288,26 @@ FetchEvent::RespondWith(Promise& aPromise, ErrorResult& aRv)
aPromise.AppendNativeHandler(handler);
}
void
FetchEvent::RespondWith(Response& aResponse, ErrorResult& aRv)
{
if (mWaitToRespond) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
nsRefPtr<Promise> promise = Promise::Create(worker->GlobalScope(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
promise->MaybeResolve(&aResponse);
RespondWith(*promise, aRv);
}
already_AddRefed<ServiceWorkerClient>
FetchEvent::GetClient()
{
+4
View File
@@ -11,6 +11,7 @@
#include "mozilla/dom/FetchEventBinding.h"
#include "mozilla/dom/InstallEventBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Response.h"
#include "nsProxyRelease.h"
class nsIInterceptedChannel;
@@ -83,6 +84,9 @@ public:
void
RespondWith(Promise& aPromise, ErrorResult& aRv);
void
RespondWith(Response& aResponse, ErrorResult& aRv);
already_AddRefed<Promise>
ForwardTo(const nsAString& aUrl);
+188 -106
View File
@@ -422,7 +422,7 @@ public:
const nsMainThreadPtrHandle<nsISupports> aJob)
: WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
, mJob(aJob)
{
{
AssertIsOnMainThread();
}
@@ -442,6 +442,40 @@ public:
}
};
namespace {
nsresult
GetRequiredScopeStringPrefix(const nsACString& aScriptSpec, nsACString& aPrefix)
{
nsCOMPtr<nsIURI> scriptURI;
nsresult rv = NS_NewURI(getter_AddRefs(scriptURI), aScriptSpec,
nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = scriptURI->GetPrePath(aPrefix);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIURL> scriptURL(do_QueryInterface(scriptURI));
if (NS_WARN_IF(!scriptURL)) {
return rv;
}
nsAutoCString dir;
rv = scriptURL->GetDirectory(dir);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aPrefix.Append(dir);
return NS_OK;
}
} // anonymous namespace
class ServiceWorkerRegisterJob final : public ServiceWorkerJob,
public nsIStreamLoaderObserver
{
@@ -563,14 +597,29 @@ public:
NS_WARNING("Byte wise check is disabled, just using new one");
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
// FIXME: Bug 1130101 - Read max scope from Service-Worker-Allowed header.
nsAutoCString allowedPrefix;
rv = GetRequiredScopeStringPrefix(mRegistration->mScriptSpec, allowedPrefix);
if (NS_WARN_IF(NS_FAILED(rv))) {
Fail(NS_ERROR_DOM_SECURITY_ERR);
return rv;
}
if (!StringBeginsWith(mRegistration->mScope, allowedPrefix)) {
NS_WARNING("By default a service worker's scope is restricted to at or below it's script's location.");
Fail(NS_ERROR_DOM_SECURITY_ERR);
return NS_ERROR_DOM_SECURITY_ERR;
}
// We have to create a ServiceWorker here simply to ensure there are no
// errors. Ideally we should just pass this worker on to ContinueInstall.
MOZ_ASSERT(!swm->mSetOfScopesBeingUpdated.Contains(mRegistration->mScope));
swm->mSetOfScopesBeingUpdated.Put(mRegistration->mScope, true);
nsRefPtr<ServiceWorkerInfo> dummyInfo =
new ServiceWorkerInfo(mRegistration, mRegistration->mScriptSpec);
nsRefPtr<ServiceWorker> serviceWorker;
rv = swm->CreateServiceWorker(mRegistration->mPrincipal,
mRegistration->mScriptSpec,
mRegistration->mScope,
dummyInfo,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -591,7 +640,7 @@ public:
if (NS_WARN_IF(!ok)) {
swm->mSetOfScopesBeingUpdated.Remove(mRegistration->mScope);
Fail(NS_ERROR_DOM_ABORT_ERR);
return rv;
return NS_ERROR_FAILURE;
}
return NS_OK;
@@ -639,8 +688,7 @@ public:
nsRefPtr<ServiceWorker> serviceWorker;
nsresult rv =
swm->CreateServiceWorker(mRegistration->mPrincipal,
mRegistration->mInstallingWorker->ScriptSpec(),
mRegistration->mScope,
mRegistration->mInstallingWorker,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -776,13 +824,8 @@ private:
mRegistration->mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
}
// Although the spec first sets waiting worker and then updates its state,
// our ServiceWorkerInfo does not hold a list of associated ServiceWorker
// objects in content JS. This means if we want to fire an event on
// ServiceWorkerRegistration.installing, we need to do it first, before
// swapping it with waiting worker.
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Installed);
mRegistration->mWaitingWorker = mRegistration->mInstallingWorker.forget();
mRegistration->mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER | WhichServiceWorker::WAITING_WORKER);
@@ -818,8 +861,8 @@ ContinueInstallTask::ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmed
// automatically reject the Promise.
NS_IMETHODIMP
ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
const nsAString& aScope,
const nsAString& aScriptURL,
nsIURI* aScopeURI,
nsIURI* aScriptURI,
nsISupports** aPromise)
{
AssertIsOnMainThread();
@@ -889,41 +932,29 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
}
}
nsCOMPtr<nsIURI> scriptURI;
rv = NS_NewURI(getter_AddRefs(scriptURI), aScriptURL, nullptr, documentURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Data URLs are not allowed.
nsCOMPtr<nsIPrincipal> documentPrincipal = doc->NodePrincipal();
rv = documentPrincipal->CheckMayLoad(scriptURI, true /* report */,
rv = documentPrincipal->CheckMayLoad(aScriptURI, true /* report */,
false /* allowIfInheritsPrincipal */);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsIURI> scopeURI;
rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, documentURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_SECURITY_ERR;
}
rv = documentPrincipal->CheckMayLoad(scopeURI, true /* report */,
rv = documentPrincipal->CheckMayLoad(aScopeURI, true /* report */,
false /* allowIfInheritsPrinciple */);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCString cleanedScope;
rv = scopeURI->GetSpecIgnoringRef(cleanedScope);
rv = aScopeURI->GetSpecIgnoringRef(cleanedScope);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
nsAutoCString spec;
rv = scriptURI->GetSpec(spec);
rv = aScriptURI->GetSpec(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -1129,7 +1160,6 @@ ServiceWorkerRegistrationInfo::Activate()
// FIXME(nsm): Unlink appcache if there is one.
swm->CheckPendingReadyPromises();
swm->StoreRegistration(mPrincipal, this);
// "Queue a task to fire a simple event named controllerchange..."
nsCOMPtr<nsIRunnable> controllerChangeRunnable =
@@ -1142,8 +1172,7 @@ ServiceWorkerRegistrationInfo::Activate()
nsRefPtr<ServiceWorker> serviceWorker;
nsresult rv =
swm->CreateServiceWorker(mPrincipal,
mActiveWorker->ScriptSpec(),
mScope,
mActiveWorker,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
nsCOMPtr<nsIRunnable> r =
@@ -1265,7 +1294,7 @@ ServiceWorkerManager::GetRegistrations(nsIDOMWindow* aWindow,
return result.ErrorCode();
}
nsRefPtr<nsIRunnable> runnable =
nsCOMPtr<nsIRunnable> runnable =
new GetRegistrationsRunnable(window, promise);
promise.forget(aPromise);
return NS_DispatchToCurrentThread(runnable);
@@ -1366,7 +1395,7 @@ ServiceWorkerManager::GetRegistration(nsIDOMWindow* aWindow,
return result.ErrorCode();
}
nsRefPtr<nsIRunnable> runnable =
nsCOMPtr<nsIRunnable> runnable =
new GetRegistrationRunnable(window, promise, aDocumentURL);
promise.forget(aPromise);
return NS_DispatchToCurrentThread(runnable);
@@ -1432,7 +1461,7 @@ ServiceWorkerManager::GetReadyPromise(nsIDOMWindow* aWindow,
return result.ErrorCode();
}
nsRefPtr<nsIRunnable> runnable =
nsCOMPtr<nsIRunnable> runnable =
new GetReadyPromiseRunnable(window, promise);
promise.forget(aPromise);
return NS_DispatchToCurrentThread(runnable);
@@ -1692,60 +1721,24 @@ ServiceWorkerRegistrationInfo::FinishActivate(bool aSuccess)
if (aSuccess) {
mActiveWorker->UpdateState(ServiceWorkerState::Activated);
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->StoreRegistration(mPrincipal, this);
} else {
mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
mActiveWorker = nullptr;
}
}
void
ServiceWorkerRegistrationInfo::QueueStateChangeEvent(ServiceWorkerInfo* aInfo,
ServiceWorkerState aState) const
{
AssertIsOnMainThread();
MOZ_ASSERT(aInfo);
MOZ_ASSERT(aInfo == mInstallingWorker ||
aInfo == mWaitingWorker ||
aInfo == mActiveWorker);
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
WhichServiceWorker whichOne;
if (aInfo == mInstallingWorker) {
whichOne = WhichServiceWorker::INSTALLING_WORKER;
} else if (aInfo == mWaitingWorker) {
whichOne = WhichServiceWorker::WAITING_WORKER;
} else if (aInfo == mActiveWorker) {
whichOne = WhichServiceWorker::ACTIVE_WORKER;
} else {
MOZ_CRASH("Hit unexpected case");
}
// Refactor this iteration pattern across this and 2 other call-sites.
nsTObserverArray<ServiceWorkerRegistration*>::ForwardIterator it(swm->mServiceWorkerRegistrations);
while (it.HasMore()) {
nsRefPtr<ServiceWorkerRegistration> target = it.GetNext();
nsAutoString regScope;
target->GetScope(regScope);
MOZ_ASSERT(!regScope.IsEmpty());
NS_ConvertUTF16toUTF8 utf8Scope(regScope);
if (utf8Scope.Equals(mScope)) {
target->QueueStateChangeEvent(whichOne, aState);
}
}
}
NS_IMETHODIMP
ServiceWorkerManager::CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
const nsACString& aScriptSpec,
const nsACString& aScope,
ServiceWorkerInfo* aInfo,
ServiceWorker** aServiceWorker)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWindow);
RuntimeService* rs = RuntimeService::GetOrCreateService();
nsRefPtr<ServiceWorker> serviceWorker;
nsRefPtr<SharedWorker> sharedWorker;
AutoJSAPI jsapi;
jsapi.Init(aWindow);
@@ -1754,15 +1747,18 @@ ServiceWorkerManager::CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
nsCOMPtr<nsIGlobalObject> sgo = do_QueryInterface(aWindow);
JS::Rooted<JSObject*> jsGlobal(cx, sgo->GetGlobalJSObject());
GlobalObject global(cx, jsGlobal);
nsresult rv = rs->CreateServiceWorker(global,
NS_ConvertUTF8toUTF16(aScriptSpec),
aScope,
getter_AddRefs(serviceWorker));
nsresult rv = rs->CreateSharedWorkerForServiceWorker(global,
NS_ConvertUTF8toUTF16(aInfo->ScriptSpec()),
aInfo->Scope(),
getter_AddRefs(sharedWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsRefPtr<ServiceWorker> serviceWorker =
new ServiceWorker(aWindow, aInfo, sharedWorker);
serviceWorker.forget(aServiceWorker);
return rv;
}
@@ -1785,8 +1781,12 @@ ServiceWorkerManager::LoadRegistrations(
registration->mScriptSpec = aRegistrations[i].scriptSpec();
registration->mActiveWorker =
new ServiceWorkerInfo(registration, aRegistrations[i].currentWorkerURL());
const nsCString& currentWorkerURL = aRegistrations[i].currentWorkerURL();
if (!currentWorkerURL.IsEmpty()) {
registration->mActiveWorker =
new ServiceWorkerInfo(registration, currentWorkerURL);
registration->mActiveWorker->SetActivateStateUncheckedWithoutEvent(ServiceWorkerState::Activated);
}
}
}
@@ -2059,7 +2059,7 @@ ServiceWorkerManager::GetServiceWorkerForScope(nsIDOMWindow* aWindow,
AssertIsOnMainThread();
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
if (!window) {
if (NS_WARN_IF(!window)) {
return NS_ERROR_FAILURE;
}
@@ -2086,7 +2086,7 @@ ServiceWorkerManager::GetServiceWorkerForScope(nsIDOMWindow* aWindow,
////////////////////////////////////////////
nsRefPtr<ServiceWorkerRegistrationInfo> registration = GetRegistration(scope);
if (!registration) {
if (NS_WARN_IF(!registration)) {
return NS_ERROR_FAILURE;
}
@@ -2101,14 +2101,13 @@ ServiceWorkerManager::GetServiceWorkerForScope(nsIDOMWindow* aWindow,
MOZ_CRASH("Invalid worker type");
}
if (!info) {
if (NS_WARN_IF(!info)) {
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
nsRefPtr<ServiceWorker> serviceWorker;
rv = CreateServiceWorkerForWindow(window,
info->ScriptSpec(),
registration->mScope,
info,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -2133,11 +2132,13 @@ public:
FetchEventRunnable(WorkerPrivate* aWorkerPrivate,
nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo)
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
bool aIsReload)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount)
, mInterceptedChannel(aChannel)
, mServiceWorker(aServiceWorker)
, mClientInfo(aClientInfo)
, mIsReload(aIsReload)
{
MOZ_ASSERT(aWorkerPrivate);
}
@@ -2176,9 +2177,6 @@ public:
rv = channel->GetLoadFlags(&loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
//TODO(jdm): we should probably include reload-ness in the loadinfo or as a separate load flag
mIsReload = false;
rv = httpChannel->VisitRequestHeaders(this);
NS_ENSURE_SUCCESS(rv, rv);
@@ -2278,7 +2276,8 @@ private:
NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVisitor)
NS_IMETHODIMP
ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChannel* aChannel)
ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChannel* aChannel,
bool aIsReload)
{
MOZ_ASSERT(aChannel);
nsCOMPtr<nsISupports> serviceWorker;
@@ -2310,8 +2309,7 @@ ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChanne
nsRefPtr<ServiceWorker> sw;
rv = CreateServiceWorker(registration->mPrincipal,
registration->mActiveWorker->ScriptSpec(),
registration->mScope,
registration->mActiveWorker,
getter_AddRefs(sw));
serviceWorker = sw.forget();
}
@@ -2329,7 +2327,7 @@ ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChanne
// clientInfo is null if we don't have a controlled document
nsRefPtr<FetchEventRunnable> event =
new FetchEventRunnable(sw->GetWorkerPrivate(), handle, serviceWorkerHandle, clientInfo);
new FetchEventRunnable(sw->GetWorkerPrivate(), handle, serviceWorkerHandle, clientInfo, aIsReload);
rv = event->Init();
NS_ENSURE_SUCCESS(rv, rv);
@@ -2406,8 +2404,7 @@ ServiceWorkerManager::GetDocumentController(nsIDOMWindow* aWindow, nsISupports**
nsRefPtr<ServiceWorker> serviceWorker;
rv = CreateServiceWorkerForWindow(window,
registration->mActiveWorker->ScriptSpec(),
registration->mScope,
registration->mActiveWorker,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -2449,15 +2446,15 @@ ServiceWorkerManager::GetActive(nsIDOMWindow* aWindow,
NS_IMETHODIMP
ServiceWorkerManager::CreateServiceWorker(nsIPrincipal* aPrincipal,
const nsACString& aScriptSpec,
const nsACString& aScope,
ServiceWorkerInfo* aInfo,
ServiceWorker** aServiceWorker)
{
AssertIsOnMainThread();
MOZ_ASSERT(aPrincipal);
WorkerPrivate::LoadInfo info;
nsresult rv = NS_NewURI(getter_AddRefs(info.mBaseURI), aScriptSpec, nullptr, nullptr);
WorkerLoadInfo info;
nsresult rv = NS_NewURI(getter_AddRefs(info.mBaseURI), aInfo->ScriptSpec(),
nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -2479,7 +2476,6 @@ ServiceWorkerManager::CreateServiceWorker(nsIPrincipal* aPrincipal,
// them here.
WorkerPrivate::OverrideLoadInfoLoadGroup(info);
nsRefPtr<ServiceWorker> serviceWorker;
RuntimeService* rs = RuntimeService::GetOrCreateService();
if (!rs) {
return NS_ERROR_FAILURE;
@@ -2487,15 +2483,19 @@ ServiceWorkerManager::CreateServiceWorker(nsIPrincipal* aPrincipal,
AutoJSAPI jsapi;
jsapi.Init();
rv = rs->CreateServiceWorkerFromLoadInfo(jsapi.cx(), &info,
NS_ConvertUTF8toUTF16(aScriptSpec),
aScope,
getter_AddRefs(serviceWorker));
nsRefPtr<SharedWorker> sharedWorker;
rv = rs->CreateSharedWorkerForServiceWorkerFromLoadInfo(jsapi.cx(), &info,
NS_ConvertUTF8toUTF16(aInfo->ScriptSpec()),
aInfo->Scope(),
getter_AddRefs(sharedWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsRefPtr<ServiceWorker> serviceWorker =
new ServiceWorker(nullptr, aInfo, sharedWorker);
serviceWorker.forget(aServiceWorker);
return NS_OK;
}
@@ -2681,4 +2681,86 @@ ServiceWorkerManager::MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRe
}
}
void
ServiceWorkerManager::RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
{
MOZ_ASSERT(aRegistration);
MOZ_ASSERT(!aRegistration->IsControllingDocuments());
MOZ_ASSERT(mServiceWorkerRegistrationInfos.Contains(aRegistration->mScope));
ServiceWorkerManager::RemoveScope(mOrderedScopes, aRegistration->mScope);
// Hold a ref since the hashtable may be the last ref.
nsRefPtr<ServiceWorkerRegistrationInfo> reg;
mServiceWorkerRegistrationInfos.Remove(aRegistration->mScope,
getter_AddRefs(reg));
MOZ_ASSERT(reg);
// All callers should be either from a job in which case the actor is
// available, or from MaybeStopControlling(), in which case, this will only be
// called if a valid registration is found. If a valid registration exists,
// it means the actor is available since the original map of registrations is
// populated by it, and any new registrations wait until the actor is
// available before proceeding (See ServiceWorkerRegisterJob::Start).
MOZ_ASSERT(mActor);
PrincipalInfo principalInfo;
if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(reg->mPrincipal,
&principalInfo)))) {
//XXXnsm I can't think of any other reason a stored principal would fail to
//convert.
NS_WARNING("Unable to unregister serviceworker due to possible OOM");
return;
}
mActor->SendUnregisterServiceWorker(principalInfo, NS_ConvertUTF8toUTF16(reg->mScope));
}
void
ServiceWorkerInfo::AppendWorker(ServiceWorker* aWorker)
{
MOZ_ASSERT(aWorker);
#ifdef DEBUG
nsAutoString workerURL;
aWorker->GetScriptURL(workerURL);
MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mScriptSpec)));
#endif
MOZ_ASSERT(!mInstances.Contains(aWorker));
mInstances.AppendElement(aWorker);
aWorker->SetState(State());
}
void
ServiceWorkerInfo::RemoveWorker(ServiceWorker* aWorker)
{
MOZ_ASSERT(aWorker);
#ifdef DEBUG
nsAutoString workerURL;
aWorker->GetScriptURL(workerURL);
MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mScriptSpec)));
#endif
MOZ_ASSERT(mInstances.Contains(aWorker));
mInstances.RemoveElement(aWorker);
}
void
ServiceWorkerInfo::UpdateState(ServiceWorkerState aState)
{
#ifdef DEBUG
// Any state can directly transition to redundant, but everything else is
// ordered.
if (aState != ServiceWorkerState::Redundant) {
MOZ_ASSERT_IF(mState == ServiceWorkerState::EndGuard_, aState == ServiceWorkerState::Installing);
MOZ_ASSERT_IF(mState == ServiceWorkerState::Installing, aState == ServiceWorkerState::Installed);
MOZ_ASSERT_IF(mState == ServiceWorkerState::Installed, aState == ServiceWorkerState::Activating);
MOZ_ASSERT_IF(mState == ServiceWorkerState::Activating, aState == ServiceWorkerState::Activated);
}
// Activated can only go to redundant.
MOZ_ASSERT_IF(mState == ServiceWorkerState::Activated, aState == ServiceWorkerState::Redundant);
#endif
mState = aState;
for (uint32_t i = 0; i < mInstances.Length(); ++i) {
mInstances[i]->QueueStateChangeEvent(mState);
}
}
END_WORKERS_NAMESPACE
+25 -29
View File
@@ -202,9 +202,6 @@ public:
void
FinishActivate(bool aSuccess);
void
QueueStateChangeEvent(ServiceWorkerInfo* aInfo,
ServiceWorkerState aState) const;
};
/*
@@ -219,6 +216,11 @@ private:
const ServiceWorkerRegistrationInfo* mRegistration;
nsCString mScriptSpec;
ServiceWorkerState mState;
// We hold rawptrs since the ServiceWorker constructor and destructor ensure
// addition and removal.
// There is a high chance of there being at least one ServiceWorker
// associated with this all the time.
nsAutoTArray<ServiceWorker*, 1> mInstances;
~ServiceWorkerInfo()
{ }
@@ -232,6 +234,12 @@ public:
return mScriptSpec;
}
const nsCString&
Scope() const
{
return mRegistration->mScope;
}
void SetScriptSpec(const nsCString& aSpec)
{
MOZ_ASSERT(!aSpec.IsEmpty());
@@ -254,23 +262,20 @@ public:
}
void
UpdateState(ServiceWorkerState aState)
UpdateState(ServiceWorkerState aState);
// Only used to set initial state when loading from disk!
void
SetActivateStateUncheckedWithoutEvent(ServiceWorkerState aState)
{
#ifdef DEBUG
// Any state can directly transition to redundant, but everything else is
// ordered.
if (aState != ServiceWorkerState::Redundant) {
MOZ_ASSERT_IF(mState == ServiceWorkerState::EndGuard_, aState == ServiceWorkerState::Installing);
MOZ_ASSERT_IF(mState == ServiceWorkerState::Installing, aState == ServiceWorkerState::Installed);
MOZ_ASSERT_IF(mState == ServiceWorkerState::Installed, aState == ServiceWorkerState::Activating);
MOZ_ASSERT_IF(mState == ServiceWorkerState::Activating, aState == ServiceWorkerState::Activated);
}
// Activated can only go to redundant.
MOZ_ASSERT_IF(mState == ServiceWorkerState::Activated, aState == ServiceWorkerState::Redundant);
#endif
mState = aState;
mRegistration->QueueStateChangeEvent(this, mState);
}
void
AppendWorker(ServiceWorker* aWorker);
void
RemoveWorker(ServiceWorker* aWorker);
};
#define NS_SERVICEWORKERMANAGER_IMPL_IID \
@@ -346,14 +351,7 @@ public:
CreateNewRegistration(const nsCString& aScope, nsIPrincipal* aPrincipal);
void
RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
{
MOZ_ASSERT(aRegistration);
MOZ_ASSERT(!aRegistration->IsControllingDocuments());
MOZ_ASSERT(mServiceWorkerRegistrationInfos.Contains(aRegistration->mScope));
ServiceWorkerManager::RemoveScope(mOrderedScopes, aRegistration->mScope);
mServiceWorkerRegistrationInfos.Remove(aRegistration->mScope);
}
RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration);
ServiceWorkerJobQueue*
GetOrCreateJobQueue(const nsCString& aScope)
@@ -405,14 +403,12 @@ private:
NS_IMETHOD
CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
const nsACString& aScriptSpec,
const nsACString& aScope,
ServiceWorkerInfo* aInfo,
ServiceWorker** aServiceWorker);
NS_IMETHOD
CreateServiceWorker(nsIPrincipal* aPrincipal,
const nsACString& aScriptSpec,
const nsACString& aScope,
ServiceWorkerInfo* aInfo,
ServiceWorker** aServiceWorker);
NS_IMETHODIMP
-22
View File
@@ -265,28 +265,6 @@ ServiceWorkerRegistration::InvalidateWorkerReference(WhichServiceWorker aWhichOn
}
}
void
ServiceWorkerRegistration::QueueStateChangeEvent(WhichServiceWorker aWhichOne,
ServiceWorkerState aState) const
{
nsRefPtr<ServiceWorker> worker;
if (aWhichOne == WhichServiceWorker::INSTALLING_WORKER) {
worker = mInstallingWorker;
} else if (aWhichOne == WhichServiceWorker::WAITING_WORKER) {
worker = mWaitingWorker;
} else if (aWhichOne == WhichServiceWorker::ACTIVE_WORKER) {
worker = mActiveWorker;
} else {
MOZ_CRASH("Invalid case");
}
if (worker) {
worker->SetState(aState);
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(worker, &ServiceWorker::DispatchStateChange);
NS_DispatchToMainThread(r);
}
}
// XXXnsm, maybe this can be optimized to only add when a event handler is
// registered.
void
-3
View File
@@ -59,9 +59,6 @@ public:
void
InvalidateWorkerReference(WhichServiceWorker aWhichOnes);
void
QueueStateChangeEvent(WhichServiceWorker aWhichOne, ServiceWorkerState aState) const;
// DOMEventTargethelper
virtual void DisconnectFromOwner() override;
+232 -177
View File
@@ -1143,6 +1143,9 @@ class MessageEventRunnable final : public WorkerRunnable
uint64_t mMessagePortSerial;
bool mToMessagePort;
// This is only used for messages dispatched to a service worker.
nsAutoPtr<ServiceWorkerClientInfo> mEventSource;
public:
MessageEventRunnable(WorkerPrivate* aWorkerPrivate,
TargetAndBusyBehavior aBehavior,
@@ -1157,6 +1160,12 @@ public:
mClonedObjects.SwapElements(aClonedObjects);
}
void
SetMessageSource(ServiceWorkerClientInfo* aSource)
{
mEventSource = aSource;
}
bool
DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
DOMEventTargetHelper* aTarget, bool aIsMainThread)
@@ -1182,6 +1191,12 @@ public:
EmptyString(),
EmptyString(),
nullptr);
if (mEventSource) {
nsRefPtr<ServiceWorkerClient> client =
new ServiceWorkerWindowClient(aTarget, *mEventSource);
event->SetSource(client);
}
if (NS_FAILED(rv)) {
xpc::Throw(aCx, rv);
return false;
@@ -2091,9 +2106,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(TopLevelWorkerFinishedRunnable, nsRunnable)
NS_IMPL_ISUPPORTS(TimerThreadEventTarget, nsIEventTarget)
template <class Derived>
WorkerPrivateParent<Derived>::
LoadInfo::LoadInfo()
WorkerLoadInfo::WorkerLoadInfo()
: mWindowID(UINT64_MAX)
, mFromWindow(false)
, mEvalAllowed(false)
@@ -2104,15 +2117,114 @@ LoadInfo::LoadInfo()
, mIsInCertifiedApp(false)
, mIndexedDBAllowed(false)
{
MOZ_COUNT_CTOR(WorkerPrivateParent<Derived>::LoadInfo);
MOZ_COUNT_CTOR(WorkerLoadInfo);
}
WorkerLoadInfo::~WorkerLoadInfo()
{
MOZ_COUNT_DTOR(WorkerLoadInfo);
}
void
WorkerLoadInfo::StealFrom(WorkerLoadInfo& aOther)
{
MOZ_ASSERT(!mBaseURI);
aOther.mBaseURI.swap(mBaseURI);
MOZ_ASSERT(!mResolvedScriptURI);
aOther.mResolvedScriptURI.swap(mResolvedScriptURI);
MOZ_ASSERT(!mPrincipal);
aOther.mPrincipal.swap(mPrincipal);
MOZ_ASSERT(!mScriptContext);
aOther.mScriptContext.swap(mScriptContext);
MOZ_ASSERT(!mWindow);
aOther.mWindow.swap(mWindow);
MOZ_ASSERT(!mCSP);
aOther.mCSP.swap(mCSP);
MOZ_ASSERT(!mChannel);
aOther.mChannel.swap(mChannel);
MOZ_ASSERT(!mLoadGroup);
aOther.mLoadGroup.swap(mLoadGroup);
MOZ_ASSERT(!mInterfaceRequestor);
aOther.mInterfaceRequestor.swap(mInterfaceRequestor);
MOZ_ASSERT(!mPrincipalInfo);
mPrincipalInfo = aOther.mPrincipalInfo.forget();
mDomain = aOther.mDomain;
mWindowID = aOther.mWindowID;
mFromWindow = aOther.mFromWindow;
mEvalAllowed = aOther.mEvalAllowed;
mReportCSPViolations = aOther.mReportCSPViolations;
mXHRParamsAllowed = aOther.mXHRParamsAllowed;
mPrincipalIsSystem = aOther.mPrincipalIsSystem;
mIsInPrivilegedApp = aOther.mIsInPrivilegedApp;
mIsInCertifiedApp = aOther.mIsInCertifiedApp;
mIndexedDBAllowed = aOther.mIndexedDBAllowed;
}
template <class Derived>
WorkerPrivateParent<Derived>::
LoadInfo::~LoadInfo()
class WorkerPrivateParent<Derived>::EventTarget MOZ_FINAL
: public nsIEventTarget
{
MOZ_COUNT_DTOR(WorkerPrivateParent<Derived>::LoadInfo);
}
// This mutex protects mWorkerPrivate and must be acquired *before* the
// WorkerPrivate's mutex whenever they must both be held.
mozilla::Mutex mMutex;
WorkerPrivate* mWorkerPrivate;
nsIEventTarget* mWeakNestedEventTarget;
nsCOMPtr<nsIEventTarget> mNestedEventTarget;
public:
explicit EventTarget(WorkerPrivate* aWorkerPrivate)
: mMutex("WorkerPrivateParent::EventTarget::mMutex"),
mWorkerPrivate(aWorkerPrivate), mWeakNestedEventTarget(nullptr)
{
MOZ_ASSERT(aWorkerPrivate);
}
EventTarget(WorkerPrivate* aWorkerPrivate, nsIEventTarget* aNestedEventTarget)
: mMutex("WorkerPrivateParent::EventTarget::mMutex"),
mWorkerPrivate(aWorkerPrivate), mWeakNestedEventTarget(aNestedEventTarget),
mNestedEventTarget(aNestedEventTarget)
{
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(aNestedEventTarget);
}
void
Disable()
{
nsCOMPtr<nsIEventTarget> nestedEventTarget;
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate = nullptr;
mNestedEventTarget.swap(nestedEventTarget);
}
}
nsIEventTarget*
GetWeakNestedEventTarget() const
{
MOZ_ASSERT(mWeakNestedEventTarget);
return mWeakNestedEventTarget;
}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIEVENTTARGET
private:
~EventTarget()
{ }
};
template <class Derived>
class WorkerPrivateParent<Derived>::SynchronizeAndResumeRunnable final
@@ -2170,184 +2282,110 @@ private:
}
};
template <class Derived>
class WorkerPrivateParent<Derived>::InterfaceRequestor final
: public nsIInterfaceRequestor
WorkerLoadInfo::
InterfaceRequestor::InterfaceRequestor(nsIPrincipal* aPrincipal,
nsILoadGroup* aLoadGroup)
{
NS_DECL_ISUPPORTS
public:
InterfaceRequestor(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
// Look for an existing LoadContext. This is optional and it's ok if
// we don't find one.
nsCOMPtr<nsILoadContext> baseContext;
if (aLoadGroup) {
nsCOMPtr<nsIInterfaceRequestor> callbacks;
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (callbacks) {
callbacks->GetInterface(NS_GET_IID(nsILoadContext),
getter_AddRefs(baseContext));
}
}
mLoadContext = new LoadContext(aPrincipal, baseContext);
}
void
MaybeAddTabChild(nsILoadGroup* aLoadGroup)
{
MOZ_ASSERT(NS_IsMainThread());
if (!aLoadGroup) {
return;
}
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
// Look for an existing LoadContext. This is optional and it's ok if
// we don't find one.
nsCOMPtr<nsILoadContext> baseContext;
if (aLoadGroup) {
nsCOMPtr<nsIInterfaceRequestor> callbacks;
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (!callbacks) {
return;
if (callbacks) {
callbacks->GetInterface(NS_GET_IID(nsILoadContext),
getter_AddRefs(baseContext));
}
nsCOMPtr<nsITabChild> tabChild;
callbacks->GetInterface(NS_GET_IID(nsITabChild), getter_AddRefs(tabChild));
if (!tabChild) {
return;
}
// Use weak references to the tab child. Holding a strong reference will
// not prevent an ActorDestroy() from being called on the TabChild.
// Therefore, we should let the TabChild destroy itself as soon as possible.
mTabChildList.AppendElement(do_GetWeakReference(tabChild));
}
NS_IMETHOD
GetInterface(const nsIID& aIID, void** aSink) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mLoadContext);
mLoadContext = new LoadContext(aPrincipal, baseContext);
}
if (aIID.Equals(NS_GET_IID(nsILoadContext))) {
nsCOMPtr<nsILoadContext> ref = mLoadContext;
ref.forget(aSink);
return NS_OK;
}
// If we still have an active nsITabChild, then return it. Its possible,
// though, that all of the TabChild objects have been destroyed. In that
// case we return NS_NOINTERFACE.
if(aIID.Equals(NS_GET_IID(nsITabChild))) {
nsCOMPtr<nsITabChild> tabChild = GetAnyLiveTabChild();
if (!tabChild) {
return NS_NOINTERFACE;
}
tabChild.forget(aSink);
return NS_OK;
}
return NS_NOINTERFACE;
}
private:
~InterfaceRequestor() { }
already_AddRefed<nsITabChild>
GetAnyLiveTabChild()
{
MOZ_ASSERT(NS_IsMainThread());
// Search our list of known TabChild objects for one that still exists.
while (!mTabChildList.IsEmpty()) {
nsCOMPtr<nsITabChild> tabChild =
do_QueryReferent(mTabChildList.LastElement());
// Does this tab child still exist? If so, return it. We are done.
if (tabChild) {
return tabChild.forget();
}
// Otherwise remove the stale weak reference and check the next one
mTabChildList.RemoveElementAt(mTabChildList.Length() - 1);
}
return nullptr;
}
nsCOMPtr<nsILoadContext> mLoadContext;
// Array of weak references to nsITabChild. We do not want to keep TabChild
// actors alive for long after their ActorDestroy() methods are called.
nsTArray<nsWeakPtr> mTabChildList;
};
template <class Derived>
NS_IMPL_ADDREF(WorkerPrivateParent<Derived>::InterfaceRequestor)
template <class Derived>
NS_IMPL_RELEASE(WorkerPrivateParent<Derived>::InterfaceRequestor)
template <class Derived>
NS_IMPL_QUERY_INTERFACE(WorkerPrivateParent<Derived>::InterfaceRequestor,
nsIInterfaceRequestor)
template <class Derived>
class WorkerPrivateParent<Derived>::EventTarget final
: public nsIEventTarget
void
WorkerLoadInfo::
InterfaceRequestor::MaybeAddTabChild(nsILoadGroup* aLoadGroup)
{
// This mutex protects mWorkerPrivate and must be acquired *before* the
// WorkerPrivate's mutex whenever they must both be held.
mozilla::Mutex mMutex;
WorkerPrivate* mWorkerPrivate;
nsIEventTarget* mWeakNestedEventTarget;
nsCOMPtr<nsIEventTarget> mNestedEventTarget;
MOZ_ASSERT(NS_IsMainThread());
public:
explicit EventTarget(WorkerPrivate* aWorkerPrivate)
: mMutex("WorkerPrivateParent::EventTarget::mMutex"),
mWorkerPrivate(aWorkerPrivate), mWeakNestedEventTarget(nullptr)
{
MOZ_ASSERT(aWorkerPrivate);
if (!aLoadGroup) {
return;
}
EventTarget(WorkerPrivate* aWorkerPrivate, nsIEventTarget* aNestedEventTarget)
: mMutex("WorkerPrivateParent::EventTarget::mMutex"),
mWorkerPrivate(aWorkerPrivate), mWeakNestedEventTarget(aNestedEventTarget),
mNestedEventTarget(aNestedEventTarget)
{
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(aNestedEventTarget);
nsCOMPtr<nsIInterfaceRequestor> callbacks;
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (!callbacks) {
return;
}
void
Disable()
{
nsCOMPtr<nsIEventTarget> nestedEventTarget;
{
MutexAutoLock lock(mMutex);
nsCOMPtr<nsITabChild> tabChild;
callbacks->GetInterface(NS_GET_IID(nsITabChild), getter_AddRefs(tabChild));
if (!tabChild) {
return;
}
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate = nullptr;
mNestedEventTarget.swap(nestedEventTarget);
// Use weak references to the tab child. Holding a strong reference will
// not prevent an ActorDestroy() from being called on the TabChild.
// Therefore, we should let the TabChild destroy itself as soon as possible.
mTabChildList.AppendElement(do_GetWeakReference(tabChild));
}
NS_IMETHODIMP
WorkerLoadInfo::
InterfaceRequestor::GetInterface(const nsIID& aIID, void** aSink)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mLoadContext);
if (aIID.Equals(NS_GET_IID(nsILoadContext))) {
nsCOMPtr<nsILoadContext> ref = mLoadContext;
ref.forget(aSink);
return NS_OK;
}
// If we still have an active nsITabChild, then return it. Its possible,
// though, that all of the TabChild objects have been destroyed. In that
// case we return NS_NOINTERFACE.
if (aIID.Equals(NS_GET_IID(nsITabChild))) {
nsCOMPtr<nsITabChild> tabChild = GetAnyLiveTabChild();
if (!tabChild) {
return NS_NOINTERFACE;
}
tabChild.forget(aSink);
return NS_OK;
}
nsIEventTarget*
GetWeakNestedEventTarget() const
{
MOZ_ASSERT(mWeakNestedEventTarget);
return mWeakNestedEventTarget;
return NS_NOINTERFACE;
}
already_AddRefed<nsITabChild>
WorkerLoadInfo::
InterfaceRequestor::GetAnyLiveTabChild()
{
MOZ_ASSERT(NS_IsMainThread());
// Search our list of known TabChild objects for one that still exists.
while (!mTabChildList.IsEmpty()) {
nsCOMPtr<nsITabChild> tabChild =
do_QueryReferent(mTabChildList.LastElement());
// Does this tab child still exist? If so, return it. We are done.
if (tabChild) {
return tabChild.forget();
}
// Otherwise remove the stale weak reference and check the next one
mTabChildList.RemoveElementAt(mTabChildList.Length() - 1);
}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIEVENTTARGET
return nullptr;
}
private:
~EventTarget()
{ }
};
NS_IMPL_ADDREF(WorkerLoadInfo::InterfaceRequestor)
NS_IMPL_RELEASE(WorkerLoadInfo::InterfaceRequestor)
NS_IMPL_QUERY_INTERFACE(WorkerLoadInfo::InterfaceRequestor, nsIInterfaceRequestor)
struct WorkerPrivate::TimeoutInfo
{
@@ -2551,7 +2589,7 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
bool aIsChromeWorker,
WorkerType aWorkerType,
const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo)
WorkerLoadInfo& aLoadInfo)
: mMutex("WorkerPrivateParent Mutex"),
mCondVar(mMutex, "WorkerPrivateParent CondVar"),
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
@@ -3193,9 +3231,10 @@ void
WorkerPrivateParent<Derived>::PostMessageInternal(
JSContext* aCx,
JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value> >& aTransferable,
const Optional<Sequence<JS::Value>>& aTransferable,
bool aToMessagePort,
uint64_t aMessagePortSerial,
ServiceWorkerClientInfo* aClientInfo,
ErrorResult& aRv)
{
AssertIsOnParentThread();
@@ -3259,11 +3298,26 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
WorkerRunnable::WorkerThreadModifyBusyCount,
Move(buffer), clonedObjects, aToMessagePort,
aMessagePortSerial);
runnable->SetMessageSource(aClientInfo);
if (!runnable->Dispatch(aCx)) {
aRv.Throw(NS_ERROR_FAILURE);
}
}
template <class Derived>
void
WorkerPrivateParent<Derived>::PostMessageToServiceWorker(
JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
ErrorResult& aRv)
{
AssertIsOnMainThread();
PostMessageInternal(aCx, aMessage, aTransferable, false, 0,
aClientInfo.forget(), aRv);
}
template <class Derived>
void
WorkerPrivateParent<Derived>::PostMessageToMessagePort(
@@ -3276,7 +3330,7 @@ WorkerPrivateParent<Derived>::PostMessageToMessagePort(
AssertIsOnMainThread();
PostMessageInternal(aCx, aMessage, aTransferable, true, aMessagePortSerial,
aRv);
nullptr, aRv);
}
template <class Derived>
@@ -4264,7 +4318,7 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
const nsAString& aScriptURL,
bool aIsChromeWorker, WorkerType aWorkerType,
const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo)
WorkerLoadInfo& aLoadInfo)
: WorkerPrivateParent<WorkerPrivate>(aCx, aParent, aScriptURL,
aIsChromeWorker, aWorkerType,
aSharedWorkerName, aLoadInfo)
@@ -4366,7 +4420,7 @@ WorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
bool aIsChromeWorker, WorkerType aWorkerType,
const nsACString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv)
WorkerLoadInfo* aLoadInfo, ErrorResult& aRv)
{
JSContext* cx = aGlobal.Context();
return Constructor(cx, aScriptURL, aIsChromeWorker, aWorkerType,
@@ -4379,7 +4433,7 @@ WorkerPrivate::Constructor(JSContext* aCx,
const nsAString& aScriptURL,
bool aIsChromeWorker, WorkerType aWorkerType,
const nsACString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv)
WorkerLoadInfo* aLoadInfo, ErrorResult& aRv)
{
WorkerPrivate* parent = NS_IsMainThread() ?
nullptr :
@@ -4395,7 +4449,7 @@ WorkerPrivate::Constructor(JSContext* aCx,
MOZ_ASSERT_IF(aWorkerType == WorkerTypeDedicated,
aSharedWorkerName.IsEmpty());
Maybe<LoadInfo> stackLoadInfo;
Maybe<WorkerLoadInfo> stackLoadInfo;
if (!aLoadInfo) {
stackLoadInfo.emplace();
@@ -4458,7 +4512,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
WorkerPrivate* aParent, const nsAString& aScriptURL,
bool aIsChromeWorker,
LoadGroupBehavior aLoadGroupBehavior,
LoadInfo* aLoadInfo)
WorkerLoadInfo* aLoadInfo)
{
using namespace mozilla::dom::workers::scriptloader;
using mozilla::dom::indexedDB::IDBFactory;
@@ -4470,7 +4524,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
AssertIsOnMainThread();
}
LoadInfo loadInfo;
WorkerLoadInfo loadInfo;
nsresult rv;
if (aParent) {
@@ -4714,12 +4768,13 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
// static
void
WorkerPrivate::OverrideLoadInfoLoadGroup(LoadInfo& aLoadInfo)
WorkerPrivate::OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo)
{
MOZ_ASSERT(!aLoadInfo.mInterfaceRequestor);
aLoadInfo.mInterfaceRequestor = new InterfaceRequestor(aLoadInfo.mPrincipal,
aLoadInfo.mLoadGroup);
aLoadInfo.mInterfaceRequestor =
new WorkerLoadInfo::InterfaceRequestor(aLoadInfo.mPrincipal,
aLoadInfo.mLoadGroup);
aLoadInfo.mInterfaceRequestor->MaybeAddTabChild(aLoadInfo.mLoadGroup);
nsCOMPtr<nsILoadGroup> loadGroup =
+17 -104
View File
@@ -61,6 +61,7 @@ BEGIN_WORKERS_NAMESPACE
class AutoSyncLoopHolder;
class MessagePort;
class SharedWorker;
class ServiceWorkerClientInfo;
class WorkerControlRunnable;
class WorkerDebugger;
class WorkerDebuggerGlobalScope;
@@ -69,15 +70,6 @@ class WorkerPrivate;
class WorkerRunnable;
class WorkerThread;
// If you change this, the corresponding list in nsIWorkerDebugger.idl needs to
// be updated too.
enum WorkerType
{
WorkerTypeDedicated,
WorkerTypeShared,
WorkerTypeService
};
// SharedMutex is a small wrapper around an (internal) reference-counted Mutex
// object. It exists to avoid changing a lot of code to use Mutex* instead of
// Mutex&.
@@ -133,7 +125,6 @@ class WorkerPrivateParent : public DOMEventTargetHelper
class SynchronizeAndResumeRunnable;
protected:
class InterfaceRequestor;
class EventTarget;
friend class EventTarget;
@@ -153,84 +144,6 @@ public:
nsString mOrigin;
};
struct LoadInfo
{
// All of these should be released in ForgetMainThreadObjects.
nsCOMPtr<nsIURI> mBaseURI;
nsCOMPtr<nsIURI> mResolvedScriptURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIScriptContext> mScriptContext;
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsILoadGroup> mLoadGroup;
// Only set if we have a custom overriden load group
nsRefPtr<InterfaceRequestor> mInterfaceRequestor;
nsAutoPtr<PrincipalInfo> mPrincipalInfo;
nsCString mDomain;
uint64_t mWindowID;
bool mFromWindow;
bool mEvalAllowed;
bool mReportCSPViolations;
bool mXHRParamsAllowed;
bool mPrincipalIsSystem;
bool mIsInPrivilegedApp;
bool mIsInCertifiedApp;
bool mIndexedDBAllowed;
LoadInfo();
~LoadInfo();
void
StealFrom(LoadInfo& aOther)
{
MOZ_ASSERT(!mBaseURI);
aOther.mBaseURI.swap(mBaseURI);
MOZ_ASSERT(!mResolvedScriptURI);
aOther.mResolvedScriptURI.swap(mResolvedScriptURI);
MOZ_ASSERT(!mPrincipal);
aOther.mPrincipal.swap(mPrincipal);
MOZ_ASSERT(!mScriptContext);
aOther.mScriptContext.swap(mScriptContext);
MOZ_ASSERT(!mWindow);
aOther.mWindow.swap(mWindow);
MOZ_ASSERT(!mCSP);
aOther.mCSP.swap(mCSP);
MOZ_ASSERT(!mChannel);
aOther.mChannel.swap(mChannel);
MOZ_ASSERT(!mLoadGroup);
aOther.mLoadGroup.swap(mLoadGroup);
MOZ_ASSERT(!mInterfaceRequestor);
aOther.mInterfaceRequestor.swap(mInterfaceRequestor);
MOZ_ASSERT(!mPrincipalInfo);
mPrincipalInfo = aOther.mPrincipalInfo.forget();
mDomain = aOther.mDomain;
mWindowID = aOther.mWindowID;
mFromWindow = aOther.mFromWindow;
mEvalAllowed = aOther.mEvalAllowed;
mReportCSPViolations = aOther.mReportCSPViolations;
mXHRParamsAllowed = aOther.mXHRParamsAllowed;
mPrincipalIsSystem = aOther.mPrincipalIsSystem;
mIsInPrivilegedApp = aOther.mIsInPrivilegedApp;
mIsInCertifiedApp = aOther.mIsInCertifiedApp;
mIndexedDBAllowed = aOther.mIndexedDBAllowed;
}
};
protected:
typedef mozilla::ErrorResult ErrorResult;
@@ -249,7 +162,7 @@ private:
LocationInfo mLocationInfo;
// The lifetime of these objects within LoadInfo is managed explicitly;
// they do not need to be cycle collected.
LoadInfo mLoadInfo;
WorkerLoadInfo mLoadInfo;
// Only used for top level workers.
nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
@@ -285,7 +198,7 @@ protected:
const nsAString& aScriptURL, bool aIsChromeWorker,
WorkerType aWorkerType,
const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo);
WorkerLoadInfo& aLoadInfo);
~WorkerPrivateParent();
@@ -309,8 +222,9 @@ private:
void
PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value> >& aTransferable,
const Optional<Sequence<JS::Value>>& aTransferable,
bool aToMessagePort, uint64_t aMessagePortSerial,
ServiceWorkerClientInfo* aClientInfo,
ErrorResult& aRv);
nsresult
@@ -412,9 +326,15 @@ public:
const Optional<Sequence<JS::Value> >& aTransferable,
ErrorResult& aRv)
{
PostMessageInternal(aCx, aMessage, aTransferable, false, 0, aRv);
PostMessageInternal(aCx, aMessage, aTransferable, false, 0, nullptr, aRv);
}
void
PostMessageToServiceWorker(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
ErrorResult& aRv);
void
PostMessageToMessagePort(JSContext* aCx,
uint64_t aMessagePortSerial,
@@ -926,12 +846,12 @@ public:
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
bool aIsChromeWorker, WorkerType aWorkerType,
const nsACString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv);
WorkerLoadInfo* aLoadInfo, ErrorResult& aRv);
static already_AddRefed<WorkerPrivate>
Constructor(JSContext* aCx, const nsAString& aScriptURL, bool aIsChromeWorker,
WorkerType aWorkerType, const nsACString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv);
WorkerLoadInfo* aLoadInfo, ErrorResult& aRv);
static bool
WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */);
@@ -945,10 +865,10 @@ public:
static nsresult
GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
LoadGroupBehavior aLoadGroupBehavior, LoadInfo* aLoadInfo);
LoadGroupBehavior aLoadGroupBehavior, WorkerLoadInfo* aLoadInfo);
static void
OverrideLoadInfoLoadGroup(LoadInfo& aLoadInfo);
OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo);
WorkerDebugger*
Debugger() const
@@ -1185,13 +1105,6 @@ public:
return mPreferences[WORKERPREF_DUMP];
}
bool
DOMFetchEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_DOM_FETCH];
}
bool
DOMCachesEnabled() const
{
@@ -1255,7 +1168,7 @@ private:
WorkerPrivate(JSContext* aCx, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
WorkerType aWorkerType, const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo);
WorkerLoadInfo& aLoadInfo);
void
ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
+87 -2
View File
@@ -14,6 +14,11 @@
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsILoadContext.h"
#include "nsIWeakReferenceUtils.h"
#include "nsIInterfaceRequestor.h"
#define BEGIN_WORKERS_NAMESPACE \
namespace mozilla { namespace dom { namespace workers {
@@ -24,9 +29,32 @@
#define WORKERS_SHUTDOWN_TOPIC "web-workers-shutdown"
class nsIGlobalObject;
class nsIContentSecurityPolicy;
class nsIScriptContext;
class nsIGlobalObject;
class nsPIDOMWindow;
class nsIPrincipal;
class nsILoadGroup;
class nsITabChild;
class nsIChannel;
class nsIURI;
namespace mozilla {
namespace ipc {
class PrincipalInfo;
}
namespace dom {
// If you change this, the corresponding list in nsIWorkerDebugger.idl needs to
// be updated too.
enum WorkerType
{
WorkerTypeDedicated,
WorkerTypeShared,
WorkerTypeService
};
}
}
BEGIN_WORKERS_NAMESPACE
@@ -166,11 +194,68 @@ struct JSSettings
enum WorkerPreference
{
WORKERPREF_DUMP = 0, // browser.dom.window.dump.enabled
WORKERPREF_DOM_FETCH,// dom.fetch.enabled
WORKERPREF_DOM_CACHES, // dom.caches.enabled
WORKERPREF_COUNT
};
// Implemented in WorkerPrivate.cpp
struct WorkerLoadInfo
{
// All of these should be released in WorkerPrivateParent::ForgetMainThreadObjects.
nsCOMPtr<nsIURI> mBaseURI;
nsCOMPtr<nsIURI> mResolvedScriptURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIScriptContext> mScriptContext;
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsILoadGroup> mLoadGroup;
class InterfaceRequestor MOZ_FINAL : public nsIInterfaceRequestor
{
NS_DECL_ISUPPORTS
public:
InterfaceRequestor(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
void MaybeAddTabChild(nsILoadGroup* aLoadGroup);
NS_IMETHOD GetInterface(const nsIID& aIID, void** aSink) MOZ_OVERRIDE;
private:
~InterfaceRequestor() { }
already_AddRefed<nsITabChild> GetAnyLiveTabChild();
nsCOMPtr<nsILoadContext> mLoadContext;
// Array of weak references to nsITabChild. We do not want to keep TabChild
// actors alive for long after their ActorDestroy() methods are called.
nsTArray<nsWeakPtr> mTabChildList;
};
// Only set if we have a custom overriden load group
nsRefPtr<InterfaceRequestor> mInterfaceRequestor;
nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
nsCString mDomain;
uint64_t mWindowID;
bool mFromWindow;
bool mEvalAllowed;
bool mReportCSPViolations;
bool mXHRParamsAllowed;
bool mPrincipalIsSystem;
bool mIsInPrivilegedApp;
bool mIsInCertifiedApp;
bool mIndexedDBAllowed;
WorkerLoadInfo();
~WorkerLoadInfo();
void StealFrom(WorkerLoadInfo& aOther);
};
// All of these are implemented in RuntimeService.cpp
void
+1 -5
View File
@@ -36,11 +36,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
checkEnabled();
});
checkEnabled();
</script>
</pre>
</body>
+1 -5
View File
@@ -36,11 +36,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
checkEnabled();
});
checkEnabled();
</script>
</pre>
</body>
+1 -5
View File
@@ -36,11 +36,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
runTest();
});
runTest();
</script>
</pre>
</body>
@@ -0,0 +1,17 @@
function handleRequest(request, response) {
// The string "hello" repeated 10 times followed by newline. Compressed using gzip.
var bytes = [0x1f, 0x8b, 0x08, 0x08, 0x4d, 0xe2, 0xf9, 0x54, 0x00, 0x03, 0x68,
0x65, 0x6c, 0x6c, 0x6f, 0x00, 0xcb, 0x48, 0xcd, 0xc9, 0xc9, 0xcf,
0x20, 0x85, 0xe0, 0x02, 0x00, 0xf5, 0x4b, 0x38, 0xcf, 0x33, 0x00,
0x00, 0x00];
response.setHeader("Content-Encoding", "gzip", false);
response.setHeader("Content-Length", "" + bytes.length, false);
response.setHeader("Content-Type", "text/plain", false);
var bos = Components.classes["@mozilla.org/binaryoutputstream;1"]
.createInstance(Components.interfaces.nsIBinaryOutputStream);
bos.setOutputStream(response.bodyOutputStream);
bos.writeByteArray(bytes, bytes.length);
}
@@ -27,6 +27,25 @@ fetch('synthesized.txt', function(xhr) {
finish();
});
fetch('test-respondwith-response.txt', function(xhr) {
my_ok(xhr.status == 200, "test-respondwith-response load should be successful");
my_ok(xhr.responseText == "test-respondwith-response response body", "load should have response");
finish();
});
fetch('synthesized-404.txt', function(xhr) {
my_ok(xhr.status == 404, "load should 404");
my_ok(xhr.responseText == "synthesized response body", "404 load should have synthesized response");
finish();
});
fetch('synthesized-headers.txt', function(xhr) {
my_ok(xhr.status == 200, "load should be successful");
my_ok(xhr.getResponseHeader("X-Custom-Greeting") === "Hello", "custom header should be set");
my_ok(xhr.responseText == "synthesized response body", "custom header load should have synthesized response");
finish();
});
fetch('ignored.txt', function(xhr) {
my_ok(xhr.status == 404, "load should be uninterrupted");
finish();
@@ -52,3 +71,35 @@ fetch('headers.txt', function(xhr) {
my_ok(xhr.responseText == "1", "request header checks should have passed");
finish();
}, null, [["X-Test1", "header1"], ["X-Test2", "header2"]]);
var expectedUncompressedResponse = "";
for (var i = 0; i < 10; ++i) {
expectedUncompressedResponse += "hello";
}
expectedUncompressedResponse += "\n";
// ServiceWorker does not intercept, at which point the network request should
// be correctly decoded.
fetch('deliver-gzip.sjs', function(xhr) {
my_ok(xhr.status == 200, "network gzip load should be successful");
my_ok(xhr.responseText == expectedUncompressedResponse, "network gzip load should have synthesized response.");
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "network Content-Encoding should be gzip.");
my_ok(xhr.getResponseHeader("Content-Length") == "35", "network Content-Length should be of original gzipped file.");
finish();
});
fetch('hello.gz', function(xhr) {
my_ok(xhr.status == 200, "gzip load should be successful");
my_ok(xhr.responseText == expectedUncompressedResponse, "gzip load should have synthesized response.");
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "Content-Encoding should be gzip.");
my_ok(xhr.getResponseHeader("Content-Length") == "35", "Content-Length should be of original gzipped file.");
finish();
});
fetch('hello-after-extracting.gz', function(xhr) {
my_ok(xhr.status == 200, "gzip load should be successful");
my_ok(xhr.responseText == expectedUncompressedResponse, "gzip load should have synthesized response.");
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "Content-Encoding should be gzip.");
my_ok(xhr.getResponseHeader("Content-Length") == "35", "Content-Length should be of original gzipped file.");
finish();
});
@@ -1,86 +1,135 @@
var seenIndex = false;
onfetch = function(ev) {
if (ev.request.url.includes("synthesized.txt")) {
var p = new Promise(function(resolve) {
var r = new Response("synthesized response body", {});
resolve(r);
});
ev.respondWith(p);
ev.respondWith(Promise.resolve(
new Response("synthesized response body", {})
));
}
else if (ev.request.url.contains("synthesized-404.txt")) {
ev.respondWith(Promise.resolve(
new Response("synthesized response body", { status: 404 })
));
}
else if (ev.request.url.contains("synthesized-headers.txt")) {
ev.respondWith(Promise.resolve(
new Response("synthesized response body", {
headers: {
"X-Custom-Greeting": "Hello"
}
})
));
}
else if (ev.request.url.contains("test-respondwith-response.txt")) {
ev.respondWith(new Response("test-respondwith-response response body", {}));
}
else if (ev.request.url.includes("ignored.txt")) {
}
else if (ev.request.url.includes("rejected.txt")) {
var p = new Promise(function(resolve, reject) {
reject();
});
ev.respondWith(p);
ev.respondWith(Promise.reject());
}
else if (ev.request.url.includes("nonresponse.txt")) {
var p = new Promise(function(resolve, reject) {
resolve(5);
});
ev.respondWith(p);
ev.respondWith(Promise.resolve(5));
}
else if (ev.request.url.includes("nonresponse2.txt")) {
var p = new Promise(function(resolve, reject) {
resolve({});
});
ev.respondWith(p);
ev.respondWith(Promise.resolve({}));
}
else if (ev.request.url.includes("headers.txt")) {
var p = new Promise(function(resolve, reject) {
var ok = true;
ok &= ev.request.headers.get("X-Test1") == "header1";
ok &= ev.request.headers.get("X-Test2") == "header2";
var r = new Response(ok.toString(), {});
resolve(r);
});
ev.respondWith(p);
var ok = true;
ok &= ev.request.headers.get("X-Test1") == "header1";
ok &= ev.request.headers.get("X-Test2") == "header2";
ev.respondWith(Promise.resolve(
new Response(ok.toString(), {})
));
}
else if (ev.request.url.includes("nonexistent_image.gif")) {
var p = new Promise(function(resolve, reject) {
resolve(new Response(atob("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs"), {}));
});
ev.respondWith(p);
resolve(new Response(atob("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs"), {
ev.respondWith(Promise.resolve(
new Response(atob("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs"), {
headers: {
"Content-Type": "image/gif"
}
})
));
}
else if (ev.request.url.includes("nonexistent_script.js")) {
var p = new Promise(function(resolve, reject) {
resolve(new Response("check_intercepted_script();", {}));
});
ev.respondWith(p);
ev.respondWith(Promise.resolve(
new Response("check_intercepted_script();", {})
));
}
else if (ev.request.url.includes("nonexistent_stylesheet.css")) {
var p = new Promise(function(resolve, reject) {
resolve(new Response("#style-test { background-color: black !important; }", {}));
});
ev.respondWith(p);
ev.respondWith(Promise.resolve(
new Response("#style-test { background-color: black !important; }", {
headers : {
"Content-Type": "text/css"
}
})
));
}
else if (ev.request.url.includes("nonexistent_page.html")) {
var p = new Promise(function(resolve, reject) {
resolve(new Response("<script>window.frameElement.test_result = true;</script>", {}));
});
ev.respondWith(p);
ev.respondWith(Promise.resolve(
new Response("<script>window.frameElement.test_result = true;</script>", {
headers : {
"Content-Type": "text/html"
}
})
));
}
else if (ev.request.url.includes("nonexistent_worker_script.js")) {
var p = new Promise(function(resolve, reject) {
resolve(new Response("postMessage('worker-intercept-success')", {}));
});
ev.respondWith(p);
ev.respondWith(Promise.resolve(
new Response("postMessage('worker-intercept-success')", {})
));
}
else if (ev.request.url.includes("nonexistent_imported_script.js")) {
var p = new Promise(function(resolve, reject) {
resolve(new Response("check_intercepted_script();", {}));
});
ev.respondWith(p);
ev.respondWith(Promise.resolve(
new Response("check_intercepted_script();", {})
));
}
else if (ev.request.url.contains("deliver-gzip")) {
// Don't handle the request, this will make Necko perform a network request, at
// which point SetApplyConversion must be re-enabled, otherwise the request
// will fail.
return;
}
else if (ev.request.url.contains("hello.gz")) {
ev.respondWith(fetch("fetch/deliver-gzip.sjs"));
}
else if (ev.request.url.contains("hello-after-extracting.gz")) {
ev.respondWith(fetch("fetch/deliver-gzip.sjs").then(function(res) {
return res.text().then(function(body) {
return new Response(body, { status: res.status, statusText: res.statusText, headers: res.headers });
});
}));
}
else if (ev.request.url.contains("index.html")) {
if (seenIndex) {
var body = "<script>" +
"opener.postMessage({status: 'ok', result: " + ev.isReload + "," +
"message: 'reload status should be indicated'}, '*');" +
"opener.postMessage({status: 'done'}, '*');" +
"</script>";
ev.respondWith(new Response(body, {headers: {'Content-Type': 'text/html'}}));
} else {
seenIndex = true;
ev.respondWith(fetch(ev.request.url));
}
}
}
@@ -24,6 +24,7 @@ support-files =
fetch/index.html
fetch/fetch_worker_script.js
fetch/fetch_tests.js
fetch/deliver-gzip.sjs
fetch/https/index.html
fetch/https/register.html
fetch/https/unregister.html
@@ -41,6 +42,8 @@ support-files =
serviceworker_not_sharedworker.js
match_all_client/match_all_client_id.html
match_all_client_id_worker.js
source_message_posting_worker.js
scope/scope_worker.js
[test_unregister.html]
skip-if = true # Bug 1133805
@@ -59,6 +62,7 @@ skip-if = true # Bug 1133805
skip-if = true # Bug 1133805
[test_post_message.html]
[test_post_message_advanced.html]
[test_post_message_source.html]
[test_match_all_client_properties.html]
[test_close.html]
[test_serviceworker_interfaces.html]
@@ -0,0 +1,2 @@
// This worker is used to test if calling register() without a scope argument
// leads to scope being relative to service worker script.
@@ -36,15 +36,6 @@
}
});
navigator.serviceWorker.getRegistration('http://mochi.test:8888/with_star/*')
.then(function(a) {
window.parent.postMessage({ type: "check", status: true,
msg: "getRegistration returns a ServiceWorkerRegistration" }, "*");
a.onupdatefound = function(e) {
eventReceived();
}
});
navigator.serviceWorker.getRegistration('http://www.something_else.net/')
.then(function(a) {
window.parent.postMessage({ type: "check", status: false,
@@ -0,0 +1,12 @@
onmessage = function(e) {
if (!e.source) {
dump("ERROR: message doesn't have a source.");
}
// The client should be a window client
if (e.source instanceof WindowClient) {
e.source.postMessage(e.data);
} else {
e.source.postMessage("ERROR. source is not a window client.");
}
};
@@ -60,6 +60,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -18,18 +18,28 @@
function simpleRegister() {
var p = navigator.serviceWorker.register("fetch_event_worker.js", { scope: "./fetch" });
return p;
return p.then(function(swr) {
return new Promise(function(resolve) {
swr.installing.onstatechange = resolve;
});
});
}
function testController() {
var p = new Promise(function(resolve, reject) {
var reloaded = false;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "done") {
window.onmessage = null;
w.close();
resolve();
if (reloaded) {
window.onmessage = null;
w.close();
resolve();
} else {
w.location.reload();
reloaded = true;
}
}
}
});
@@ -51,9 +61,9 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.fetch.enabled", true]
]}, runTest);
</script>
</pre>
@@ -102,6 +102,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -177,6 +177,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.messageChannel.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
@@ -67,6 +67,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -27,6 +27,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true]
]}, function() {
checkEnabled();
@@ -66,6 +66,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -95,6 +95,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -0,0 +1,65 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1142015 - Test service worker post message source </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"></pre>
<script class="testbody" type="text/javascript">
var magic_value = "MAGIC_VALUE_RANDOM";
var registration;
function start() {
return navigator.serviceWorker.register("source_message_posting_worker.js",
{ scope: "./nonexistent_scope/" })
.then((swr) => registration = swr);
}
function unregister() {
return registration.unregister().then(function(result) {
ok(result, "Unregister should return true.");
});
}
function testPostMessage(swr) {
var p = new Promise(function(res, rej) {
navigator.serviceWorker.onmessage = function(e) {
ok(e.data === magic_value, "Worker posted the correct value.");
res();
}
});
ok(swr.installing, "Installing worker exists.");
swr.installing.postMessage(magic_value);
return p;
}
function runTest() {
start()
.then(testPostMessage)
.then(unregister)
.catch(function(e) {
ok(false, "Some test failed with error " + e);
}).then(SimpleTest.finish);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
</script>
</pre>
</body>
</html>
@@ -16,7 +16,6 @@
<script class="testbody" type="text/javascript">
var scriptsAndScopes = [
[ "worker.js", "." ],
[ "worker.js", "./sub/dir/"],
[ "worker.js", "./sub/dir" ],
[ "worker.js", "./sub/dir.html" ],
@@ -30,6 +29,22 @@
scriptsAndScopes.forEach(function(item) {
registerArray.push(navigator.serviceWorker.register(item[0], { scope: item[1] }));
});
// Check register()'s step 4 which uses script's url with "./" as the scope if no scope is passed.
// The other tests already check step 5.
registerArray.push(navigator.serviceWorker.register("scope/scope_worker.js"));
// Check that SW cannot be registered for a scope "above" the script's location.
registerArray.push(new Promise(function(resolve, reject) {
navigator.serviceWorker.register("scope/scope_worker.js", { scope: "./" })
.then(function() {
ok(false, "registration scope has to be inside service worker script scope.");
reject();
}, function() {
ok(true, "registration scope has to be inside service worker script scope.");
resolve();
});
}));
return Promise.all(registerArray);
}
@@ -41,6 +56,11 @@
return reg.unregister();
}));
});
unregisterArray.push(navigator.serviceWorker.getRegistration("scope/").then(function (reg) {
return reg.unregister();
}));
return Promise.all(unregisterArray);
}
@@ -53,15 +73,25 @@
return base + s;
}
ok(getScope(p("index.html")) === p(""), "Scope should match");
ok(getScope(p("sua.html")) === p(""), "Scope should match");
function fail(fn) {
try {
getScope(p("index.html"));
ok(false, "No registration");
} catch(e) {
ok(true, "No registration");
}
}
ok(getScope(p("sub.html")) === p("sub"), "Scope should match");
ok(getScope(p("sub/dir.html")) === p("sub/dir.html"), "Scope should match");
ok(getScope(p("sub/dir")) === p("sub/dir"), "Scope should match");
ok(getScope(p("sub/dir/foo")) === p("sub/dir/"), "Scope should match");
ok(getScope(p("sub/dir/afoo")) === p("sub/dir/a"), "Scope should match");
ok(getScope(p("star*wars")) === p("star*"), "Scope should match");
ok(getScope(p("star/a.html")) === p(""), "Scope should match");
ok(getScope(p("scope/some_file.html")) === p("scope/"), "Scope should match");
fail("index.html");
fail("sua.html");
fail("star/a.html");
resolve();
});
}
@@ -80,6 +110,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -104,7 +104,6 @@
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.fetch.enabled", true],
["dom.caches.enabled", true]
]}, runTest);
};
@@ -115,7 +115,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"FileReaderSync",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "Headers", pref: "dom.fetch.enabled" },
"Headers",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBCursor",
// IMPORTANT: Do not change this list without review from a DOM peer!
@@ -16,8 +16,31 @@
<script class="testbody" type="text/javascript">
function simpleRegister() {
info("simpleRegister() just before calling register");
return navigator.serviceWorker.register("worker.js", { scope: "unregister/" });
return navigator.serviceWorker.register("worker.js", { scope: "unregister/" }).then(function(swr) {
if (swr.installing) {
return new Promise(function(resolve, reject) {
swr.installing.onstatechange = function(e) {
if (swr.waiting) {
swr.waiting.onstatechange = function(e) {
if (swr.active) {
resolve();
} else if (swr.waiting && swr.waiting.state == "redundant") {
reject("Should not go into redundant");
}
}
} else {
if (swr.active) {
resolve();
} else {
reject("No waiting and no active!");
}
}
}
});
} else {
return Promise.reject("Installing should be non-null");
}
});
}
function testControlled() {
@@ -49,6 +72,11 @@
function unregister() {
return navigator.serviceWorker.getRegistration("unregister/")
.then(function(reg) {
if (!reg) {
info("Registration already removed");
return;
}
info("getRegistration() succeeded " + reg.scope);
return reg.unregister().then(function(v) {
ok(v, "Unregister should resolve to true");
@@ -99,6 +127,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -14,7 +14,31 @@
<script class="testbody" type="text/javascript">
function simpleRegister() {
return navigator.serviceWorker.register("worker_unregister.js", { scope: "unregister/" });
return navigator.serviceWorker.register("worker_unregister.js", { scope: "unregister/" }).then(function(swr) {
if (swr.installing) {
return new Promise(function(resolve, reject) {
swr.installing.onstatechange = function(e) {
if (swr.waiting) {
swr.waiting.onstatechange = function(e) {
if (swr.active) {
resolve();
} else if (swr.waiting && swr.waiting.state == "redundant") {
reject("Should not go into redundant");
}
}
} else {
if (swr.active) {
resolve();
} else {
reject("No waiting and no active!");
}
}
}
});
} else {
return Promise.reject("Installing should be non-null");
}
});
}
function waitForMessages(sw) {
@@ -47,6 +71,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -44,6 +44,7 @@
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
@@ -19,22 +19,7 @@
info("unregister/index.html should not to be launched directly!");
}
SimpleTest.requestFlakyTimeout("Unfortunately we have no way to test for a page being uncontrolled except waiting for ready to not resolve");
var tId = setTimeout(function() {
parent.postMessage({ controlled: false }, "*");
tId = null;
}, 2000);
navigator.serviceWorker.ready.then(function() {
if (tId == null) {
parent.postMessage("FAIL!!!", "*");
return;
}
clearTimeout(tId);
parent.postMessage({ controlled: true }, "*");
});
parent.postMessage({ controlled: !!navigator.serviceWorker.controller }, "*");
</script>
</pre>
</body>
@@ -12,7 +12,7 @@
<body>
<script type="text/javascript">
onmessage = function(e) { parent.postMessage(e.data, "*"); }
navigator.serviceWorker.onmessage = function(e) { parent.postMessage(e.data, "*"); }
navigator.serviceWorker.controller.postMessage("GO");
</script>
@@ -12,7 +12,7 @@
<body>
<script type="text/javascript">
onmessage = function(e) { parent.postMessage(e.data, "*"); }
navigator.serviceWorker.onmessage = function(e) { parent.postMessage(e.data, "*"); }
navigator.serviceWorker.ready.then(function() {
navigator.serviceWorker.controller.postMessage("GO");
});
+5 -1
View File
@@ -109,7 +109,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"FileReaderSync",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "Headers", pref: "dom.fetch.enabled" },
"Headers",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBCursor",
// IMPORTANT: Do not change this list without review from a DOM peer!
@@ -140,6 +140,10 @@ var interfaceNamesInGlobalScope =
"Performance",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Promise",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Request",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Response",
// IMPORTANT: Do not change this list without review from a DOM peer!
"TextDecoder",
// IMPORTANT: Do not change this list without review from a DOM peer!
+1 -1
View File
@@ -109,7 +109,7 @@ private:
RefPtr<AndroidNativeWindow> mNativeWindow;
int mID;
nsRefPtr<nsIRunnable> mFrameAvailableCallback;
nsCOMPtr<nsIRunnable> mFrameAvailableCallback;
};
}
+6 -4
View File
@@ -2212,10 +2212,12 @@ DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue val
// it's just a plain old data property. However the JS_Define* APIs use
// null getter and setter to mean "default to the Class getProperty and
// setProperty ops".
if (!getter)
getter = obj->getClass()->getProperty;
if (!setter)
setter = obj->getClass()->setProperty;
if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
if (!getter)
getter = obj->getClass()->getProperty;
if (!setter)
setter = obj->getClass()->setProperty;
}
if (getter == JS_PropertyStub)
getter = nullptr;
if (setter == JS_StrictPropertyStub)
+1 -1
View File
@@ -49,7 +49,7 @@ VsyncParent::NotifyVsync(TimeStamp aTimeStamp)
{
// Called on hardware vsync thread. We should post to current ipc thread.
MOZ_ASSERT(!IsOnBackgroundThread());
nsRefPtr<nsIRunnable> vsyncEvent =
nsCOMPtr<nsIRunnable> vsyncEvent =
NS_NewRunnableMethodWithArg<TimeStamp>(this,
&VsyncParent::DispatchVsyncEvent,
aTimeStamp);
@@ -383,7 +383,7 @@ PeerConnectionCtx::~PeerConnectionCtx() {
#endif
};
void PeerConnectionCtx::queueJSEPOperation(nsRefPtr<nsIRunnable> aOperation) {
void PeerConnectionCtx::queueJSEPOperation(nsCOMPtr<nsIRunnable> aOperation) {
mQueuedJSEPOperations.AppendElement(aOperation);
}
@@ -39,7 +39,7 @@ class PeerConnectionCtx {
return true;
}
void queueJSEPOperation(nsRefPtr<nsIRunnable> aJSEPOperation);
void queueJSEPOperation(nsCOMPtr<nsIRunnable> aJSEPOperation);
void onGMPReady();
bool gmpHasH264();
@@ -94,7 +94,7 @@ private:
// ready to go, since blocking on this init is just begging for deadlock.
nsCOMPtr<mozIGoannaMediaPluginService> mGMPService;
bool mGMPReady;
nsTArray<nsRefPtr<nsIRunnable>> mQueuedJSEPOperations;
nsTArray<nsCOMPtr<nsIRunnable>> mQueuedJSEPOperations;
static PeerConnectionCtx *gInstance;
public:
@@ -396,7 +396,7 @@ PeerConnectionMedia::StartIceChecks(const JsepSession& session) {
}
}
nsRefPtr<nsIRunnable> runnable(
nsCOMPtr<nsIRunnable> runnable(
WrapRunnable(
RefPtr<PeerConnectionMedia>(this),
&PeerConnectionMedia::StartIceChecks_s,
@@ -507,7 +507,7 @@ PeerConnectionMedia::FlushIceCtxOperationQueueIfReady()
void
PeerConnectionMedia::PerformOrEnqueueIceCtxOperation(
const nsRefPtr<nsIRunnable>& runnable)
const nsCOMPtr<nsIRunnable>& runnable)
{
ASSERT_ON_THREAD(mMainThread);
@@ -522,7 +522,7 @@ void
PeerConnectionMedia::GatherIfReady() {
ASSERT_ON_THREAD(mMainThread);
nsRefPtr<nsIRunnable> runnable(WrapRunnable(
nsCOMPtr<nsIRunnable> runnable(WrapRunnable(
RefPtr<PeerConnectionMedia>(this),
&PeerConnectionMedia::EnsureIceGathering_s));
@@ -421,7 +421,7 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
const std::vector<std::string>& aCandidateList);
void GatherIfReady();
void FlushIceCtxOperationQueueIfReady();
void PerformOrEnqueueIceCtxOperation(const nsRefPtr<nsIRunnable>& runnable);
void PerformOrEnqueueIceCtxOperation(const nsCOMPtr<nsIRunnable>& runnable);
void EnsureIceGathering_s();
void StartIceChecks_s(bool aIsControlling,
bool aIsIceLite,
@@ -499,7 +499,7 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
// on our ICE ctx, but are not ready to do so at the moment (eg; we are
// waiting to get a callback with our http proxy config before we start
// gathering or start checking)
std::vector<nsRefPtr<nsIRunnable>> mQueuedIceCtxOperations;
std::vector<nsCOMPtr<nsIRunnable>> mQueuedIceCtxOperations;
// Used to cancel any ongoing proxy request.
nsCOMPtr<nsICancelable> mProxyRequest;
-3
View File
@@ -4767,9 +4767,6 @@ pref("beacon.enabled", true);
// Camera prefs
pref("camera.control.face_detection.enabled", true);
// Fetch API.
pref("dom.fetch.enabled", true);
// SW Cache API
pref("dom.caches.enabled", false);
+1 -1
View File
@@ -296,6 +296,6 @@ NetworkActivityMonitor::DataInOut(Direction direction)
void
NetworkActivityMonitor::PostNotification(Direction direction)
{
nsRefPtr<nsIRunnable> ev = new NotifyNetworkActivity(direction);
nsCOMPtr<nsIRunnable> ev = new NotifyNetworkActivity(direction);
NS_DispatchToMainThread(ev);
}
+2 -2
View File
@@ -21,7 +21,7 @@ OfflineObserver::RegisterOfflineObserver()
if (NS_IsMainThread()) {
RegisterOfflineObserverMainThread();
} else {
nsRefPtr<nsIRunnable> event =
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &OfflineObserver::RegisterOfflineObserverMainThread);
NS_DispatchToMainThread(event);
}
@@ -33,7 +33,7 @@ OfflineObserver::RemoveOfflineObserver()
if (NS_IsMainThread()) {
RemoveOfflineObserverMainThread();
} else {
nsRefPtr<nsIRunnable> event =
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &OfflineObserver::RemoveOfflineObserverMainThread);
NS_DispatchToMainThread(event);
}
+1 -1
View File
@@ -59,7 +59,7 @@ Tickler::~Tickler()
// Shutting down a thread can spin the event loop - which is a surprising
// thing to do from a dtor. Running it on its own event is safer.
nsRefPtr<nsIRunnable> event = new TicklerThreadDestructor(mThread);
nsCOMPtr<nsIRunnable> event = new TicklerThreadDestructor(mThread);
if (NS_FAILED(NS_DispatchToCurrentThread(event))) {
mThread->Shutdown();
}
+1 -1
View File
@@ -182,7 +182,7 @@ nsAsyncRedirectVerifyHelper::ExplicitCallback(nsresult result)
mWaitingForRedirectCallback = false;
// Now, dispatch the callback on the event-target which called Init()
nsRefPtr<nsIRunnable> event =
nsCOMPtr<nsIRunnable> event =
new nsAsyncVerifyRedirectCallbackEvent(callback, result);
if (!event) {
NS_WARNING("nsAsyncRedirectVerifyHelper::ExplicitCallback() "
@@ -16,7 +16,7 @@ interface nsIURI;
* which do not implement nsIChannel.
*/
[scriptable, uuid(155378c1-ebb2-4492-917f-85483430d5f5)]
[scriptable, uuid(2fc1170c-4f9d-4c9e-8e5d-2d351dbe03f2)]
interface nsIInterceptedChannel : nsISupports
{
/**
@@ -25,6 +25,12 @@ interface nsIInterceptedChannel : nsISupports
*/
void resetInterception();
/**
* Set the status and reason for the forthcoming synthesized response.
* Multiple calls overwrite existing values.
*/
void synthesizeStatus(in uint16_t status, in ACString reason);
/**
* Attach a header name/value pair to the forthcoming synthesized response.
* Overwrites any existing header value.
+1 -1
View File
@@ -536,7 +536,7 @@ nsCacheEntryDescriptor::AsyncDoom(nsICacheListener *listener)
return NS_OK;
}
nsRefPtr<nsIRunnable> event = new nsAsyncDoomEvent(this, listener);
nsCOMPtr<nsIRunnable> event = new nsAsyncDoomEvent(this, listener);
return nsCacheService::DispatchToCacheIOThread(event);
}

Some files were not shown because too many files have changed in this diff Show More