tor-browser

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

MessageEventRunnable.cpp (6458B)


      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 "MessageEventRunnable.h"
      8 
      9 #include "WorkerScope.h"
     10 #include "mozilla/dom/MessageEvent.h"
     11 #include "mozilla/dom/MessageEventBinding.h"
     12 #include "mozilla/dom/RootedDictionary.h"
     13 #include "nsQueryObject.h"
     14 
     15 namespace mozilla::dom {
     16 
     17 MessageEventRunnable::MessageEventRunnable(WorkerPrivate* aWorkerPrivate)
     18    : WorkerDebuggeeRunnable("MessageEventRunnable"),
     19      StructuredCloneHolder(CloningSupported, TransferringSupported,
     20                            StructuredCloneScope::SameProcess) {}
     21 
     22 bool MessageEventRunnable::DispatchDOMEvent(JSContext* aCx,
     23                                            WorkerPrivate* aWorkerPrivate,
     24                                            DOMEventTargetHelper* aTarget,
     25                                            bool aIsMainThread) {
     26  nsCOMPtr<nsIGlobalObject> parent = aTarget->GetParentObject();
     27 
     28  // For some workers without window, parent is null and we try to find it
     29  // from the JS Context.
     30  if (!parent) {
     31    JS::Rooted<JSObject*> globalObject(aCx, JS::CurrentGlobalOrNull(aCx));
     32    if (NS_WARN_IF(!globalObject)) {
     33      return false;
     34    }
     35 
     36    parent = xpc::NativeGlobal(globalObject);
     37    if (NS_WARN_IF(!parent)) {
     38      return false;
     39    }
     40  }
     41 
     42  MOZ_ASSERT(parent);
     43 
     44  JS::Rooted<JS::Value> messageData(aCx);
     45  IgnoredErrorResult rv;
     46 
     47  JS::CloneDataPolicy cloneDataPolicy;
     48  if (parent->GetClientInfo().isSome() &&
     49      parent->GetClientInfo()->AgentClusterId().isSome() &&
     50      parent->GetClientInfo()->AgentClusterId()->Equals(
     51          aWorkerPrivate->AgentClusterId())) {
     52    cloneDataPolicy.allowIntraClusterClonableSharedObjects();
     53  }
     54 
     55  if (aWorkerPrivate->IsSharedMemoryAllowed()) {
     56    cloneDataPolicy.allowSharedMemoryObjects();
     57  }
     58 
     59  Read(parent, aCx, &messageData, cloneDataPolicy, rv);
     60 
     61  if (NS_WARN_IF(rv.Failed())) {
     62    DispatchError(aCx, aTarget);
     63    return false;
     64  }
     65 
     66  Sequence<OwningNonNull<MessagePort>> ports;
     67  if (!TakeTransferredPortsAsSequence(ports)) {
     68    DispatchError(aCx, aTarget);
     69    return false;
     70  }
     71 
     72  RefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
     73  event->InitMessageEvent(nullptr, u"message"_ns, CanBubble::eNo,
     74                          Cancelable::eNo, messageData, u""_ns, u""_ns, nullptr,
     75                          ports);
     76 
     77  event->SetTrusted(true);
     78 
     79  aTarget->DispatchEvent(*event);
     80 
     81  return true;
     82 }
     83 
     84 bool MessageEventRunnable::WorkerRun(JSContext* aCx,
     85                                     WorkerPrivate* aWorkerPrivate) {
     86  MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
     87  MOZ_ASSERT(aWorkerPrivate->GlobalScope());
     88 
     89  // If the worker start shutting down, don't dispatch the message event.
     90  if (NS_FAILED(
     91          aWorkerPrivate->GlobalScope()->CheckCurrentGlobalCorrectness())) {
     92    return true;
     93  }
     94 
     95  return DispatchDOMEvent(aCx, aWorkerPrivate, aWorkerPrivate->GlobalScope(),
     96                          false);
     97 }
     98 
     99 void MessageEventRunnable::DispatchError(JSContext* aCx,
    100                                         DOMEventTargetHelper* aTarget) {
    101  RootedDictionary<MessageEventInit> init(aCx);
    102  init.mBubbles = false;
    103  init.mCancelable = false;
    104 
    105  RefPtr<Event> event =
    106      MessageEvent::Constructor(aTarget, u"messageerror"_ns, init);
    107  event->SetTrusted(true);
    108 
    109  aTarget->DispatchEvent(*event);
    110 }
    111 
    112 MessageEventToParentRunnable::MessageEventToParentRunnable(
    113    WorkerPrivate* aWorkerPrivate)
    114    : WorkerParentDebuggeeRunnable("MessageEventToParentRunnable"),
    115      StructuredCloneHolder(CloningSupported, TransferringSupported,
    116                            StructuredCloneScope::SameProcess) {}
    117 
    118 bool MessageEventToParentRunnable::DispatchDOMEvent(
    119    JSContext* aCx, WorkerPrivate* aWorkerPrivate,
    120    DOMEventTargetHelper* aTarget, bool aIsMainThread) {
    121  nsCOMPtr<nsIGlobalObject> parent = aTarget->GetParentObject();
    122 
    123  // For some workers without window, parent is null and we try to find it
    124  // from the JS Context.
    125  if (!parent) {
    126    JS::Rooted<JSObject*> globalObject(aCx, JS::CurrentGlobalOrNull(aCx));
    127    if (NS_WARN_IF(!globalObject)) {
    128      return false;
    129    }
    130 
    131    parent = xpc::NativeGlobal(globalObject);
    132    if (NS_WARN_IF(!parent)) {
    133      return false;
    134    }
    135  }
    136 
    137  MOZ_ASSERT(parent);
    138 
    139  JS::Rooted<JS::Value> messageData(aCx);
    140  IgnoredErrorResult rv;
    141 
    142  JS::CloneDataPolicy cloneDataPolicy;
    143  if (parent->GetClientInfo().isSome() &&
    144      parent->GetClientInfo()->AgentClusterId().isSome() &&
    145      parent->GetClientInfo()->AgentClusterId()->Equals(
    146          aWorkerPrivate->AgentClusterId())) {
    147    cloneDataPolicy.allowIntraClusterClonableSharedObjects();
    148  }
    149 
    150  if (aWorkerPrivate->IsSharedMemoryAllowed()) {
    151    cloneDataPolicy.allowSharedMemoryObjects();
    152  }
    153 
    154  Read(parent, aCx, &messageData, cloneDataPolicy, rv);
    155 
    156  if (NS_WARN_IF(rv.Failed())) {
    157    DispatchError(aCx, aTarget);
    158    return false;
    159  }
    160 
    161  Sequence<OwningNonNull<MessagePort>> ports;
    162  if (!TakeTransferredPortsAsSequence(ports)) {
    163    DispatchError(aCx, aTarget);
    164    return false;
    165  }
    166 
    167  RefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
    168  event->InitMessageEvent(nullptr, u"message"_ns, CanBubble::eNo,
    169                          Cancelable::eNo, messageData, u""_ns, u""_ns, nullptr,
    170                          ports);
    171 
    172  event->SetTrusted(true);
    173 
    174  aTarget->DispatchEvent(*event);
    175 
    176  return true;
    177 }
    178 
    179 bool MessageEventToParentRunnable::WorkerRun(JSContext* aCx,
    180                                             WorkerPrivate* aWorkerPrivate) {
    181  if (!aWorkerPrivate->IsAcceptingEvents()) {
    182    return true;
    183  }
    184 
    185  aWorkerPrivate->AssertInnerWindowIsCorrect();
    186 
    187  return DispatchDOMEvent(aCx, aWorkerPrivate,
    188                          aWorkerPrivate->ParentEventTargetRef(),
    189                          !aWorkerPrivate->GetParent());
    190 }
    191 
    192 void MessageEventToParentRunnable::DispatchError(
    193    JSContext* aCx, DOMEventTargetHelper* aTarget) {
    194  RootedDictionary<MessageEventInit> init(aCx);
    195  init.mBubbles = false;
    196  init.mCancelable = false;
    197 
    198  RefPtr<Event> event =
    199      MessageEvent::Constructor(aTarget, u"messageerror"_ns, init);
    200  event->SetTrusted(true);
    201 
    202  aTarget->DispatchEvent(*event);
    203 }
    204 
    205 }  // namespace mozilla::dom