Bug 1250572 - Force a parent object in MessagePort/Channel and in StructuredCloneHolder, r=smaug

This commit is contained in:
Andrea Marchesini 2016-02-24 20:04:37 +01:00
parent 46bb47edff
commit 53c0f726fe
8 changed files with 67 additions and 52 deletions

View File

@ -295,6 +295,7 @@ StructuredCloneHolder::Read(nsISupports* aParent,
{
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread,
mCreationThread == NS_GetCurrentThread());
MOZ_ASSERT(aParent);
mozilla::AutoRestore<nsISupports*> guard(mParent);
mParent = aParent;
@ -1044,9 +1045,11 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
const MessagePortIdentifier& portIdentifier = mPortIdentifiers[aExtraData];
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
ErrorResult rv;
RefPtr<MessagePort> port =
MessagePort::Create(mParent, portIdentifier, rv);
MessagePort::Create(global, portIdentifier, rv);
if (NS_WARN_IF(rv.Failed())) {
return false;
}

View File

@ -13,14 +13,14 @@
#include "mozilla/dom/WorkerRunnable.h"
#include "nsContentUtils.h"
#include "nsIDocument.h"
#include "nsIGlobalObject.h"
#include "nsIPrincipal.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MessageChannel, mWindow, mPort1, mPort2)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MessageChannel, mGlobal, mPort1, mPort2)
NS_IMPL_CYCLE_COLLECTING_ADDREF(MessageChannel)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MessageChannel)
@ -29,9 +29,10 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
MessageChannel::MessageChannel(nsPIDOMWindowInner* aWindow)
: mWindow(aWindow)
MessageChannel::MessageChannel(nsIGlobalObject* aGlobal)
: mGlobal(aGlobal)
{
MOZ_ASSERT(aGlobal);
}
MessageChannel::~MessageChannel()
@ -47,14 +48,15 @@ MessageChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
/* static */ already_AddRefed<MessageChannel>
MessageChannel::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
{
// window can be null in workers.
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
return Constructor(window, aRv);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
return Constructor(global, aRv);
}
/* static */ already_AddRefed<MessageChannel>
MessageChannel::Constructor(nsPIDOMWindowInner* aWindow, ErrorResult& aRv)
MessageChannel::Constructor(nsIGlobalObject* aGlobal, ErrorResult& aRv)
{
MOZ_ASSERT(aGlobal);
nsID portUUID1;
aRv = nsContentUtils::GenerateUUIDInPlace(portUUID1);
if (aRv.Failed()) {
@ -67,14 +69,14 @@ MessageChannel::Constructor(nsPIDOMWindowInner* aWindow, ErrorResult& aRv)
return nullptr;
}
RefPtr<MessageChannel> channel = new MessageChannel(aWindow);
RefPtr<MessageChannel> channel = new MessageChannel(aGlobal);
channel->mPort1 = MessagePort::Create(aWindow, portUUID1, portUUID2, aRv);
channel->mPort1 = MessagePort::Create(aGlobal, portUUID1, portUUID2, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
channel->mPort2 = MessagePort::Create(aWindow, portUUID2, portUUID1, aRv);
channel->mPort2 = MessagePort::Create(aGlobal, portUUID2, portUUID1, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}

View File

@ -14,7 +14,7 @@
#include "nsWrapperCache.h"
#include "nsCOMPtr.h"
class nsPIDOMWindowInner;
class nsIGlobalObject;
namespace mozilla {
namespace dom {
@ -28,10 +28,10 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel)
nsPIDOMWindowInner*
nsIGlobalObject*
GetParentObject() const
{
return mWindow;
return mGlobal;
}
virtual JSObject*
@ -41,7 +41,7 @@ public:
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
static already_AddRefed<MessageChannel>
Constructor(nsPIDOMWindowInner* aWindow, ErrorResult& aRv);
Constructor(nsIGlobalObject* aGlobal, ErrorResult& aRv);
MessagePort*
Port1() const
@ -56,10 +56,10 @@ public:
}
private:
explicit MessageChannel(nsPIDOMWindowInner* aWindow);
explicit MessageChannel(nsIGlobalObject* aGlobal);
~MessageChannel();
nsCOMPtr<nsPIDOMWindowInner> mWindow;
nsCOMPtr<nsIGlobalObject> mGlobal;
RefPtr<MessagePort> mPort1;
RefPtr<MessagePort> mPort2;

View File

@ -86,15 +86,8 @@ private:
nsresult
DispatchMessage() const
{
nsCOMPtr<nsIGlobalObject> globalObject;
if (NS_IsMainThread()) {
globalObject = do_QueryInterface(mPort->GetParentObject());
} else {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
globalObject = workerPrivate->GlobalScope();
}
nsCOMPtr<nsIGlobalObject> globalObject = mPort->GetParentObject();
MOZ_ASSERT(globalObject);
AutoJSAPI jsapi;
if (!globalObject || !jsapi.Init(globalObject)) {
@ -259,20 +252,17 @@ NS_IMPL_ISUPPORTS(ForceCloseHelper, nsIIPCBackgroundChildCreateCallback)
} // namespace
MessagePort::MessagePort(nsISupports* aSupports)
: mInnerID(0)
MessagePort::MessagePort(nsIGlobalObject* aGlobal)
: DOMEventTargetHelper(aGlobal)
, mInnerID(0)
, mMessageQueueEnabled(false)
, mIsKeptAlive(false)
{
MOZ_ASSERT(aGlobal);
mIdentifier = new MessagePortIdentifier();
mIdentifier->neutered() = true;
mIdentifier->sequenceId() = 0;
nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(aSupports);
if (NS_WARN_IF(!globalObject)) {
return;
}
BindToOwner(globalObject);
}
MessagePort::~MessagePort()
@ -282,21 +272,25 @@ MessagePort::~MessagePort()
}
/* static */ already_AddRefed<MessagePort>
MessagePort::Create(nsISupports* aSupport, const nsID& aUUID,
MessagePort::Create(nsIGlobalObject* aGlobal, const nsID& aUUID,
const nsID& aDestinationUUID, ErrorResult& aRv)
{
RefPtr<MessagePort> mp = new MessagePort(aSupport);
MOZ_ASSERT(aGlobal);
RefPtr<MessagePort> mp = new MessagePort(aGlobal);
mp->Initialize(aUUID, aDestinationUUID, 1 /* 0 is an invalid sequence ID */,
false /* Neutered */, eStateUnshippedEntangled, aRv);
return mp.forget();
}
/* static */ already_AddRefed<MessagePort>
MessagePort::Create(nsISupports* aSupport,
MessagePort::Create(nsIGlobalObject* aGlobal,
const MessagePortIdentifier& aIdentifier,
ErrorResult& aRv)
{
RefPtr<MessagePort> mp = new MessagePort(aSupport);
MOZ_ASSERT(aGlobal);
RefPtr<MessagePort> mp = new MessagePort(aGlobal);
mp->Initialize(aIdentifier.uuid(), aIdentifier.destinationUuid(),
aIdentifier.sequenceId(), aIdentifier.neutered(),
eStateEntangling, aRv);

View File

@ -16,7 +16,7 @@
#undef PostMessage
#endif
class nsPIDOMWindowInner;
class nsIGlobalObject;
namespace mozilla {
namespace dom {
@ -45,11 +45,12 @@ public:
DOMEventTargetHelper)
static already_AddRefed<MessagePort>
Create(nsISupports* aSupport, const nsID& aUUID,
Create(nsIGlobalObject* aGlobal, const nsID& aUUID,
const nsID& aDestinationUUID, ErrorResult& aRv);
static already_AddRefed<MessagePort>
Create(nsISupports* aSupport, const MessagePortIdentifier& aIdentifier,
Create(nsIGlobalObject* aGlobal,
const MessagePortIdentifier& aIdentifier,
ErrorResult& aRv);
// For IPC.
@ -88,7 +89,7 @@ public:
void Closed();
private:
explicit MessagePort(nsISupports* nsISupports);
explicit MessagePort(nsIGlobalObject* aGlobal);
~MessagePort();
enum State {

View File

@ -2386,13 +2386,14 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
// We don't actually care about this MessageChannel, but we use it to 'steal'
// its 2 connected ports.
RefPtr<MessageChannel> channel = MessageChannel::Constructor(window, rv);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window);
RefPtr<MessageChannel> channel = MessageChannel::Constructor(global, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
RefPtr<SharedWorker> sharedWorker = new SharedWorker(window, workerPrivate,
channel->Port1());
channel->Port1());
if (!workerPrivate->RegisterSharedWorker(aCx, sharedWorker,
channel->Port2())) {

View File

@ -672,10 +672,8 @@ public:
DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
DOMEventTargetHelper* aTarget, bool aIsMainThread)
{
nsCOMPtr<nsPIDOMWindowInner> parent;
if (aIsMainThread) {
parent = do_QueryInterface(aTarget->GetParentObject());
}
nsCOMPtr<nsIGlobalObject> parent = do_QueryInterface(aTarget->GetParentObject());
MOZ_ASSERT(parent);
JS::Rooted<JS::Value> messageData(aCx);
ErrorResult rv;
@ -6384,7 +6382,7 @@ WorkerPrivate::ConnectMessagePort(JSContext* aCx,
// This MessagePortIdentifier is used to create a new port, still connected
// with the other one, but in the worker thread.
ErrorResult rv;
RefPtr<MessagePort> port = MessagePort::Create(nullptr, aIdentifier, rv);
RefPtr<MessagePort> port = MessagePort::Create(globalScope, aIdentifier, rv);
if (NS_WARN_IF(rv.Failed())) {
return false;
}

View File

@ -26,6 +26,7 @@
#include "nsVariant.h"
#include "RuntimeService.h"
#include "WorkerScope.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "XMLHttpRequestUpload.h"
@ -1336,7 +1337,12 @@ EventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
ErrorResult rv;
JS::Rooted<JS::Value> response(aCx);
Read(nullptr, aCx, &response, rv);
GlobalObject globalObj(aCx, aWorkerPrivate->GlobalScope()->GetWrapper());
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(globalObj.GetAsSupports());
Read(global, aCx, &response, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return false;
@ -1513,8 +1519,18 @@ SendRunnable::MainThreadRun()
ErrorResult rv;
JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx));
if (NS_WARN_IF(!globalObject)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIGlobalObject> parent = xpc::NativeGlobal(globalObject);
if (NS_WARN_IF(!parent)) {
return NS_ERROR_FAILURE;
}
JS::Rooted<JS::Value> body(cx);
Read(nullptr, cx, &body, rv);
Read(parent, cx, &body, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}