tor-browser

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

RemoteWorkerDebuggerChild.cpp (6129B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "RemoteWorkerDebuggerChild.h"
      6 
      7 #include "mozilla/dom/MessageEvent.h"
      8 #include "mozilla/dom/MessageEventBinding.h"
      9 #include "mozilla/dom/WorkerCommon.h"
     10 #include "mozilla/dom/WorkerPrivate.h"
     11 #include "mozilla/dom/WorkerRunnable.h"
     12 #include "mozilla/dom/WorkerScope.h"
     13 #include "mozilla/dom/workerinternals/ScriptLoader.h"
     14 #include "nsThreadUtils.h"
     15 
     16 namespace mozilla::dom {
     17 
     18 namespace {
     19 
     20 class RemoteDebuggerMessageEventRunnable final : public WorkerDebuggerRunnable {
     21  nsString mMessage;
     22 
     23 public:
     24  explicit RemoteDebuggerMessageEventRunnable(const nsAString& aMessage)
     25      : WorkerDebuggerRunnable("RemoteDebuggerMessageEventRunnable"),
     26        mMessage(aMessage) {}
     27 
     28 private:
     29  virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) override {
     30    return true;
     31  }
     32 
     33  virtual void PostDispatch(WorkerPrivate* aWorkerPrivate,
     34                            bool aDispatchResult) override {}
     35 
     36  virtual bool WorkerRun(JSContext* aCx,
     37                         WorkerPrivate* aWorkerPrivate) override {
     38    WorkerDebuggerGlobalScope* globalScope =
     39        aWorkerPrivate->DebuggerGlobalScope();
     40    MOZ_ASSERT(globalScope);
     41 
     42    JS::Rooted<JSString*> message(
     43        aCx, JS_NewUCStringCopyN(aCx, mMessage.get(), mMessage.Length()));
     44    if (!message) {
     45      return false;
     46    }
     47    JS::Rooted<JS::Value> data(aCx, JS::StringValue(message));
     48 
     49    RefPtr<MessageEvent> event =
     50        new MessageEvent(globalScope, nullptr, nullptr);
     51    event->InitMessageEvent(nullptr, u"message"_ns, CanBubble::eNo,
     52                            Cancelable::eYes, data, u""_ns, u""_ns, nullptr,
     53                            Sequence<OwningNonNull<MessagePort>>());
     54    event->SetTrusted(true);
     55 
     56    globalScope->DispatchEvent(*event);
     57    return true;
     58  }
     59 };
     60 
     61 class CompileRemoteDebuggerScriptRunnable final
     62    : public WorkerDebuggerRunnable {
     63  nsString mScriptURL;
     64  const mozilla::Encoding* mDocumentEncoding;
     65 
     66 public:
     67  CompileRemoteDebuggerScriptRunnable(
     68      WorkerPrivate* aWorkerPrivate, const nsAString& aScriptURL,
     69      const mozilla::Encoding* aDocumentEncoding)
     70      : WorkerDebuggerRunnable("CompileDebuggerScriptRunnable"),
     71        mScriptURL(aScriptURL),
     72        mDocumentEncoding(aDocumentEncoding) {}
     73 
     74 private:
     75  virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) override {
     76    return true;
     77  }
     78 
     79  virtual void PostDispatch(WorkerPrivate* aWorkerPrivate,
     80                            bool aDispatchResult) override {}
     81 
     82  virtual bool WorkerRun(JSContext* aCx,
     83                         WorkerPrivate* aWorkerPrivate) override {
     84    aWorkerPrivate->AssertIsOnWorkerThread();
     85 
     86    WorkerDebuggerGlobalScope* globalScope =
     87        aWorkerPrivate->CreateDebuggerGlobalScope(aCx);
     88    if (!globalScope) {
     89      NS_WARNING("Failed to make global!");
     90      return false;
     91    }
     92 
     93    if (NS_WARN_IF(!aWorkerPrivate->EnsureCSPEventListener())) {
     94      return false;
     95    }
     96 
     97    JS::Rooted<JSObject*> global(aCx, globalScope->GetWrapper());
     98 
     99    ErrorResult rv;
    100    JSAutoRealm ar(aCx, global);
    101    workerinternals::LoadMainScript(aWorkerPrivate, nullptr, mScriptURL,
    102                                    DebuggerScript, rv, mDocumentEncoding);
    103    rv.WouldReportJSException();
    104    // Explicitly ignore NS_BINDING_ABORTED on rv.  Or more precisely, still
    105    // return false and don't SetWorkerScriptExecutedSuccessfully() in that
    106    // case, but don't throw anything on aCx.  The idea is to not dispatch error
    107    // events if our load is canceled with that error code.
    108    if (rv.ErrorCodeIs(NS_BINDING_ABORTED)) {
    109      rv.SuppressException();
    110      return false;
    111    }
    112    // Make sure to propagate exceptions from rv onto aCx, so that they will get
    113    // reported after we return.  We do this for all failures on rv, because now
    114    // we're using rv to track all the state we care about.
    115    if (rv.MaybeSetPendingException(aCx)) {
    116      return false;
    117    }
    118 
    119    return true;
    120  }
    121 };
    122 
    123 }  // namespace
    124 
    125 RemoteWorkerDebuggerChild::RemoteWorkerDebuggerChild(
    126    WorkerPrivate* aWorkerPrivate) {
    127  MOZ_ASSERT_DEBUG_OR_FUZZING(aWorkerPrivate);
    128  aWorkerPrivate->AssertIsOnWorkerThread();
    129 }
    130 
    131 RemoteWorkerDebuggerChild::~RemoteWorkerDebuggerChild() {}
    132 
    133 mozilla::ipc::IPCResult RemoteWorkerDebuggerChild::RecvRegisterDone() {
    134  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    135  MOZ_ASSERT_DEBUG_OR_FUZZING(workerPrivate);
    136 
    137  workerPrivate->SetIsRemoteDebuggerRegistered(true);
    138  return IPC_OK();
    139 }
    140 
    141 mozilla::ipc::IPCResult RemoteWorkerDebuggerChild::RecvUnregisterDone() {
    142  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    143  MOZ_ASSERT_DEBUG_OR_FUZZING(workerPrivate);
    144 
    145  workerPrivate->SetIsRemoteDebuggerRegistered(false);
    146  return IPC_OK();
    147 }
    148 
    149 mozilla::ipc::IPCResult RemoteWorkerDebuggerChild::RecvInitialize(
    150    const nsString& aURL) {
    151  if (!mIsInitialized) {
    152    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    153    MOZ_ASSERT_DEBUG_OR_FUZZING(workerPrivate);
    154    RefPtr<CompileRemoteDebuggerScriptRunnable> runnable =
    155        new CompileRemoteDebuggerScriptRunnable(workerPrivate, aURL, nullptr);
    156    (void)NS_WARN_IF(!runnable->Dispatch(workerPrivate));
    157    (void)SendSetAsInitialized();
    158  }
    159  mIsInitialized = true;
    160  return IPC_OK();
    161 }
    162 
    163 mozilla::ipc::IPCResult RemoteWorkerDebuggerChild::RecvPostMessage(
    164    const nsString& aMessage) {
    165  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    166  MOZ_ASSERT_DEBUG_OR_FUZZING(workerPrivate);
    167  RefPtr<RemoteDebuggerMessageEventRunnable> runnable =
    168      new RemoteDebuggerMessageEventRunnable(aMessage);
    169  (void)NS_WARN_IF(!runnable->Dispatch(workerPrivate));
    170  return IPC_OK();
    171 }
    172 
    173 mozilla::ipc::IPCResult RemoteWorkerDebuggerChild::RecvSetDebuggerReady(
    174    const bool& aReady) {
    175  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    176  MOZ_ASSERT_DEBUG_OR_FUZZING(workerPrivate);
    177  workerPrivate->SetIsRemoteDebuggerReady(aReady);
    178  return IPC_OK();
    179 }
    180 
    181 }  // namespace mozilla::dom