tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

JSActor.h (6029B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_JSActor_h
      8 #define mozilla_dom_JSActor_h
      9 
     10 #include "ipc/EnumSerializer.h"
     11 #include "js/TypeDecls.h"
     12 #include "mozilla/dom/JSIPCValue.h"
     13 #include "mozilla/dom/PromiseNativeHandler.h"
     14 #include "nsCycleCollectionParticipant.h"
     15 #include "nsTHashMap.h"
     16 #include "nsWrapperCache.h"
     17 
     18 class nsIGlobalObject;
     19 class nsQueryJSActor;
     20 
     21 namespace mozilla {
     22 class ErrorResult;
     23 
     24 namespace dom {
     25 
     26 namespace ipc {
     27 class StructuredCloneData;
     28 }
     29 
     30 class JSActorManager;
     31 class JSActorMessageMeta;
     32 class QueryPromiseHandler;
     33 
     34 enum class JSActorMessageKind {
     35  Message,
     36  Query,
     37  QueryResolve,
     38  QueryReject,
     39  EndGuard_,
     40 };
     41 
     42 // Common base class for JSWindowActor{Parent,Child}.
     43 class JSActor : public nsISupports, public nsWrapperCache {
     44 public:
     45  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     46  NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(JSActor)
     47 
     48  explicit JSActor(nsISupports* aGlobal = nullptr);
     49 
     50  const nsCString& Name() const { return mName; }
     51  void GetName(nsCString& aName) { aName = Name(); }
     52 
     53  void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
     54                        JS::Handle<JS::Value> aObj,
     55                        JS::Handle<JS::Value> aTransfers, ErrorResult& aRv);
     56 
     57  already_AddRefed<Promise> SendQuery(JSContext* aCx,
     58                                      const nsAString& aMessageName,
     59                                      JS::Handle<JS::Value> aObj,
     60                                      ErrorResult& aRv);
     61 
     62  nsIGlobalObject* GetParentObject() const { return mGlobal; };
     63 
     64 protected:
     65  // Send the message described by the structured clone data |aData|, and the
     66  // message metadata |aMetadata|. The underlying transport should call the
     67  // |ReceiveMessage| method on the other side asynchronously.
     68  virtual void SendRawMessage(const JSActorMessageMeta& aMetadata,
     69                              JSIPCValue&& aData,
     70                              UniquePtr<ipc::StructuredCloneData> aStack,
     71                              ErrorResult& aRv) = 0;
     72 
     73  // Helper method to send an in-process raw message.
     74  using OtherSideCallback = std::function<already_AddRefed<JSActorManager>()>;
     75  static void SendRawMessageInProcess(
     76      const JSActorMessageMeta& aMeta, JSIPCValue&& aData,
     77      UniquePtr<ipc::StructuredCloneData> aStack,
     78      OtherSideCallback&& aGetOtherSide);
     79 
     80  virtual ~JSActor() = default;
     81 
     82  void Init(const nsACString& aName, bool aSendTyped);
     83 
     84  bool CanSend() const { return mCanSend; }
     85 
     86  void ThrowStateErrorForGetter(const char* aName, ErrorResult& aRv) const;
     87 
     88  void StartDestroy();
     89  void AfterDestroy();
     90 
     91  enum class CallbackFunction { DidDestroy, ActorCreated };
     92  void InvokeCallback(CallbackFunction callback);
     93 
     94  virtual void ClearManager() = 0;
     95 
     96 private:
     97  friend class JSActorManager;
     98  friend class ::nsQueryJSActor;  // for QueryInterfaceActor
     99 
    100  nsresult QueryInterfaceActor(const nsIID& aIID, void** aPtr);
    101 
    102  // Called by JSActorManager when they receive raw message data destined for
    103  // this actor.
    104  void ReceiveMessage(JSContext* aCx, const JSActorMessageMeta& aMetadata,
    105                      JS::Handle<JS::Value> aData, ErrorResult& aRv);
    106  void ReceiveQuery(JSContext* aCx, const JSActorMessageMeta& aMetadata,
    107                    JS::Handle<JS::Value> aData, ErrorResult& aRv);
    108  void ReceiveQueryReply(JSContext* aCx, const JSActorMessageMeta& aMetadata,
    109                         JS::Handle<JS::Value> aData, ErrorResult& aRv);
    110 
    111  // Call the actual `ReceiveMessage` method, and get the return value.
    112  void CallReceiveMessage(JSContext* aCx, const JSActorMessageMeta& aMetadata,
    113                          JS::Handle<JS::Value> aData,
    114                          JS::MutableHandle<JS::Value> aRetVal,
    115                          ErrorResult& aRv);
    116 
    117  // Helper object used while processing query messages to send the final reply
    118  // message.
    119  class QueryHandler final : public PromiseNativeHandler {
    120   public:
    121    NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL
    122    NS_DECL_CYCLE_COLLECTION_CLASS(QueryHandler)
    123 
    124    QueryHandler(JSActor* aActor, const JSActorMessageMeta& aMetadata,
    125                 Promise* aPromise);
    126 
    127    void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
    128                          ErrorResult& aRv) override;
    129 
    130    void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
    131                          ErrorResult& aRv) override;
    132 
    133   private:
    134    ~QueryHandler() = default;
    135 
    136    void SendReply(JSContext* aCx, JSActorMessageKind aKind,
    137                   JSIPCValue&& aData);
    138 
    139    RefPtr<JSActor> mActor;
    140    RefPtr<Promise> mPromise;
    141    nsString mMessageName;
    142    uint64_t mQueryId;
    143  };
    144 
    145  // A query which hasn't been resolved yet, along with metadata about what
    146  // query the promise is for.
    147  struct PendingQuery {
    148    RefPtr<Promise> mPromise;
    149    nsString mMessageName;
    150  };
    151 
    152  nsCOMPtr<nsIGlobalObject> mGlobal;
    153  nsCOMPtr<nsISupports> mWrappedJS;
    154  nsCString mName;
    155  nsTHashMap<nsUint64HashKey, PendingQuery> mPendingQueries;
    156  uint64_t mNextQueryId = 0;
    157  bool mCanSend = true;
    158 
    159  // If this is false, the receiver won't be doing type checking, so
    160  // use structured clone when sending. The security of the receiver does not
    161  // depend on this value, because it will make its own independent judgment
    162  // about whether the message needs to be typed.
    163  bool mSendTyped = true;
    164 };
    165 
    166 }  // namespace dom
    167 }  // namespace mozilla
    168 
    169 namespace IPC {
    170 
    171 template <>
    172 struct ParamTraits<mozilla::dom::JSActorMessageKind>
    173    : public ContiguousEnumSerializer<
    174          mozilla::dom::JSActorMessageKind,
    175          mozilla::dom::JSActorMessageKind::Message,
    176          mozilla::dom::JSActorMessageKind::EndGuard_> {};
    177 
    178 }  // namespace IPC
    179 
    180 #endif  // !defined(mozilla_dom_JSActor_h)