mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Backout rev 509957c7a9f9 (bug 1456986). r=me a=ryanvm
This commit is contained in:
parent
17a7546f6b
commit
363fb9cea0
@ -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<JS::Value> 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<nsString> { NS_ConvertUTF8toUTF16(mDescriptor.Scope()) });
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
||||
Maybe<ClientState> clientState = window->GetClientState();
|
||||
if (NS_WARN_IF(clientInfo.isNothing() || clientState.isNothing())) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv) = 0;
|
||||
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
};
|
||||
|
@ -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<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
mServiceWorkerPrivate->SendMessageEvent(Move(aData),
|
||||
ClientInfoAndState(aClientInfo.ToIPC(),
|
||||
aClientState.ToIPC()));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> 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<nsString> { NS_ConvertUTF8toUTF16(Scope()) });
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
||||
Maybe<ClientState> 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
|
||||
|
@ -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<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -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<JSObject*> 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<JS::Value> messageData(aCx);
|
||||
nsCOMPtr<nsIGlobalObject> 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<OwningNonNull<MessagePort>> 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<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& 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<JSObject*> 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<JS::Value> messageData(cx);
|
||||
aData.Read(cx, &messageData, rv);
|
||||
if (rv.Failed()) {
|
||||
ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent));
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
Sequence<OwningNonNull<MessagePort>> ports;
|
||||
if (!aData.TakeTransferredPortsAsSequence(ports)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedHandleValue);
|
||||
|
||||
JS::Rooted<JSObject*> 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<JS::Value> 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<JS::Value> 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<KeepAliveToken> token = CreateEventKeepAliveToken();
|
||||
RefPtr<SendMessageEventRunnable> 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;
|
||||
}
|
||||
|
@ -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<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
const ClientInfoAndState& aClientInfoAndState);
|
||||
|
||||
// This is used to validate the worker script and continue the installation
|
||||
@ -205,9 +199,6 @@ private:
|
||||
already_AddRefed<KeepAliveToken>
|
||||
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<KeepAliveToken> 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<JSObjectHolder> mSandbox;
|
||||
|
||||
uint64_t mDebuggerCount;
|
||||
|
||||
uint64_t mTokenCount;
|
||||
|
Loading…
x
Reference in New Issue
Block a user