2019-01-28 22:02:02 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "mozilla/dom/JSWindowActorBinding.h"
|
|
|
|
#include "mozilla/dom/JSWindowActorParent.h"
|
|
|
|
#include "mozilla/dom/WindowGlobalParent.h"
|
2019-02-08 16:02:08 +03:00
|
|
|
#include "mozilla/dom/MessageManagerBinding.h"
|
2019-01-28 22:02:02 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2019-05-10 18:01:33 +03:00
|
|
|
JSWindowActorParent::~JSWindowActorParent() { MOZ_ASSERT(!mManager); }
|
|
|
|
|
Bug 1541557: Part 1 - Use correct globals for JSWindowActors not in the shared JSM global. r=nika
The current JSWindowActor code assumes that all actors will be created in the
shared JSM global. This has a few problems:
1) For actors in other scopes, it enters the wrong compartment before decoding
messages, which leads to a compartment checker error when trying to call
message handlers. That could be fixed by just wrapping the result for the
caller, but that would lead to other problems. Aside from the efficiency
concerns of having to deal with cross-compartment wrappers, SpecialPowers in
particular would not be able to pass the resulting objects to unprivileged
scopes, since only SpecialPowers compartments have permissive CCWs enabled.
2) It also leads to the prototype objects for the actor instances being
created in the shared JSM scope, even when the actors themselves are defined
in other compartments. Again, aside from CCW efficiency issues, this prevents
the SpecialPowers instances from being accessed by the unprivileged scopes
that they're exposed to, since the prototype objects live in privileged scopes
which don't have permissive CCWs enabled.
This patch changes child actors to always create their objects in the global
of their constructors.
The parent objects are still created in the shared JSM global, but they now
wrap values for the appropriate compartment before trying to call message
handlers.
Differential Revision: https://phabricator.services.mozilla.com/D35051
--HG--
extra : rebase_source : 436ce516080812680d1433bf3ecbd12f91d88165
extra : source : 61fa2745733f3631488a3ecccc144823683b7b6d
2019-06-13 02:06:40 +03:00
|
|
|
nsIGlobalObject* JSWindowActorParent::GetParentObject() const {
|
|
|
|
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
|
|
|
}
|
|
|
|
|
2019-01-28 22:02:02 +03:00
|
|
|
JSObject* JSWindowActorParent::WrapObject(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) {
|
|
|
|
return JSWindowActorParent_Binding::Wrap(aCx, this, aGivenProto);
|
|
|
|
}
|
|
|
|
|
2019-06-06 13:13:30 +03:00
|
|
|
WindowGlobalParent* JSWindowActorParent::GetManager() const { return mManager; }
|
2019-01-28 22:02:02 +03:00
|
|
|
|
2019-02-21 22:53:59 +03:00
|
|
|
void JSWindowActorParent::Init(const nsAString& aName,
|
|
|
|
WindowGlobalParent* aManager) {
|
2019-01-28 22:02:02 +03:00
|
|
|
MOZ_ASSERT(!mManager, "Cannot Init() a JSWindowActorParent twice!");
|
2019-04-18 22:37:15 +03:00
|
|
|
SetName(aName);
|
2019-01-28 22:02:02 +03:00
|
|
|
mManager = aManager;
|
|
|
|
}
|
|
|
|
|
2019-02-08 16:02:08 +03:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
class AsyncMessageToChild : public Runnable {
|
|
|
|
public:
|
2019-04-18 22:37:15 +03:00
|
|
|
AsyncMessageToChild(const JSWindowActorMessageMeta& aMetadata,
|
2019-02-08 16:02:08 +03:00
|
|
|
ipc::StructuredCloneData&& aData,
|
2019-05-24 23:16:16 +03:00
|
|
|
WindowGlobalParent* aManager)
|
2019-02-08 16:02:08 +03:00
|
|
|
: mozilla::Runnable("WindowGlobalChild::HandleAsyncMessage"),
|
2019-04-18 22:37:15 +03:00
|
|
|
mMetadata(aMetadata),
|
2019-02-08 16:02:08 +03:00
|
|
|
mData(std::move(aData)),
|
2019-05-24 23:16:16 +03:00
|
|
|
mManager(aManager) {}
|
2019-02-08 16:02:08 +03:00
|
|
|
|
|
|
|
NS_IMETHOD Run() override {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread.");
|
2019-05-24 23:16:16 +03:00
|
|
|
RefPtr<WindowGlobalChild> child = mManager->GetChildActor();
|
|
|
|
if (child) {
|
|
|
|
child->ReceiveRawMessage(mMetadata, std::move(mData));
|
|
|
|
}
|
2019-02-08 16:02:08 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-04-18 22:37:15 +03:00
|
|
|
JSWindowActorMessageMeta mMetadata;
|
2019-02-08 16:02:08 +03:00
|
|
|
ipc::StructuredCloneData mData;
|
2019-05-24 23:16:16 +03:00
|
|
|
RefPtr<WindowGlobalParent> mManager;
|
2019-02-08 16:02:08 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2019-04-18 22:37:15 +03:00
|
|
|
void JSWindowActorParent::SendRawMessage(const JSWindowActorMessageMeta& aMeta,
|
|
|
|
ipc::StructuredCloneData&& aData,
|
|
|
|
ErrorResult& aRv) {
|
2019-08-08 19:06:52 +03:00
|
|
|
if (NS_WARN_IF(!mCanSend || !mManager || !mManager->CanSend())) {
|
2019-02-08 16:02:08 +03:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mManager->IsInProcess()) {
|
2019-04-18 22:37:15 +03:00
|
|
|
nsCOMPtr<nsIRunnable> runnable =
|
2019-05-24 23:16:16 +03:00
|
|
|
new AsyncMessageToChild(aMeta, std::move(aData), mManager);
|
2019-04-18 22:37:15 +03:00
|
|
|
NS_DispatchToMainThread(runnable.forget());
|
2019-02-08 16:02:08 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-04-18 22:37:15 +03:00
|
|
|
// Cross-process case - send data over WindowGlobalParent to other side.
|
2019-02-08 16:02:08 +03:00
|
|
|
ClonedMessageData msgData;
|
2019-05-08 22:34:47 +03:00
|
|
|
RefPtr<BrowserParent> browserParent = mManager->GetBrowserParent();
|
2019-04-10 00:38:15 +03:00
|
|
|
ContentParent* cp = browserParent->Manager();
|
2019-04-18 22:37:15 +03:00
|
|
|
if (NS_WARN_IF(!aData.BuildClonedMessageDataForParent(cp, msgData))) {
|
2019-02-08 16:02:08 +03:00
|
|
|
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-04-18 22:37:15 +03:00
|
|
|
if (NS_WARN_IF(!mManager->SendRawMessage(aMeta, msgData))) {
|
2019-02-08 16:02:08 +03:00
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-05 19:59:56 +03:00
|
|
|
CanonicalBrowsingContext* JSWindowActorParent::GetBrowsingContext(
|
|
|
|
ErrorResult& aRv) {
|
|
|
|
if (!mManager) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mManager->BrowsingContext();
|
|
|
|
}
|
|
|
|
|
2019-05-10 18:01:33 +03:00
|
|
|
void JSWindowActorParent::StartDestroy() {
|
2019-05-10 18:01:40 +03:00
|
|
|
JSWindowActor::StartDestroy();
|
2019-05-10 18:01:33 +03:00
|
|
|
mCanSend = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JSWindowActorParent::AfterDestroy() {
|
2019-05-10 18:01:40 +03:00
|
|
|
JSWindowActor::AfterDestroy();
|
2019-05-10 18:01:33 +03:00
|
|
|
mManager = nullptr;
|
|
|
|
}
|
|
|
|
|
2019-04-18 22:37:15 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(JSWindowActorParent, JSWindowActor, mManager)
|
2019-03-05 20:12:40 +03:00
|
|
|
|
2019-04-18 22:37:15 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(JSWindowActorParent,
|
|
|
|
JSWindowActor)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JSWindowActorParent)
|
|
|
|
NS_INTERFACE_MAP_END_INHERITING(JSWindowActor)
|
2019-01-28 22:02:02 +03:00
|
|
|
|
2019-04-18 22:37:15 +03:00
|
|
|
NS_IMPL_ADDREF_INHERITED(JSWindowActorParent, JSWindowActor)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(JSWindowActorParent, JSWindowActor)
|
2019-01-28 22:02:02 +03:00
|
|
|
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|