mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
ae31355192
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
137 lines
4.2 KiB
C++
137 lines
4.2 KiB
C++
/* -*- 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/. */
|
|
|
|
#ifndef mozilla_dom_JSWindowActor_h
|
|
#define mozilla_dom_JSWindowActor_h
|
|
|
|
#include "js/TypeDecls.h"
|
|
#include "ipc/IPCMessageUtils.h"
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/ErrorResult.h"
|
|
#include "mozilla/dom/PromiseNativeHandler.h"
|
|
#include "nsRefPtrHashtable.h"
|
|
|
|
class nsIGlobalObject;
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
enum class JSWindowActorMessageKind {
|
|
Message,
|
|
Query,
|
|
QueryResolve,
|
|
QueryReject,
|
|
EndGuard_,
|
|
};
|
|
|
|
class JSWindowActorMessageMeta;
|
|
class QueryPromiseHandler;
|
|
|
|
// Common base class for JSWindowActor{Parent,Child}.
|
|
class JSWindowActor : public nsISupports, public nsWrapperCache {
|
|
public:
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(JSWindowActor)
|
|
|
|
JSWindowActor();
|
|
|
|
enum class Type { Parent, Child };
|
|
enum class DestroyCallbackFunction { WillDestroy, DidDestroy };
|
|
|
|
const nsString& Name() const { return mName; }
|
|
|
|
void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
|
|
JS::Handle<JS::Value> aObj,
|
|
JS::Handle<JS::Value> aTransfers, ErrorResult& aRv);
|
|
|
|
already_AddRefed<Promise> SendQuery(JSContext* aCx,
|
|
const nsAString& aMessageName,
|
|
JS::Handle<JS::Value> aObj,
|
|
JS::Handle<JS::Value> aTransfers,
|
|
ErrorResult& aRv);
|
|
|
|
void ReceiveRawMessage(const JSWindowActorMessageMeta& aMetadata,
|
|
ipc::StructuredCloneData&& aData);
|
|
|
|
virtual nsIGlobalObject* GetParentObject() const = 0;
|
|
|
|
void RejectPendingQueries();
|
|
|
|
protected:
|
|
// Send the message described by the structured clone data |aData|, and the
|
|
// message metadata |aMetadata|. The underlying transport should call the
|
|
// |ReceiveMessage| method on the other side asynchronously.
|
|
virtual void SendRawMessage(const JSWindowActorMessageMeta& aMetadata,
|
|
ipc::StructuredCloneData&& aData,
|
|
ErrorResult& aRv) = 0;
|
|
|
|
virtual ~JSWindowActor() = default;
|
|
|
|
void SetName(const nsAString& aName);
|
|
|
|
void StartDestroy();
|
|
|
|
void AfterDestroy();
|
|
|
|
void DestroyCallback(DestroyCallbackFunction willDestroy);
|
|
|
|
private:
|
|
void ReceiveMessageOrQuery(JSContext* aCx,
|
|
const JSWindowActorMessageMeta& aMetadata,
|
|
JS::Handle<JS::Value> aData, ErrorResult& aRv);
|
|
|
|
void ReceiveQueryReply(JSContext* aCx,
|
|
const JSWindowActorMessageMeta& aMetadata,
|
|
JS::Handle<JS::Value> aData, ErrorResult& aRv);
|
|
|
|
// Helper object used while processing query messages to send the final reply
|
|
// message.
|
|
class QueryHandler final : public PromiseNativeHandler {
|
|
public:
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
NS_DECL_CYCLE_COLLECTION_CLASS(QueryHandler)
|
|
|
|
QueryHandler(JSWindowActor* aActor,
|
|
const JSWindowActorMessageMeta& aMetadata);
|
|
|
|
void RejectedCallback(JSContext* aCx,
|
|
JS::Handle<JS::Value> aValue) override;
|
|
|
|
void ResolvedCallback(JSContext* aCx,
|
|
JS::Handle<JS::Value> aValue) override;
|
|
|
|
private:
|
|
~QueryHandler() = default;
|
|
|
|
void SendReply(JSContext* aCx, JSWindowActorMessageKind aKind,
|
|
ipc::StructuredCloneData&& aData);
|
|
|
|
RefPtr<JSWindowActor> mActor;
|
|
nsString mMessageName;
|
|
uint64_t mQueryId;
|
|
};
|
|
|
|
nsString mName;
|
|
nsRefPtrHashtable<nsUint64HashKey, Promise> mPendingQueries;
|
|
uint64_t mNextQueryId;
|
|
};
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|
|
|
|
namespace IPC {
|
|
|
|
template <>
|
|
struct ParamTraits<mozilla::dom::JSWindowActorMessageKind>
|
|
: public ContiguousEnumSerializer<
|
|
mozilla::dom::JSWindowActorMessageKind,
|
|
mozilla::dom::JSWindowActorMessageKind::Message,
|
|
mozilla::dom::JSWindowActorMessageKind::EndGuard_> {};
|
|
|
|
} // namespace IPC
|
|
|
|
#endif // !defined(mozilla_dom_JSWindowActor_h)
|