tor-browser

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

RemoteOuterWindowProxy.cpp (6346B)


      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 #include "AccessCheck.h"
      8 #include "js/Proxy.h"
      9 #include "mozilla/Maybe.h"
     10 #include "mozilla/dom/BrowsingContext.h"
     11 #include "mozilla/dom/ProxyHandlerUtils.h"
     12 #include "mozilla/dom/RemoteObjectProxy.h"
     13 #include "mozilla/dom/WindowBinding.h"
     14 #include "mozilla/dom/WindowProxyHolder.h"
     15 #include "xpcprivate.h"
     16 
     17 namespace mozilla::dom {
     18 
     19 /**
     20 * RemoteOuterWindowProxy is the proxy handler for the WindowProxy objects for
     21 * Window objects that live in a different process.
     22 *
     23 * RemoteOuterWindowProxy holds a BrowsingContext, which is cycle collected.
     24 * This reference is declared to the cycle collector via NoteChildren().
     25 */
     26 
     27 class RemoteOuterWindowProxy
     28    : public RemoteObjectProxy<BrowsingContext,
     29                               Window_Binding::sCrossOriginProperties> {
     30 public:
     31  using Base = RemoteObjectProxy;
     32 
     33  constexpr RemoteOuterWindowProxy()
     34      : RemoteObjectProxy(prototypes::id::Window) {}
     35 
     36  // Standard internal methods
     37  bool getOwnPropertyDescriptor(
     38      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
     39      JS::MutableHandle<Maybe<JS::PropertyDescriptor>> aDesc) const final;
     40  bool ownPropertyKeys(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     41                       JS::MutableHandleVector<jsid> aProps) const final;
     42 
     43  // SpiderMonkey extensions
     44  bool getOwnEnumerablePropertyKeys(
     45      JSContext* cx, JS::Handle<JSObject*> proxy,
     46      JS::MutableHandleVector<jsid> props) const final;
     47 
     48  void NoteChildren(JSObject* aProxy,
     49                    nsCycleCollectionTraversalCallback& aCb) const override {
     50    CycleCollectionNoteChild(aCb,
     51                             static_cast<BrowsingContext*>(GetNative(aProxy)),
     52                             "JS::GetPrivate(obj)");
     53  }
     54 };
     55 
     56 static const RemoteOuterWindowProxy sSingleton;
     57 
     58 // Give RemoteOuterWindowProxy 2 reserved slots, like the other wrappers,
     59 // so JSObject::swap can swap it with CrossCompartmentWrappers without requiring
     60 // malloc.
     61 template <>
     62 const JSClass RemoteOuterWindowProxy::Base::sClass =
     63    PROXY_CLASS_DEF("Proxy", JSCLASS_HAS_RESERVED_SLOTS(2));
     64 
     65 bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
     66                               JS::Handle<JSObject*> aTransplantTo,
     67                               JS::MutableHandle<JSObject*> aRetVal) {
     68  MOZ_ASSERT(!aContext->GetDocShell(),
     69             "Why are we creating a RemoteOuterWindowProxy?");
     70 
     71  sSingleton.GetProxyObject(aCx, aContext, aTransplantTo, aRetVal);
     72  return !!aRetVal;
     73 }
     74 
     75 BrowsingContext* GetBrowsingContext(JSObject* aProxy) {
     76  MOZ_ASSERT(IsRemoteObjectProxy(aProxy, prototypes::id::Window));
     77  return static_cast<BrowsingContext*>(
     78      RemoteObjectProxyBase::GetNative(aProxy));
     79 }
     80 
     81 static bool WrapResult(JSContext* aCx, JS::Handle<JSObject*> aProxy,
     82                       BrowsingContext* aResult, JS::PropertyAttributes attrs,
     83                       JS::MutableHandle<Maybe<JS::PropertyDescriptor>> aDesc) {
     84  JS::Rooted<JS::Value> v(aCx);
     85  if (!ToJSValue(aCx, WindowProxyHolder(aResult), &v)) {
     86    return false;
     87  }
     88 
     89  aDesc.set(Some(JS::PropertyDescriptor::Data(v, attrs)));
     90  return true;
     91 }
     92 
     93 bool RemoteOuterWindowProxy::getOwnPropertyDescriptor(
     94    JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
     95    JS::MutableHandle<Maybe<JS::PropertyDescriptor>> aDesc) const {
     96  BrowsingContext* bc = GetBrowsingContext(aProxy);
     97  uint32_t index = GetArrayIndexFromId(aId);
     98  if (IsArrayIndex(index)) {
     99    Span<RefPtr<BrowsingContext>> children = bc->Children();
    100    if (index < children.Length()) {
    101      return WrapResult(aCx, aProxy, children[index],
    102                        {JS::PropertyAttribute::Configurable,
    103                         JS::PropertyAttribute::Enumerable},
    104                        aDesc);
    105    }
    106    return ReportCrossOriginDenial(aCx, aId, "access"_ns);
    107  }
    108 
    109  bool ok = CrossOriginGetOwnPropertyHelper(aCx, aProxy, aId, aDesc);
    110  if (!ok || aDesc.isSome()) {
    111    return ok;
    112  }
    113 
    114  // We don't need the "print" hack that nsOuterWindowProxy has, because pdf
    115  // documents are placed in a process based on their principal before the PDF
    116  // viewer changes principals around, so are always same-process with things
    117  // that are same-origin with their original principal and won't reach this
    118  // code in the cases when "print" should be accessible.
    119 
    120  if (aId.isString()) {
    121    nsAutoJSString str;
    122    if (!str.init(aCx, aId.toString())) {
    123      return false;
    124    }
    125 
    126    for (BrowsingContext* child : bc->Children()) {
    127      if (child->NameEquals(str)) {
    128        return WrapResult(aCx, aProxy, child,
    129                          {JS::PropertyAttribute::Configurable}, aDesc);
    130      }
    131    }
    132  }
    133 
    134  return CrossOriginPropertyFallback(aCx, aProxy, aId, aDesc);
    135 }
    136 
    137 bool AppendIndexedPropertyNames(JSContext* aCx, BrowsingContext* aContext,
    138                                JS::MutableHandleVector<jsid> aIndexedProps) {
    139  int32_t length = aContext->Children().Length();
    140  if (!aIndexedProps.reserve(aIndexedProps.length() + length)) {
    141    return false;
    142  }
    143 
    144  for (int32_t i = 0; i < length; ++i) {
    145    aIndexedProps.infallibleAppend(JS::PropertyKey::Int(i));
    146  }
    147  return true;
    148 }
    149 
    150 bool RemoteOuterWindowProxy::ownPropertyKeys(
    151    JSContext* aCx, JS::Handle<JSObject*> aProxy,
    152    JS::MutableHandleVector<jsid> aProps) const {
    153  BrowsingContext* bc = GetBrowsingContext(aProxy);
    154 
    155  // https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-ownpropertykeys:crossoriginownpropertykeys-(-o-)
    156  // step 3 to 5
    157  if (!AppendIndexedPropertyNames(aCx, bc, aProps)) {
    158    return false;
    159  }
    160 
    161  // https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-ownpropertykeys:crossoriginownpropertykeys-(-o-)
    162  // step 7
    163  return RemoteObjectProxy::ownPropertyKeys(aCx, aProxy, aProps);
    164 }
    165 
    166 bool RemoteOuterWindowProxy::getOwnEnumerablePropertyKeys(
    167    JSContext* aCx, JS::Handle<JSObject*> aProxy,
    168    JS::MutableHandleVector<jsid> aProps) const {
    169  return AppendIndexedPropertyNames(aCx, GetBrowsingContext(aProxy), aProps);
    170 }
    171 
    172 }  // namespace mozilla::dom