tor-browser

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

RemoteObjectProxy.h (8002B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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_RemoteObjectProxy_h
      8 #define mozilla_dom_RemoteObjectProxy_h
      9 
     10 #include "js/Proxy.h"
     11 #include "mozilla/Maybe.h"
     12 #include "mozilla/dom/MaybeCrossOriginObject.h"
     13 #include "mozilla/dom/PrototypeList.h"
     14 #include "xpcpublic.h"
     15 
     16 namespace mozilla::dom {
     17 
     18 class BrowsingContext;
     19 
     20 /**
     21 * Base class for RemoteObjectProxy. Implements the pieces of the handler that
     22 * don't depend on properties/methods of the specific WebIDL interface that this
     23 * proxy implements.
     24 */
     25 class RemoteObjectProxyBase : public js::BaseProxyHandler,
     26                              public MaybeCrossOriginObjectMixins {
     27 protected:
     28  explicit constexpr RemoteObjectProxyBase(prototypes::ID aPrototypeID)
     29      : BaseProxyHandler(&sCrossOriginProxyFamily, false),
     30        mPrototypeID(aPrototypeID) {}
     31 
     32 public:
     33  bool finalizeInBackground(const JS::Value& priv) const final { return false; }
     34 
     35  // Standard internal methods
     36  bool getOwnPropertyDescriptor(
     37      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
     38      JS::MutableHandle<Maybe<JS::PropertyDescriptor>> aDesc) const override;
     39  bool ownPropertyKeys(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     40                       JS::MutableHandleVector<jsid> aProps) const override;
     41  bool defineProperty(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     42                      JS::Handle<jsid> aId,
     43                      JS::Handle<JS::PropertyDescriptor> aDesc,
     44                      JS::ObjectOpResult& result) const final;
     45  bool delete_(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     46               JS::Handle<jsid> aId, JS::ObjectOpResult& aResult) const final;
     47 
     48  bool getPrototypeIfOrdinary(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     49                              bool* aIsOrdinary,
     50                              JS::MutableHandle<JSObject*> aProtop) const final;
     51 
     52  bool preventExtensions(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     53                         JS::ObjectOpResult& aResult) const final;
     54  bool isExtensible(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     55                    bool* aExtensible) const final;
     56 
     57  bool get(JSContext* cx, JS::Handle<JSObject*> aProxy,
     58           JS::Handle<JS::Value> aReceiver, JS::Handle<jsid> aId,
     59           JS::MutableHandle<JS::Value> aVp) const final;
     60  bool set(JSContext* cx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
     61           JS::Handle<JS::Value> aValue, JS::Handle<JS::Value> aReceiver,
     62           JS::ObjectOpResult& aResult) const final;
     63 
     64  // SpiderMonkey extensions
     65  bool getOwnEnumerablePropertyKeys(
     66      JSContext* aCx, JS::Handle<JSObject*> aProxy,
     67      JS::MutableHandleVector<jsid> aProps) const override;
     68  const char* className(JSContext* aCx,
     69                        JS::Handle<JSObject*> aProxy) const final;
     70 
     71  // Cross origin objects like RemoteWindowProxy should not participate in
     72  // private fields.
     73  virtual bool throwOnPrivateField() const override { return true; }
     74 
     75  bool isCallable(JSObject* aObj) const final { return false; }
     76  bool isConstructor(JSObject* aObj) const final { return false; }
     77 
     78  virtual void NoteChildren(JSObject* aProxy,
     79                            nsCycleCollectionTraversalCallback& aCb) const = 0;
     80 
     81  static void* GetNative(JSObject* aProxy) {
     82    return js::GetProxyPrivate(aProxy).toPrivate();
     83  }
     84 
     85  /**
     86   * Returns true if aProxy is a cross-process proxy that represents
     87   * an object implementing the WebIDL interface for aProtoID. aProxy
     88   * should be a proxy object.
     89   */
     90  static inline bool IsRemoteObjectProxy(JSObject* aProxy,
     91                                         prototypes::ID aProtoID) {
     92    const js::BaseProxyHandler* handler = js::GetProxyHandler(aProxy);
     93    return handler->family() == &sCrossOriginProxyFamily &&
     94           static_cast<const RemoteObjectProxyBase*>(handler)->mPrototypeID ==
     95               aProtoID;
     96  }
     97 
     98  /**
     99   * Returns true if aProxy is a cross-process proxy, no matter which
    100   * interface it represents.  aProxy should be a proxy object.
    101   */
    102  static inline bool IsRemoteObjectProxy(JSObject* aProxy) {
    103    const js::BaseProxyHandler* handler = js::GetProxyHandler(aProxy);
    104    return handler->family() == &sCrossOriginProxyFamily;
    105  }
    106 
    107 protected:
    108  /**
    109   * Gets an existing cached proxy object, or creates a new one and caches it.
    110   * aProxy will be null on failure. aNewObjectCreated is set to true if a new
    111   * object was created, callers probably need to addref the native in that
    112   * case. aNewObjectCreated can be true even if aProxy is null, if something
    113   * failed after creating the object.
    114   *
    115   * If aTransplantTo is non-null, failure is assumed to be unrecoverable, so
    116   * this will crash.
    117   */
    118  void GetOrCreateProxyObject(JSContext* aCx, void* aNative,
    119                              const JSClass* aClasp,
    120                              JS::Handle<JSObject*> aTransplantTo,
    121                              JS::MutableHandle<JSObject*> aProxy,
    122                              bool& aNewObjectCreated) const;
    123 
    124  const prototypes::ID mPrototypeID;
    125 
    126  friend struct SetDOMProxyInformation;
    127  static const char sCrossOriginProxyFamily;
    128 };
    129 
    130 /**
    131 * Proxy handler for proxy objects that represent an object implementing a
    132 * WebIDL interface that has cross-origin accessible properties/methods, and
    133 * which lives in a different process. The WebIDL code generator will create
    134 * arrays of cross-origin accessible properties/methods that can be used as
    135 * arguments to this template.
    136 *
    137 * The properties and methods can be cached on a holder JSObject, stored in a
    138 * reserved slot on the proxy object.
    139 *
    140 * The proxy objects that use a handler derived from this one are stored in a
    141 * hash map in the JS compartment's private (@see
    142 * xpc::CompartmentPrivate::GetRemoteProxyMap).
    143 */
    144 template <class Native, const CrossOriginProperties& P>
    145 class RemoteObjectProxy : public RemoteObjectProxyBase {
    146 public:
    147  void finalize(JS::GCContext* aGcx, JSObject* aProxy) const final {
    148    auto native = static_cast<Native*>(GetNative(aProxy));
    149    RefPtr<Native> self(dont_AddRef(native));
    150  }
    151 
    152  void GetProxyObject(JSContext* aCx, Native* aNative,
    153                      JS::Handle<JSObject*> aTransplantTo,
    154                      JS::MutableHandle<JSObject*> aProxy) const {
    155    bool objectCreated = false;
    156    GetOrCreateProxyObject(aCx, aNative, &sClass, aTransplantTo, aProxy,
    157                           objectCreated);
    158    if (objectCreated) {
    159      NS_ADDREF(aNative);
    160    }
    161  }
    162 
    163 protected:
    164  using RemoteObjectProxyBase::RemoteObjectProxyBase;
    165 
    166 private:
    167  bool EnsureHolder(JSContext* aCx, JS::Handle<JSObject*> aProxy,
    168                    JS::MutableHandle<JSObject*> aHolder) const final {
    169    return MaybeCrossOriginObjectMixins::EnsureHolder(
    170        aCx, aProxy, /* slot = */ 0, P, aHolder);
    171  }
    172 
    173  static const JSClass sClass;
    174 };
    175 
    176 /**
    177 * Returns true if aObj is a cross-process proxy object that
    178 * represents an object implementing the WebIDL interface for
    179 * aProtoID.
    180 */
    181 inline bool IsRemoteObjectProxy(JSObject* aObj, prototypes::ID aProtoID) {
    182  if (!js::IsProxy(aObj)) {
    183    return false;
    184  }
    185  return RemoteObjectProxyBase::IsRemoteObjectProxy(aObj, aProtoID);
    186 }
    187 
    188 /**
    189 * Returns true if aObj is a cross-process proxy object, no matter
    190 * which WebIDL interface it corresponds to.
    191 */
    192 inline bool IsRemoteObjectProxy(JSObject* aObj) {
    193  if (!js::IsProxy(aObj)) {
    194    return false;
    195  }
    196  return RemoteObjectProxyBase::IsRemoteObjectProxy(aObj);
    197 }
    198 
    199 /**
    200 * Return the browsing context for this remote outer window proxy.
    201 * Only call this function on remote outer window proxies.
    202 */
    203 BrowsingContext* GetBrowsingContext(JSObject* aProxy);
    204 
    205 }  // namespace mozilla::dom
    206 
    207 #endif /* mozilla_dom_RemoteObjectProxy_h */