tor-browser

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

EventWithOptionsRunnable.cpp (4821B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=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 https://mozilla.org/MPL/2.0/. */
      6 
      7 #include "EventWithOptionsRunnable.h"
      8 
      9 #include "MainThreadUtils.h"
     10 #include "WorkerScope.h"
     11 #include "js/GlobalObject.h"
     12 #include "js/RootingAPI.h"
     13 #include "js/StructuredClone.h"
     14 #include "js/Value.h"
     15 #include "mozilla/Assertions.h"
     16 #include "mozilla/DOMEventTargetHelper.h"
     17 #include "mozilla/ErrorResult.h"
     18 #include "mozilla/OwningNonNull.h"
     19 #include "mozilla/RefPtr.h"
     20 #include "mozilla/dom/Event.h"
     21 #include "mozilla/dom/MessagePort.h"
     22 #include "mozilla/dom/MessagePortBinding.h"
     23 #include "mozilla/dom/StructuredCloneHolder.h"
     24 #include "mozilla/dom/WorkerCommon.h"
     25 #include "mozilla/dom/WorkerRunnable.h"
     26 #include "nsCOMPtr.h"
     27 #include "nsContentUtils.h"
     28 #include "nsDebug.h"
     29 #include "nsGlobalWindowInner.h"
     30 #include "nsIGlobalObject.h"
     31 #include "nsJSPrincipals.h"
     32 #include "xpcpublic.h"
     33 
     34 namespace mozilla::dom {
     35 EventWithOptionsRunnable::EventWithOptionsRunnable(Worker& aWorker,
     36                                                   const char* aName)
     37    : WorkerDebuggeeRunnable(aName),
     38      StructuredCloneHolder(CloningSupported, TransferringSupported,
     39                            StructuredCloneScope::SameProcess) {}
     40 
     41 EventWithOptionsRunnable::~EventWithOptionsRunnable() = default;
     42 
     43 void EventWithOptionsRunnable::InitOptions(
     44    JSContext* aCx, JS::Handle<JS::Value> aOptions,
     45    const Sequence<JSObject*>& aTransferable, ErrorResult& aRv) {
     46  JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
     47 
     48  aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
     49                                                          &transferable);
     50  if (NS_WARN_IF(aRv.Failed())) {
     51    return;
     52  }
     53 
     54  JS::CloneDataPolicy clonePolicy;
     55  // DedicatedWorkers are always part of the same agent cluster.
     56  clonePolicy.allowIntraClusterClonableSharedObjects();
     57 
     58  MOZ_ASSERT(NS_IsMainThread());
     59  nsGlobalWindowInner* win = nsContentUtils::IncumbentInnerWindow();
     60  if (win && win->IsSharedMemoryAllowed()) {
     61    clonePolicy.allowSharedMemoryObjects();
     62  }
     63 
     64  Write(aCx, aOptions, transferable, clonePolicy, aRv);
     65 }
     66 
     67 // Cargo-culted from MesssageEventRunnable.
     68 bool EventWithOptionsRunnable::BuildAndFireEvent(
     69    JSContext* aCx, WorkerPrivate* aWorkerPrivate,
     70    DOMEventTargetHelper* aTarget) {
     71  IgnoredErrorResult rv;
     72  nsCOMPtr<nsIGlobalObject> parent = aTarget->GetParentObject();
     73 
     74  // For some workers without window, parent is null and we try to find it
     75  // from the JS Context.
     76  if (!parent) {
     77    JS::Rooted<JSObject*> globalObject(aCx, JS::CurrentGlobalOrNull(aCx));
     78    if (NS_WARN_IF(!globalObject)) {
     79      rv.ThrowDataCloneError("failed to get global object");
     80      OptionsDeserializeFailed(rv);
     81      return false;
     82    }
     83 
     84    parent = xpc::NativeGlobal(globalObject);
     85    if (NS_WARN_IF(!parent)) {
     86      rv.ThrowDataCloneError("failed to get parent");
     87      OptionsDeserializeFailed(rv);
     88      return false;
     89    }
     90  }
     91 
     92  MOZ_ASSERT(parent);
     93 
     94  JS::Rooted<JS::Value> options(aCx);
     95 
     96  JS::CloneDataPolicy cloneDataPolicy;
     97  if (parent->GetClientInfo().isSome() &&
     98      parent->GetClientInfo()->AgentClusterId().isSome() &&
     99      parent->GetClientInfo()->AgentClusterId()->Equals(
    100          aWorkerPrivate->AgentClusterId())) {
    101    cloneDataPolicy.allowIntraClusterClonableSharedObjects();
    102  }
    103 
    104  if (aWorkerPrivate->IsSharedMemoryAllowed()) {
    105    cloneDataPolicy.allowSharedMemoryObjects();
    106  }
    107 
    108  Read(parent, aCx, &options, cloneDataPolicy, rv);
    109 
    110  if (NS_WARN_IF(rv.Failed())) {
    111    OptionsDeserializeFailed(rv);
    112    return false;
    113  }
    114 
    115  Sequence<OwningNonNull<MessagePort>> ports;
    116  if (NS_WARN_IF(!TakeTransferredPortsAsSequence(ports))) {
    117    // TODO: Is this an appropriate type? What does this actually do?
    118    rv.ThrowDataCloneError("TakeTransferredPortsAsSequence failed");
    119    OptionsDeserializeFailed(rv);
    120    return false;
    121  }
    122 
    123  RefPtr<dom::Event> event = BuildEvent(aCx, parent, aTarget, options);
    124 
    125  if (NS_WARN_IF(!event)) {
    126    return false;
    127  }
    128 
    129  aTarget->DispatchEvent(*event);
    130  return true;
    131 }
    132 
    133 bool EventWithOptionsRunnable::WorkerRun(JSContext* aCx,
    134                                         WorkerPrivate* aWorkerPrivate) {
    135  MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
    136  MOZ_ASSERT(aWorkerPrivate->GlobalScope());
    137 
    138  // If the worker start shutting down, don't dispatch the event.
    139  if (NS_FAILED(
    140          aWorkerPrivate->GlobalScope()->CheckCurrentGlobalCorrectness())) {
    141    return true;
    142  }
    143 
    144  return BuildAndFireEvent(aCx, aWorkerPrivate, aWorkerPrivate->GlobalScope());
    145 }
    146 
    147 }  // namespace mozilla::dom