From 363fb9cea0f161ed1667fd38156e187afe372c2b Mon Sep 17 00:00:00 2001 From: Ben Kelly Date: Tue, 8 May 2018 07:38:53 -0700 Subject: [PATCH] Backout rev 509957c7a9f9 (bug 1456986). r=me a=ryanvm --- dom/serviceworkers/ServiceWorker.cpp | 38 +------ dom/serviceworkers/ServiceWorker.h | 11 +- dom/serviceworkers/ServiceWorkerInfo.cpp | 37 +++++-- dom/serviceworkers/ServiceWorkerInfo.h | 8 +- dom/serviceworkers/ServiceWorkerPrivate.cpp | 108 ++++---------------- dom/serviceworkers/ServiceWorkerPrivate.h | 18 +--- 6 files changed, 62 insertions(+), 158 deletions(-) diff --git a/dom/serviceworkers/ServiceWorker.cpp b/dom/serviceworkers/ServiceWorker.cpp index 455cd26e4265..4d3ac9888abc 100644 --- a/dom/serviceworkers/ServiceWorker.cpp +++ b/dom/serviceworkers/ServiceWorker.cpp @@ -17,7 +17,6 @@ #include "mozilla/dom/Promise.h" #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" #include "mozilla/dom/WorkerPrivate.h" -#include "mozilla/dom/ipc/StructuredCloneData.h" #ifdef XP_WIN #undef PostMessage @@ -148,42 +147,7 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle aMessage, return; } - nsPIDOMWindowInner* window = GetOwner(); - if (NS_WARN_IF(!window || !window->GetExtantDoc())) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - - auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window); - if (storageAllowed != nsContentUtils::StorageAccess::eAllow) { - ServiceWorkerManager::LocalizeAndReportToAllClients( - mDescriptor.Scope(), "ServiceWorkerPostMessageStorageError", - nsTArray { NS_ConvertUTF8toUTF16(mDescriptor.Scope()) }); - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return; - } - - Maybe clientInfo = window->GetClientInfo(); - Maybe clientState = window->GetClientState(); - if (NS_WARN_IF(clientInfo.isNothing() || clientState.isNothing())) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - - JS::Rooted transferable(aCx, JS::UndefinedValue()); - aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable, - &transferable); - if (aRv.Failed()) { - return; - } - - ipc::StructuredCloneData data; - data.Write(aCx, aMessage, transferable, aRv); - if (aRv.Failed()) { - return; - } - - mInner->PostMessage(Move(data), clientInfo.ref(), clientState.ref()); + mInner->PostMessage(GetParentObject(), aCx, aMessage, aTransferable, aRv); } diff --git a/dom/serviceworkers/ServiceWorker.h b/dom/serviceworkers/ServiceWorker.h index a2b20b5c0ba1..8aad0d7f199b 100644 --- a/dom/serviceworkers/ServiceWorker.h +++ b/dom/serviceworkers/ServiceWorker.h @@ -20,10 +20,6 @@ class nsIGlobalObject; namespace mozilla { namespace dom { -namespace ipc { -class StructuredCloneData; -} // namespace ipc - #define NS_DOM_SERVICEWORKER_IID \ {0xd42e0611, 0x3647, 0x4319, {0xae, 0x05, 0x19, 0x89, 0x59, 0xba, 0x99, 0x5e}} @@ -58,9 +54,10 @@ public: RemoveServiceWorker(ServiceWorker* aWorker) = 0; virtual void - PostMessage(ipc::StructuredCloneData&& aData, - const ClientInfo& aClientInfo, - const ClientState& aClientState) = 0; + PostMessage(nsIGlobalObject* aGlobal, + JSContext* aCx, JS::Handle aMessage, + const Sequence& aTransferable, + ErrorResult& aRv) = 0; NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING }; diff --git a/dom/serviceworkers/ServiceWorkerInfo.cpp b/dom/serviceworkers/ServiceWorkerInfo.cpp index e9f7e57e0824..d3f0f886ab7a 100644 --- a/dom/serviceworkers/ServiceWorkerInfo.cpp +++ b/dom/serviceworkers/ServiceWorkerInfo.cpp @@ -256,13 +256,38 @@ ServiceWorkerInfo::RemoveServiceWorker(ServiceWorker* aWorker) } void -ServiceWorkerInfo::PostMessage(ipc::StructuredCloneData&& aData, - const ClientInfo& aClientInfo, - const ClientState& aClientState) +ServiceWorkerInfo::PostMessage(nsIGlobalObject* aGlobal, + JSContext* aCx, JS::Handle aMessage, + const Sequence& aTransferable, + ErrorResult& aRv) { - mServiceWorkerPrivate->SendMessageEvent(Move(aData), - ClientInfoAndState(aClientInfo.ToIPC(), - aClientState.ToIPC())); + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr window = do_QueryInterface(aGlobal); + if (NS_WARN_IF(!window || !window->GetExtantDoc())) { + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return; + } + + auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window); + if (storageAllowed != nsContentUtils::StorageAccess::eAllow) { + ServiceWorkerManager::LocalizeAndReportToAllClients( + Scope(), "ServiceWorkerPostMessageStorageError", + nsTArray { NS_ConvertUTF8toUTF16(Scope()) }); + aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); + return; + } + + Maybe clientInfo = window->GetClientInfo(); + Maybe clientState = window->GetClientState(); + if (NS_WARN_IF(clientInfo.isNothing() || clientState.isNothing())) { + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return; + } + + aRv = mServiceWorkerPrivate->SendMessageEvent(aCx, aMessage, aTransferable, + ClientInfoAndState(clientInfo.ref().ToIPC(), + clientState.ref().ToIPC())); } void diff --git a/dom/serviceworkers/ServiceWorkerInfo.h b/dom/serviceworkers/ServiceWorkerInfo.h index e83c17d48e3a..e0a5f00e3cbd 100644 --- a/dom/serviceworkers/ServiceWorkerInfo.h +++ b/dom/serviceworkers/ServiceWorkerInfo.h @@ -17,7 +17,6 @@ namespace mozilla { namespace dom { -class ClientInfoAndState; class ServiceWorkerPrivate; /* @@ -86,9 +85,10 @@ private: RemoveServiceWorker(ServiceWorker* aWorker) override; virtual void - PostMessage(ipc::StructuredCloneData&& aData, - const ClientInfo& aClientInfo, - const ClientState& aClientState) override; + PostMessage(nsIGlobalObject* aGlobal, + JSContext* aCx, JS::Handle aMessage, + const Sequence& aTransferable, + ErrorResult& aRv) override; public: NS_DECL_ISUPPORTS diff --git a/dom/serviceworkers/ServiceWorkerPrivate.cpp b/dom/serviceworkers/ServiceWorkerPrivate.cpp index e7896eaca5df..ba158622ac1e 100644 --- a/dom/serviceworkers/ServiceWorkerPrivate.cpp +++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp @@ -23,7 +23,6 @@ #include "nsStreamUtils.h" #include "nsStringStream.h" #include "mozilla/Assertions.h" -#include "mozilla/JSObjectHolder.h" #include "mozilla/dom/Client.h" #include "mozilla/dom/ClientIPCTypes.h" #include "mozilla/dom/DOMPrefs.h" @@ -34,12 +33,10 @@ #include "mozilla/dom/PromiseNativeHandler.h" #include "mozilla/dom/PushEventBinding.h" #include "mozilla/dom/RequestBinding.h" -#include "mozilla/dom/StructuredCloneHolder.h" #include "mozilla/dom/WorkerDebugger.h" #include "mozilla/dom/WorkerRef.h" #include "mozilla/dom/WorkerRunnable.h" #include "mozilla/dom/WorkerScope.h" -#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/Unused.h" using namespace mozilla; @@ -215,24 +212,6 @@ ServiceWorkerPrivate::CheckScriptEvaluation(LifeCycleEventCallback* aScriptEvalu return NS_OK; } -JSObject* -ServiceWorkerPrivate::GetOrCreateSandbox(JSContext* aCx) -{ - AssertIsOnMainThread(); - - if (!mSandbox) { - nsIXPConnect* xpc = nsContentUtils::XPConnect(); - - JS::Rooted sandbox(aCx); - nsresult rv = xpc->CreateSandbox(aCx, mInfo->Principal(), sandbox.address()); - NS_ENSURE_SUCCESS(rv, nullptr); - - mSandbox = new JSObjectHolder(aCx, sandbox); - } - - return mSandbox->GetJSObject(); -} - namespace { enum ExtendableEventResult { @@ -521,17 +500,17 @@ public: }; class SendMessageEventRunnable final : public ExtendableEventWorkerRunnable + , public StructuredCloneHolder { - StructuredCloneHolder mData; const ClientInfoAndState mClientInfoAndState; public: SendMessageEventRunnable(WorkerPrivate* aWorkerPrivate, KeepAliveToken* aKeepAliveToken, - StructuredCloneHolder&& aData, const ClientInfoAndState& aClientInfoAndState) : ExtendableEventWorkerRunnable(aWorkerPrivate, aKeepAliveToken) - , mData(Move(aData)) + , StructuredCloneHolder(CloningSupported, TransferringSupported, + StructuredCloneScope::SameProcessDifferentThread) , mClientInfoAndState(aClientInfoAndState) { MOZ_ASSERT(NS_IsMainThread()); @@ -543,13 +522,13 @@ public: JS::Rooted messageData(aCx); nsCOMPtr sgo = aWorkerPrivate->GlobalScope(); ErrorResult rv; - mData.Read(sgo, aCx, &messageData, rv); + Read(sgo, aCx, &messageData, rv); if (NS_WARN_IF(rv.Failed())) { return true; } Sequence> ports; - if (!mData.TakeTransferredPortsAsSequence(ports)) { + if (!TakeTransferredPortsAsSequence(ports)) { return true; } @@ -584,82 +563,35 @@ public: } // anonymous namespace nsresult -ServiceWorkerPrivate::SendMessageEvent(ipc::StructuredCloneData&& aData, +ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx, + JS::Handle aMessage, + const Sequence& aTransferable, const ClientInfoAndState& aClientInfoAndState) { MOZ_ASSERT(NS_IsMainThread()); - ErrorResult rv; - - // Ideally we would simply move the StructuredCloneData to the - // SendMessageEventRunnable, but we cannot because it uses non-threadsafe - // ref-counting. The following gnarly code unpacks the IPC-friendly - // StructuredCloneData and re-packs it into the thread-friendly - // StructuredCloneHolder. In the future we should remove this and make - // it easier to simple move the data to the other thread. See bug 1458936. - - AutoSafeJSContext cx; - JSObject* sandbox = GetOrCreateSandbox(cx); - NS_ENSURE_TRUE(sandbox, NS_ERROR_FAILURE); - - JS::Rooted global(cx, sandbox); - NS_ENSURE_TRUE(sandbox, NS_ERROR_FAILURE); - - // The CreateSandbox call returns a proxy to the actual sandbox object. We - // don't need a proxy here. - global = js::UncheckedUnwrap(global); - - JSAutoCompartment ac(cx, global); - - JS::Rooted messageData(cx); - aData.Read(cx, &messageData, rv); - if (rv.Failed()) { + ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent)); + if (NS_WARN_IF(rv.Failed())) { return rv.StealNSResult(); } - Sequence> ports; - if (!aData.TakeTransferredPortsAsSequence(ports)) { - return NS_ERROR_FAILURE; - } + JS::Rooted transferable(aCx, JS::UndefinedHandleValue); - JS::Rooted array(cx, JS_NewArrayObject(cx, ports.Length())); - NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY); - - for (uint32_t i = 0; i < ports.Length(); ++i) { - JS::Rooted value(cx); - if (!GetOrCreateDOMReflector(cx, ports[i], &value)) { - JS_ClearPendingException(cx); - return NS_ERROR_FAILURE; - } - - if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) { - return NS_ERROR_OUT_OF_MEMORY; - } - } - - JS::Rooted transferable(cx); - transferable.setObject(*array); - - StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, - StructuredCloneHolder::TransferringSupported, - JS::StructuredCloneScope::SameProcessDifferentThread); - holder.Write(cx, messageData, transferable, JS::CloneDataPolicy(), rv); - if (rv.Failed()) { - return rv.StealNSResult(); - } - - // Now that the re-packing is complete, send a runnable to the service worker - // thread. - - rv = SpawnWorkerIfNeeded(MessageEvent); + rv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable, + &transferable); if (NS_WARN_IF(rv.Failed())) { return rv.StealNSResult(); } RefPtr token = CreateEventKeepAliveToken(); RefPtr runnable = - new SendMessageEventRunnable(mWorkerPrivate, token, Move(holder), - aClientInfoAndState); + new SendMessageEventRunnable(mWorkerPrivate, token, aClientInfoAndState); + + runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), rv); + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); + } + if (!runnable->Dispatch()) { return NS_ERROR_FAILURE; } diff --git a/dom/serviceworkers/ServiceWorkerPrivate.h b/dom/serviceworkers/ServiceWorkerPrivate.h index acee14f5e66e..87bacd99109c 100644 --- a/dom/serviceworkers/ServiceWorkerPrivate.h +++ b/dom/serviceworkers/ServiceWorkerPrivate.h @@ -16,9 +16,6 @@ class nsIInterceptedChannel; namespace mozilla { - -class JSObjectHolder; - namespace dom { class ClientInfoAndState; @@ -26,10 +23,6 @@ class KeepAliveToken; class ServiceWorkerInfo; class ServiceWorkerRegistrationInfo; -namespace ipc { -class StructuredCloneData; -} // namespace ipc - class LifeCycleEventCallback : public Runnable { public: @@ -89,7 +82,8 @@ public: explicit ServiceWorkerPrivate(ServiceWorkerInfo* aInfo); nsresult - SendMessageEvent(ipc::StructuredCloneData&& aData, + SendMessageEvent(JSContext* aCx, JS::Handle aMessage, + const Sequence& aTransferable, const ClientInfoAndState& aClientInfoAndState); // This is used to validate the worker script and continue the installation @@ -205,9 +199,6 @@ private: already_AddRefed CreateEventKeepAliveToken(); - JSObject* - GetOrCreateSandbox(JSContext* aCx); - // The info object owns us. It is possible to outlive it for a brief period // of time if there are pending waitUntil promises, in which case it // will be null and |SpawnWorkerIfNeeded| will always fail. @@ -224,11 +215,6 @@ private: // worker a grace period after each event. RefPtr mIdleKeepAliveToken; - // Sandbox global used to re-pack structured clone data before sending - // to the service worker thread. Ideally we would remove this and just - // make StructuredCloneData thread safe enough to pass to the worker thread. - RefPtr mSandbox; - uint64_t mDebuggerCount; uint64_t mTokenCount;