tor-browser

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

WorkerScope.cpp (52770B)


      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 "mozilla/dom/WorkerScope.h"
      8 
      9 #include <stdio.h>
     10 
     11 #include <new>
     12 #include <utility>
     13 
     14 #include "Crypto.h"
     15 #include "GeckoProfiler.h"
     16 #include "MainThreadUtils.h"
     17 #include "ScriptLoader.h"
     18 #include "js/CompilationAndEvaluation.h"
     19 #include "js/CompileOptions.h"
     20 #include "js/RealmOptions.h"
     21 #include "js/RootingAPI.h"
     22 #include "js/SourceText.h"
     23 #include "js/Value.h"
     24 #include "js/Wrapper.h"
     25 #include "jsapi.h"
     26 #include "jsfriendapi.h"
     27 #include "mozilla/AlreadyAddRefed.h"
     28 #include "mozilla/BaseProfilerMarkersPrerequisites.h"
     29 #include "mozilla/CycleCollectedJSContext.h"
     30 #include "mozilla/ErrorResult.h"
     31 #include "mozilla/EventListenerManager.h"
     32 #include "mozilla/Logging.h"
     33 #include "mozilla/Maybe.h"
     34 #include "mozilla/MozPromise.h"
     35 #include "mozilla/Mutex.h"
     36 #include "mozilla/RefPtr.h"
     37 #include "mozilla/Result.h"
     38 #include "mozilla/StaticAnalysisFunctions.h"
     39 #include "mozilla/StorageAccess.h"
     40 #include "mozilla/UniquePtr.h"
     41 #include "mozilla/dom/AutoEntryScript.h"
     42 #include "mozilla/dom/BindingDeclarations.h"
     43 #include "mozilla/dom/BindingUtils.h"
     44 #include "mozilla/dom/BlobURLProtocolHandler.h"
     45 #include "mozilla/dom/CSPEvalChecker.h"
     46 #include "mozilla/dom/CallbackDebuggerNotification.h"
     47 #include "mozilla/dom/ClientSource.h"
     48 #include "mozilla/dom/Clients.h"
     49 #include "mozilla/dom/Console.h"
     50 #include "mozilla/dom/CookieStore.h"
     51 #include "mozilla/dom/DOMMozPromiseRequestHolder.h"
     52 #include "mozilla/dom/DOMString.h"
     53 #include "mozilla/dom/DebuggerNotification.h"
     54 #include "mozilla/dom/DebuggerNotificationBinding.h"
     55 #include "mozilla/dom/DebuggerNotificationManager.h"
     56 #include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
     57 #include "mozilla/dom/Fetch.h"
     58 #include "mozilla/dom/FontFaceSet.h"
     59 #include "mozilla/dom/IDBFactory.h"
     60 #include "mozilla/dom/ImageBitmap.h"
     61 #include "mozilla/dom/ImageBitmapSource.h"
     62 #include "mozilla/dom/MessagePortBinding.h"
     63 #include "mozilla/dom/Performance.h"
     64 #include "mozilla/dom/Promise.h"
     65 #include "mozilla/dom/PromiseWorkerProxy.h"
     66 #include "mozilla/dom/ScriptSettings.h"
     67 #include "mozilla/dom/SerializedStackHolder.h"
     68 #include "mozilla/dom/ServiceWorker.h"
     69 #include "mozilla/dom/ServiceWorkerDescriptor.h"
     70 #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
     71 #include "mozilla/dom/ServiceWorkerManager.h"
     72 #include "mozilla/dom/ServiceWorkerRegistration.h"
     73 #include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
     74 #include "mozilla/dom/ServiceWorkerUtils.h"
     75 #include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
     76 #include "mozilla/dom/SimpleGlobalObject.h"
     77 #include "mozilla/dom/TestUtils.h"
     78 #include "mozilla/dom/TimeoutHandler.h"
     79 #include "mozilla/dom/TimeoutManager.h"
     80 #include "mozilla/dom/TrustedTypeUtils.h"
     81 #include "mozilla/dom/TrustedTypesConstants.h"
     82 #include "mozilla/dom/VsyncWorkerChild.h"
     83 #include "mozilla/dom/WebTaskSchedulerWorker.h"
     84 #include "mozilla/dom/WindowOrWorkerGlobalScopeBinding.h"
     85 #include "mozilla/dom/WorkerCommon.h"
     86 #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
     87 #include "mozilla/dom/WorkerDocumentListener.h"
     88 #include "mozilla/dom/WorkerGlobalScopeBinding.h"
     89 #include "mozilla/dom/WorkerLocation.h"
     90 #include "mozilla/dom/WorkerNavigator.h"
     91 #include "mozilla/dom/WorkerPrivate.h"
     92 #include "mozilla/dom/WorkerRunnable.h"
     93 #include "mozilla/dom/cache/CacheStorage.h"
     94 #include "mozilla/dom/cache/Types.h"
     95 #include "mozilla/extensions/ExtensionBrowser.h"
     96 #include "mozilla/fallible.h"
     97 #include "mozilla/gfx/Rect.h"
     98 #include "mozilla/ipc/BackgroundChild.h"
     99 #include "mozilla/ipc/PBackgroundChild.h"
    100 #include "mozilla/ipc/PBackgroundSharedTypes.h"
    101 #include "nsAtom.h"
    102 #include "nsCOMPtr.h"
    103 #include "nsContentUtils.h"
    104 #include "nsDebug.h"
    105 #include "nsGkAtoms.h"
    106 #include "nsIEventTarget.h"
    107 #include "nsIGlobalObject.h"
    108 #include "nsIScriptError.h"
    109 #include "nsISerialEventTarget.h"
    110 #include "nsIWeakReference.h"
    111 #include "nsJSUtils.h"
    112 #include "nsLiteralString.h"
    113 #include "nsQueryObject.h"
    114 #include "nsRFPService.h"
    115 #include "nsReadableUtils.h"
    116 #include "nsString.h"
    117 #include "nsTArray.h"
    118 #include "nsTLiteralString.h"
    119 #include "nsThreadUtils.h"
    120 #include "nsWeakReference.h"
    121 #include "nsWrapperCacheInlines.h"
    122 #include "nscore.h"
    123 #include "xpcpublic.h"
    124 
    125 #ifdef ANDROID
    126 #  include <android/log.h>
    127 #endif
    128 
    129 #ifdef XP_WIN
    130 #  undef PostMessage
    131 #endif
    132 
    133 using mozilla::dom::cache::CacheStorage;
    134 using mozilla::dom::workerinternals::NamedWorkerGlobalScopeMixin;
    135 using mozilla::ipc::BackgroundChild;
    136 using mozilla::ipc::PBackgroundChild;
    137 using mozilla::ipc::PrincipalInfo;
    138 
    139 namespace mozilla::dom {
    140 
    141 static mozilla::LazyLogModule sWorkerScopeLog("WorkerScope");
    142 
    143 #ifdef LOG
    144 #  undef LOG
    145 #endif
    146 #define LOG(args) MOZ_LOG(sWorkerScopeLog, LogLevel::Debug, args);
    147 
    148 class WorkerScriptTimeoutHandler final : public ScriptTimeoutHandler {
    149 public:
    150  NS_DECL_ISUPPORTS_INHERITED
    151  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WorkerScriptTimeoutHandler,
    152                                           ScriptTimeoutHandler)
    153 
    154  WorkerScriptTimeoutHandler(JSContext* aCx, nsIGlobalObject* aGlobal,
    155                             const nsAString& aExpression)
    156      : ScriptTimeoutHandler(aCx, aGlobal, aExpression) {}
    157 
    158  MOZ_CAN_RUN_SCRIPT virtual bool Call(const char* aExecutionReason) override;
    159 
    160 private:
    161  virtual ~WorkerScriptTimeoutHandler() = default;
    162 };
    163 
    164 NS_IMPL_CYCLE_COLLECTION_INHERITED(WorkerScriptTimeoutHandler,
    165                                   ScriptTimeoutHandler)
    166 
    167 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerScriptTimeoutHandler)
    168 NS_INTERFACE_MAP_END_INHERITING(ScriptTimeoutHandler)
    169 
    170 NS_IMPL_ADDREF_INHERITED(WorkerScriptTimeoutHandler, ScriptTimeoutHandler)
    171 NS_IMPL_RELEASE_INHERITED(WorkerScriptTimeoutHandler, ScriptTimeoutHandler)
    172 
    173 bool WorkerScriptTimeoutHandler::Call(const char* aExecutionReason) {
    174  nsAutoMicroTask mt;
    175  AutoEntryScript aes(mGlobal, aExecutionReason, false);
    176 
    177  JSContext* cx = aes.cx();
    178  JS::CompileOptions options(cx);
    179  options.setFileAndLine(mCaller.FileName().get(), mCaller.mLine)
    180      .setNoScriptRval(true);
    181  options.setIntroductionType("domTimer");
    182 
    183  JS::Rooted<JS::Value> unused(cx);
    184  JS::SourceText<char16_t> srcBuf;
    185  if (!srcBuf.init(cx, mExpr.BeginReading(), mExpr.Length(),
    186                   JS::SourceOwnership::Borrowed) ||
    187      !JS::Evaluate(cx, options, srcBuf, &unused)) {
    188    if (!JS_IsExceptionPending(cx)) {
    189      return false;
    190    }
    191  }
    192 
    193  return true;
    194 };
    195 
    196 namespace workerinternals {
    197 void NamedWorkerGlobalScopeMixin::GetName(DOMString& aName) const {
    198  aName.AsAString() = mName;
    199 }
    200 static const char* GetTimeoutReasonString(Timeout* aTimeout) {
    201  switch (aTimeout->mReason) {
    202    case Timeout::Reason::eTimeoutOrInterval:
    203      if (aTimeout->mIsInterval) {
    204        return "setInterval handler";
    205      }
    206      return "setTimeout handler";
    207    case Timeout::Reason::eIdleCallbackTimeout:
    208      return "setIdleCallback handler (timed out)";
    209    case Timeout::Reason::eAbortSignalTimeout:
    210      return "AbortSignal timeout";
    211    case Timeout::Reason::eDelayedWebTaskTimeout:
    212      return "delayedWebTaskCallback handler (timed out)";
    213    case Timeout::Reason::eJSTimeout:
    214      return "JS timeout";
    215  }
    216  MOZ_CRASH("Unexpected enum value");
    217  return "";
    218 }
    219 }  // namespace workerinternals
    220 
    221 NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScopeBase)
    222 
    223 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScopeBase,
    224                                                  DOMEventTargetHelper)
    225  tmp->AssertIsOnWorkerThread();
    226  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
    227  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mModuleLoader)
    228  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSerialEventTarget)
    229  tmp->TraverseObjectsInGlobal(cb);
    230  // If we already exited WorkerThreadPrimaryRunnable, we will find it
    231  // nullptr and there is nothing left to do here on the WorkerPrivate,
    232  // in particular the timeouts have already been canceled and unlinked.
    233  if (tmp->mWorkerPrivate) {
    234    tmp->mWorkerPrivate->TraverseTimeouts(cb);
    235  }
    236 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    237 
    238 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScopeBase,
    239                                                DOMEventTargetHelper)
    240  tmp->AssertIsOnWorkerThread();
    241  NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
    242  NS_IMPL_CYCLE_COLLECTION_UNLINK(mModuleLoader)
    243  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSerialEventTarget)
    244  tmp->UnlinkObjectsInGlobal();
    245  // If we already exited WorkerThreadPrimaryRunnable, we will find it
    246  // nullptr and there is nothing left to do here on the WorkerPrivate,
    247  // in particular the timeouts have already been canceled and unlinked.
    248  if (tmp->mWorkerPrivate) {
    249    tmp->mWorkerPrivate->UnlinkTimeouts();
    250  }
    251  NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
    252 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    253 
    254 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerGlobalScopeBase,
    255                                               DOMEventTargetHelper)
    256  tmp->AssertIsOnWorkerThread();
    257 NS_IMPL_CYCLE_COLLECTION_TRACE_END
    258 
    259 NS_IMPL_ADDREF_INHERITED(WorkerGlobalScopeBase, DOMEventTargetHelper)
    260 NS_IMPL_RELEASE_INHERITED(WorkerGlobalScopeBase, DOMEventTargetHelper)
    261 
    262 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScopeBase)
    263  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
    264  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    265 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
    266 
    267 WorkerGlobalScopeBase::WorkerGlobalScopeBase(
    268    WorkerPrivate* aWorkerPrivate, UniquePtr<ClientSource> aClientSource)
    269    : mWorkerPrivate(aWorkerPrivate),
    270      mClientSource(std::move(aClientSource)),
    271      mSerialEventTarget(aWorkerPrivate->HybridEventTarget()) {
    272  mTimeoutManager = MakeUnique<dom::TimeoutManager>(
    273      *this, /* not used on workers */ 0, mSerialEventTarget,
    274      mWorkerPrivate->IsChromeWorker());
    275  LOG(("WorkerGlobalScopeBase::WorkerGlobalScopeBase [%p]", this));
    276  MOZ_ASSERT(mWorkerPrivate);
    277 #ifdef DEBUG
    278  mWorkerPrivate->AssertIsOnWorkerThread();
    279  mWorkerThreadUsedOnlyForAssert = PR_GetCurrentThread();
    280 #endif
    281  MOZ_ASSERT(mClientSource);
    282 
    283  MOZ_DIAGNOSTIC_ASSERT(
    284      mSerialEventTarget,
    285      "There should be an event target when a worker global is created.");
    286 
    287  // In workers, each DETH must have an owner. Because the global scope doesn't
    288  // have one, let's set it as owner of itself.
    289  BindToOwner(static_cast<nsIGlobalObject*>(this));
    290 }
    291 
    292 WorkerGlobalScopeBase::~WorkerGlobalScopeBase() = default;
    293 
    294 JSObject* WorkerGlobalScopeBase::GetGlobalJSObject() {
    295  AssertIsOnWorkerThread();
    296  return GetWrapper();
    297 }
    298 
    299 bool WorkerGlobalScopeBase::RunTimeoutHandler(mozilla::dom::Timeout* aTimeout) {
    300  // this is almost a copy of nsGlobalWindowInner::RunTimeoutHandler
    301 
    302  // Hold on to the timeout in case mExpr or mFunObj releases its
    303  // doc.
    304  // XXXbz Our caller guarantees it'll hold on to the timeout (because
    305  // we're MOZ_CAN_RUN_SCRIPT), so we can probably stop doing that...
    306  RefPtr<Timeout> timeout = aTimeout;
    307  Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout);
    308  timeout->mRunning = true;
    309 
    310  uint32_t nestingLevel = mTimeoutManager->GetNestingLevelForWorker();
    311  mTimeoutManager->SetNestingLevelForWorker(timeout->mNestingLevel);
    312 
    313  const char* reason = workerinternals::GetTimeoutReasonString(timeout);
    314 
    315  bool abortIntervalHandler;
    316  {
    317    RefPtr<TimeoutHandler> handler(timeout->mScriptHandler);
    318 
    319    CallbackDebuggerNotificationGuard guard(
    320        this, timeout->mIsInterval
    321                  ? DebuggerNotificationType::SetIntervalCallback
    322                  : DebuggerNotificationType::SetTimeoutCallback);
    323    abortIntervalHandler = !handler->Call(reason);
    324  }
    325 
    326  // If we received an uncatchable exception, do not schedule the timeout again.
    327  // This allows the slow script dialog to break easy DoS attacks like
    328  // setInterval(function() { while(1); }, 100);
    329  if (abortIntervalHandler) {
    330    // If it wasn't an interval timer to begin with, this does nothing.  If it
    331    // was, we'll treat it as a timeout that we just ran and discard it when
    332    // we return.
    333    timeout->mIsInterval = false;
    334  }
    335 
    336  // We ignore any failures from calling EvaluateString() on the context or
    337  // Call() on a Function here since we're in a loop
    338  // where we're likely to be running timeouts whose OS timers
    339  // didn't fire in time and we don't want to not fire those timers
    340  // now just because execution of one timer failed. We can't
    341  // propagate the error to anyone who cares about it from this
    342  // point anyway, and the script context should have already reported
    343  // the script error in the usual way - so we just drop it.
    344 
    345  mTimeoutManager->SetNestingLevelForWorker(nestingLevel);
    346 
    347  mTimeoutManager->EndRunningTimeout(last_running_timeout);
    348  timeout->mRunning = false;
    349 
    350  return timeout->mCleared;
    351 }
    352 
    353 JSObject* WorkerGlobalScopeBase::GetGlobalJSObjectPreserveColor() const {
    354  AssertIsOnWorkerThread();
    355  return GetWrapperPreserveColor();
    356 }
    357 
    358 bool WorkerGlobalScopeBase::IsSharedMemoryAllowed() const {
    359  AssertIsOnWorkerThread();
    360  return mWorkerPrivate->IsSharedMemoryAllowed();
    361 }
    362 
    363 bool WorkerGlobalScopeBase::ShouldResistFingerprinting(
    364    RFPTarget aTarget) const {
    365  AssertIsOnWorkerThread();
    366  return mWorkerPrivate->ShouldResistFingerprinting(aTarget);
    367 }
    368 
    369 OriginTrials WorkerGlobalScopeBase::Trials() const {
    370  AssertIsOnWorkerThread();
    371  return mWorkerPrivate->Trials();
    372 }
    373 
    374 StorageAccess WorkerGlobalScopeBase::GetStorageAccess() {
    375  AssertIsOnWorkerThread();
    376  return mWorkerPrivate->StorageAccess();
    377 }
    378 
    379 nsICookieJarSettings* WorkerGlobalScopeBase::GetCookieJarSettings() {
    380  AssertIsOnWorkerThread();
    381  return mWorkerPrivate->CookieJarSettings();
    382 }
    383 
    384 nsIURI* WorkerGlobalScopeBase::GetBaseURI() const {
    385  return mWorkerPrivate->GetBaseURI();
    386 }
    387 
    388 Maybe<ClientInfo> WorkerGlobalScopeBase::GetClientInfo() const {
    389  return Some(mClientSource->Info());
    390 }
    391 
    392 Maybe<ClientState> WorkerGlobalScopeBase::GetClientState() const {
    393  Result<ClientState, ErrorResult> res = mClientSource->SnapshotState();
    394  if (res.isOk()) {
    395    return Some(res.unwrap());
    396  }
    397 
    398  res.unwrapErr().SuppressException();
    399  return Nothing();
    400 }
    401 
    402 Maybe<ServiceWorkerDescriptor> WorkerGlobalScopeBase::GetController() const {
    403  return mClientSource->GetController();
    404 }
    405 
    406 mozilla::Result<mozilla::ipc::PrincipalInfo, nsresult>
    407 WorkerGlobalScopeBase::GetStorageKey() {
    408  AssertIsOnWorkerThread();
    409 
    410  const mozilla::ipc::PrincipalInfo& principalInfo =
    411      mWorkerPrivate->GetEffectiveStoragePrincipalInfo();
    412 
    413  // Block expanded and null principals, let content and system through.
    414  if (principalInfo.type() !=
    415          mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
    416      principalInfo.type() !=
    417          mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo) {
    418    return Err(NS_ERROR_DOM_SECURITY_ERR);
    419  }
    420 
    421  return principalInfo;
    422 }
    423 
    424 void WorkerGlobalScopeBase::Control(
    425    const ServiceWorkerDescriptor& aServiceWorker) {
    426  AssertIsOnWorkerThread();
    427  MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate->IsChromeWorker());
    428  MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate->Kind() != WorkerKindService);
    429 
    430  if (IsBlobURI(mWorkerPrivate->GetBaseURI())) {
    431    // Blob URL workers can only become controlled by inheriting from
    432    // their parent.  Make sure to note this properly.
    433    mClientSource->InheritController(aServiceWorker);
    434  } else {
    435    // Otherwise this is a normal interception and we simply record the
    436    // controller locally.
    437    mClientSource->SetController(aServiceWorker);
    438  }
    439 }
    440 
    441 nsresult WorkerGlobalScopeBase::Dispatch(
    442    already_AddRefed<nsIRunnable>&& aRunnable) const {
    443  return SerialEventTarget()->Dispatch(std::move(aRunnable),
    444                                       NS_DISPATCH_NORMAL);
    445 }
    446 
    447 nsISerialEventTarget* WorkerGlobalScopeBase::SerialEventTarget() const {
    448  AssertIsOnWorkerThread();
    449  return mSerialEventTarget;
    450 }
    451 
    452 // See also AutoJSAPI::ReportException
    453 void WorkerGlobalScopeBase::ReportError(JSContext* aCx,
    454                                        JS::Handle<JS::Value> aError,
    455                                        CallerType, ErrorResult& aRv) {
    456  JS::ErrorReportBuilder jsReport(aCx);
    457  JS::ExceptionStack exnStack(aCx, aError, nullptr);
    458  if (!jsReport.init(aCx, exnStack, JS::ErrorReportBuilder::NoSideEffects)) {
    459    return aRv.NoteJSContextException(aCx);
    460  }
    461 
    462  // Before invoking ReportError, put the exception back on the context,
    463  // because it may want to put it in its error events and has no other way
    464  // to get hold of it.  After we invoke ReportError, clear the exception on
    465  // cx(), just in case ReportError didn't.
    466  JS::SetPendingExceptionStack(aCx, exnStack);
    467  mWorkerPrivate->ReportError(aCx, jsReport.toStringResult(),
    468                              jsReport.report());
    469  JS_ClearPendingException(aCx);
    470 }
    471 
    472 void WorkerGlobalScopeBase::Atob(const nsAString& aAtob, nsAString& aOut,
    473                                 ErrorResult& aRv) const {
    474  AssertIsOnWorkerThread();
    475  aRv = nsContentUtils::Atob(aAtob, aOut);
    476 }
    477 
    478 void WorkerGlobalScopeBase::Btoa(const nsAString& aBtoa, nsAString& aOut,
    479                                 ErrorResult& aRv) const {
    480  AssertIsOnWorkerThread();
    481  aRv = nsContentUtils::Btoa(aBtoa, aOut);
    482 }
    483 
    484 already_AddRefed<Console> WorkerGlobalScopeBase::GetConsole(ErrorResult& aRv) {
    485  AssertIsOnWorkerThread();
    486 
    487  if (!mConsole) {
    488    mConsole = Console::Create(mWorkerPrivate->GetJSContext(), nullptr, aRv);
    489    if (NS_WARN_IF(aRv.Failed())) {
    490      return nullptr;
    491    }
    492  }
    493 
    494  RefPtr<Console> console = mConsole;
    495  return console.forget();
    496 }
    497 
    498 uint64_t WorkerGlobalScopeBase::WindowID() const {
    499  return mWorkerPrivate->WindowID();
    500 }
    501 
    502 NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope)
    503 
    504 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope,
    505                                                  WorkerGlobalScopeBase)
    506  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
    507  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
    508  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebTaskScheduler)
    509  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebTaskSchedulingState)
    510  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTrustedTypePolicyFactory)
    511  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
    512  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
    513  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet)
    514  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
    515  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
    516  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)
    517 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    518 
    519 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope,
    520                                                WorkerGlobalScopeBase)
    521  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
    522  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
    523  if (tmp->mWebTaskScheduler) {
    524    tmp->mWebTaskScheduler->Disconnect();
    525    NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebTaskScheduler)
    526  }
    527  NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebTaskSchedulingState)
    528  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTrustedTypePolicyFactory)
    529  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
    530  NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
    531  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet)
    532  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
    533  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
    534  NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)
    535 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    536 
    537 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(WorkerGlobalScope,
    538                                               WorkerGlobalScopeBase)
    539 
    540 WorkerGlobalScope::~WorkerGlobalScope() = default;
    541 
    542 void WorkerGlobalScope::NoteTerminating() {
    543  LOG(("WorkerGlobalScope::NoteTerminating [%p]", this));
    544  if (IsDying()) {
    545    return;
    546  }
    547 
    548  StartDying();
    549 }
    550 
    551 void WorkerGlobalScope::NoteShuttingDown() {
    552  MOZ_ASSERT(IsDying());
    553  LOG(("WorkerGlobalScope::NoteShuttingDown [%p]", this));
    554 
    555  if (mNavigator) {
    556    mNavigator->Invalidate();
    557    mNavigator = nullptr;
    558  }
    559 }
    560 
    561 Crypto* WorkerGlobalScope::GetCrypto(ErrorResult& aError) {
    562  AssertIsOnWorkerThread();
    563 
    564  if (!mCrypto) {
    565    mCrypto = new Crypto(this);
    566  }
    567 
    568  return mCrypto;
    569 }
    570 
    571 already_AddRefed<CacheStorage> WorkerGlobalScope::GetCaches(ErrorResult& aRv) {
    572  if (!mCacheStorage) {
    573    mCacheStorage = CacheStorage::CreateOnWorker(cache::DEFAULT_NAMESPACE, this,
    574                                                 mWorkerPrivate, aRv);
    575    mWorkerPrivate->NotifyStorageKeyUsed();
    576  }
    577 
    578  RefPtr<CacheStorage> ref = mCacheStorage;
    579  return ref.forget();
    580 }
    581 
    582 bool WorkerGlobalScope::IsSecureContext() const {
    583  bool globalSecure = JS::GetIsSecureContext(
    584      js::GetNonCCWObjectRealm(GetWrapperPreserveColor()));
    585  MOZ_ASSERT(globalSecure == mWorkerPrivate->IsSecureContext());
    586  return globalSecure;
    587 }
    588 
    589 already_AddRefed<WorkerLocation> WorkerGlobalScope::Location() {
    590  AssertIsOnWorkerThread();
    591 
    592  if (!mLocation) {
    593    mLocation = WorkerLocation::Create(mWorkerPrivate->GetLocationInfo());
    594    MOZ_ASSERT(mLocation);
    595  }
    596 
    597  RefPtr<WorkerLocation> location = mLocation;
    598  return location.forget();
    599 }
    600 
    601 already_AddRefed<WorkerNavigator> WorkerGlobalScope::Navigator() {
    602  AssertIsOnWorkerThread();
    603 
    604  if (!mNavigator) {
    605    bool onLine = mWorkerPrivate->OnLine();
    606    if (mWorkerPrivate->ShouldResistFingerprinting(
    607            RFPTarget::NetworkConnection)) {
    608      onLine = true;
    609    }
    610    mNavigator = WorkerNavigator::Create(onLine);
    611    MOZ_ASSERT(mNavigator);
    612  }
    613 
    614  RefPtr<WorkerNavigator> navigator = mNavigator;
    615  return navigator.forget();
    616 }
    617 
    618 already_AddRefed<WorkerNavigator> WorkerGlobalScope::GetExistingNavigator()
    619    const {
    620  AssertIsOnWorkerThread();
    621 
    622  RefPtr<WorkerNavigator> navigator = mNavigator;
    623  return navigator.forget();
    624 }
    625 
    626 FontFaceSet* WorkerGlobalScope::GetFonts(ErrorResult& aRv) {
    627  AssertIsOnWorkerThread();
    628 
    629  if (!mFontFaceSet) {
    630    mFontFaceSet = FontFaceSet::CreateForWorker(this, mWorkerPrivate);
    631    if (MOZ_UNLIKELY(!mFontFaceSet)) {
    632      aRv.ThrowInvalidStateError("Couldn't acquire worker reference");
    633      return nullptr;
    634    }
    635  }
    636 
    637  return mFontFaceSet;
    638 }
    639 
    640 OnErrorEventHandlerNonNull* WorkerGlobalScope::GetOnerror() {
    641  AssertIsOnWorkerThread();
    642 
    643  EventListenerManager* elm = GetExistingListenerManager();
    644  return elm ? elm->GetOnErrorEventHandler() : nullptr;
    645 }
    646 
    647 void WorkerGlobalScope::SetOnerror(OnErrorEventHandlerNonNull* aHandler) {
    648  AssertIsOnWorkerThread();
    649 
    650  EventListenerManager* elm = GetOrCreateListenerManager();
    651  if (elm) {
    652    elm->SetEventHandler(aHandler);
    653  }
    654 }
    655 
    656 void WorkerGlobalScope::ImportScripts(
    657    JSContext* aCx, const Sequence<OwningTrustedScriptURLOrString>& aScriptURLs,
    658    nsIPrincipal* aSubjectPrincipal, ErrorResult& aRv) {
    659  AssertIsOnWorkerThread();
    660 
    661  UniquePtr<SerializedStackHolder> stack;
    662  if (mWorkerPrivate->IsWatchedByDevTools()) {
    663    stack = GetCurrentStackForNetMonitor(aCx);
    664  }
    665 
    666  {
    667    nsTArray<nsString> scriptURLs;
    668    nsCOMPtr<nsIGlobalObject> pinnedGlobal = this;
    669    for (const auto& scriptURL : aScriptURLs) {
    670      constexpr nsLiteralString sink = u"WorkerGlobalScope importScripts"_ns;
    671      Maybe<nsAutoString> compliantStringHolder;
    672      const nsAString* compliantString =
    673          TrustedTypeUtils::GetTrustedTypesCompliantString(
    674              scriptURL, sink, kTrustedTypesOnlySinkGroup, *pinnedGlobal,
    675              aSubjectPrincipal, compliantStringHolder, aRv);
    676      if (aRv.Failed()) {
    677        return;
    678      }
    679      scriptURLs.AppendElement(*compliantString);
    680    }
    681    AUTO_PROFILER_MARKER_TEXT(
    682        "ImportScripts", JS, MarkerStack::Capture(),
    683        profiler_thread_is_being_profiled_for_markers()
    684            ? StringJoin(","_ns, scriptURLs,
    685                         [](nsACString& dest, const auto& scriptUrl) {
    686                           AppendUTF16toUTF8(
    687                               Substring(
    688                                   scriptUrl, 0,
    689                                   std::min(size_t(128), scriptUrl.Length())),
    690                               dest);
    691                         })
    692            : nsAutoCString{});
    693    workerinternals::Load(mWorkerPrivate, std::move(stack), scriptURLs,
    694                          WorkerScript, aRv);
    695  }
    696 }
    697 
    698 int32_t WorkerGlobalScope::SetTimeout(
    699    JSContext* aCx, const FunctionOrTrustedScriptOrString& aHandler,
    700    const int32_t aTimeout, const Sequence<JS::Value>& aArguments,
    701    nsIPrincipal* aSubjectPrincipal, ErrorResult& aRv) {
    702  return SetTimeoutOrInterval(aCx, aHandler, aTimeout, aArguments, false,
    703                              aSubjectPrincipal, aRv);
    704 }
    705 
    706 void WorkerGlobalScope::ClearTimeout(int32_t aHandle) {
    707  AssertIsOnWorkerThread();
    708 
    709  DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearTimeout);
    710 
    711  mWorkerPrivate->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
    712 }
    713 
    714 int32_t WorkerGlobalScope::SetInterval(
    715    JSContext* aCx, const FunctionOrTrustedScriptOrString& aHandler,
    716    const int32_t aTimeout, const Sequence<JS::Value>& aArguments,
    717    nsIPrincipal* aSubjectPrincipal, ErrorResult& aRv) {
    718  return SetTimeoutOrInterval(aCx, aHandler, aTimeout, aArguments, true,
    719                              aSubjectPrincipal, aRv);
    720 }
    721 
    722 void WorkerGlobalScope::ClearInterval(int32_t aHandle) {
    723  AssertIsOnWorkerThread();
    724 
    725  DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearInterval);
    726 
    727  mWorkerPrivate->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
    728 }
    729 
    730 int32_t WorkerGlobalScope::SetTimeoutOrInterval(
    731    JSContext* aCx, const FunctionOrTrustedScriptOrString& aHandler,
    732    const int32_t aTimeout, const Sequence<JS::Value>& aArguments,
    733    bool aIsInterval, nsIPrincipal* aSubjectPrincipal, ErrorResult& aRv) {
    734  AssertIsOnWorkerThread();
    735 
    736  DebuggerNotificationDispatch(
    737      this, aIsInterval ? DebuggerNotificationType::SetInterval
    738                        : DebuggerNotificationType::SetTimeout);
    739 
    740  if (aHandler.IsFunction()) {
    741    nsTArray<JS::Heap<JS::Value>> args;
    742    if (!args.AppendElements(aArguments, fallible)) {
    743      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    744      return 0;
    745    }
    746    RefPtr<TimeoutHandler> handler = new CallbackTimeoutHandler(
    747        aCx, this, &aHandler.GetAsFunction(), std::move(args));
    748    return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, aIsInterval,
    749                                      Timeout::Reason::eTimeoutOrInterval, aRv);
    750  }
    751 
    752  constexpr nsLiteralString sinkSetTimeout = u"WorkerGlobalScope setTimeout"_ns;
    753  constexpr nsLiteralString sinkSetInterval =
    754      u"WorkerGlobalScope setInterval"_ns;
    755  Maybe<nsAutoString> compliantStringHolder;
    756  nsCOMPtr<nsIGlobalObject> pinnedGlobal = this;
    757  const nsAString* compliantString =
    758      TrustedTypeUtils::GetTrustedTypesCompliantString(
    759          aHandler, aIsInterval ? sinkSetInterval : sinkSetTimeout,
    760          kTrustedTypesOnlySinkGroup, *pinnedGlobal, aSubjectPrincipal,
    761          compliantStringHolder, aRv);
    762  if (aRv.Failed()) {
    763    return 0;
    764  }
    765 
    766  bool allowEval = false;
    767  aRv = CSPEvalChecker::CheckForWorker(aCx, mWorkerPrivate, *compliantString,
    768                                       &allowEval);
    769  if (NS_WARN_IF(aRv.Failed()) || !allowEval) {
    770    return 0;
    771  }
    772 
    773  RefPtr<TimeoutHandler> handler =
    774      new WorkerScriptTimeoutHandler(aCx, this, *compliantString);
    775 
    776  return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, aIsInterval,
    777                                    Timeout::Reason::eTimeoutOrInterval, aRv);
    778 }
    779 
    780 bool WorkerGlobalScope::HasScheduledNormalOrHighPriorityWebTasks() const {
    781  if (!mWebTaskScheduler) {
    782    return false;
    783  }
    784  return mWebTaskScheduler->HasScheduledNormalOrHighPriorityWebTasks();
    785 }
    786 
    787 void WorkerGlobalScope::GetOrigin(nsAString& aOrigin) const {
    788  AssertIsOnWorkerThread();
    789  nsContentUtils::GetWebExposedOriginSerialization(
    790      mWorkerPrivate->GetPrincipal(), aOrigin);
    791 }
    792 
    793 bool WorkerGlobalScope::CrossOriginIsolated() const {
    794  return mWorkerPrivate->CrossOriginIsolated();
    795 }
    796 
    797 void WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const {
    798  AssertIsOnWorkerThread();
    799 
    800  if (!aString.WasPassed()) {
    801    return;
    802  }
    803 
    804  if (!nsJSUtils::DumpEnabled()) {
    805    return;
    806  }
    807 
    808  NS_ConvertUTF16toUTF8 str(aString.Value());
    809 
    810  MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug,
    811          ("[Worker.Dump] %s", str.get()));
    812 #ifdef ANDROID
    813  __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", str.get());
    814 #endif
    815  fputs(str.get(), stdout);
    816  fflush(stdout);
    817 }
    818 
    819 Performance* WorkerGlobalScope::GetPerformance() {
    820  AssertIsOnWorkerThread();
    821 
    822  if (!mPerformance) {
    823    mPerformance = Performance::CreateForWorker(this);
    824  }
    825 
    826  return mPerformance;
    827 }
    828 
    829 bool WorkerGlobalScope::IsInAutomation(JSContext* aCx, JSObject* /* unused */) {
    830  return GetWorkerPrivateFromContext(aCx)->IsInAutomation();
    831 }
    832 
    833 void WorkerGlobalScope::GetJSTestingFunctions(
    834    JSContext* aCx, JS::MutableHandle<JSObject*> aFunctions, ErrorResult& aRv) {
    835  JSObject* obj = js::GetTestingFunctions(aCx);
    836  if (!obj) {
    837    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    838    return;
    839  }
    840 
    841  aFunctions.set(obj);
    842 }
    843 
    844 already_AddRefed<Promise> WorkerGlobalScope::Fetch(
    845    const RequestOrUTF8String& aInput, const RequestInit& aInit,
    846    CallerType aCallerType, ErrorResult& aRv) {
    847  return FetchRequest(this, aInput, aInit, aCallerType, aRv);
    848 }
    849 
    850 already_AddRefed<IDBFactory> WorkerGlobalScope::GetIndexedDB(
    851    JSContext* aCx, ErrorResult& aErrorResult) {
    852  AssertIsOnWorkerThread();
    853 
    854  RefPtr<IDBFactory> indexedDB = mIndexedDB;
    855 
    856  if (!indexedDB) {
    857    StorageAccess access = mWorkerPrivate->StorageAccess();
    858 
    859    bool allowed = true;
    860    if (access == StorageAccess::eDeny) {
    861      NS_WARNING("IndexedDB is not allowed in this worker!");
    862      allowed = false;
    863    }
    864 
    865    if (ShouldPartitionStorage(access) &&
    866        !StoragePartitioningEnabled(access,
    867                                    mWorkerPrivate->CookieJarSettings())) {
    868      NS_WARNING("IndexedDB is not allowed in this worker!");
    869      allowed = false;
    870    }
    871 
    872    auto windowID = mWorkerPrivate->WindowID();
    873 
    874    auto principalInfoPtr =
    875        allowed ? MakeUnique<PrincipalInfo>(
    876                      mWorkerPrivate->GetEffectiveStoragePrincipalInfo())
    877                : nullptr;
    878    auto res = IDBFactory::CreateForWorker(this, std::move(principalInfoPtr),
    879                                           windowID);
    880 
    881    if (NS_WARN_IF(res.isErr())) {
    882      aErrorResult = res.unwrapErr();
    883      return nullptr;
    884    }
    885 
    886    indexedDB = res.unwrap();
    887    mIndexedDB = indexedDB;
    888  }
    889 
    890  mWorkerPrivate->NotifyStorageKeyUsed();
    891 
    892  return indexedDB.forget();
    893 }
    894 
    895 WebTaskScheduler* WorkerGlobalScope::Scheduler() {
    896  mWorkerPrivate->AssertIsOnWorkerThread();
    897 
    898  if (!mWebTaskScheduler) {
    899    mWebTaskScheduler = WebTaskScheduler::CreateForWorker(mWorkerPrivate);
    900  }
    901 
    902  MOZ_ASSERT(mWebTaskScheduler);
    903  return mWebTaskScheduler;
    904 }
    905 
    906 WebTaskScheduler* WorkerGlobalScope::GetExistingScheduler() const {
    907  return mWebTaskScheduler;
    908 }
    909 
    910 inline void WorkerGlobalScope::SetWebTaskSchedulingState(
    911    WebTaskSchedulingState* aState) {
    912  mWebTaskSchedulingState = aState;
    913 }
    914 
    915 already_AddRefed<Promise> WorkerGlobalScope::CreateImageBitmap(
    916    const ImageBitmapSource& aImage, const ImageBitmapOptions& aOptions,
    917    ErrorResult& aRv) {
    918  return ImageBitmap::Create(this, aImage, Nothing(), aOptions, aRv);
    919 }
    920 
    921 already_AddRefed<Promise> WorkerGlobalScope::CreateImageBitmap(
    922    const ImageBitmapSource& aImage, int32_t aSx, int32_t aSy, int32_t aSw,
    923    int32_t aSh, const ImageBitmapOptions& aOptions, ErrorResult& aRv) {
    924  return ImageBitmap::Create(
    925      this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aOptions, aRv);
    926 }
    927 
    928 // https://html.spec.whatwg.org/#structured-cloning
    929 void WorkerGlobalScope::StructuredClone(
    930    JSContext* aCx, JS::Handle<JS::Value> aValue,
    931    const StructuredSerializeOptions& aOptions,
    932    JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError) {
    933  nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRetval, aError);
    934 }
    935 
    936 mozilla::dom::DebuggerNotificationManager*
    937 WorkerGlobalScope::GetOrCreateDebuggerNotificationManager() {
    938  if (!mDebuggerNotificationManager) {
    939    mDebuggerNotificationManager = new DebuggerNotificationManager(this);
    940  }
    941 
    942  return mDebuggerNotificationManager;
    943 }
    944 
    945 mozilla::dom::DebuggerNotificationManager*
    946 WorkerGlobalScope::GetExistingDebuggerNotificationManager() {
    947  return mDebuggerNotificationManager;
    948 }
    949 
    950 Maybe<EventCallbackDebuggerNotificationType>
    951 WorkerGlobalScope::GetDebuggerNotificationType() const {
    952  return Some(EventCallbackDebuggerNotificationType::Global);
    953 }
    954 
    955 already_AddRefed<ServiceWorkerContainer>
    956 WorkerGlobalScope::GetServiceWorkerContainer() {
    957  return RefPtr(Navigator())->ServiceWorker();
    958 }
    959 
    960 RefPtr<ServiceWorker> WorkerGlobalScope::GetOrCreateServiceWorker(
    961    const ServiceWorkerDescriptor& aDescriptor) {
    962  RefPtr<ServiceWorker> ref;
    963  ForEachGlobalTeardownObserver(
    964      [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) {
    965        RefPtr<ServiceWorker> sw = do_QueryObject(aObserver);
    966        if (!sw || !sw->Descriptor().Matches(aDescriptor)) {
    967          return;
    968        }
    969 
    970        ref = std::move(sw);
    971        *aDoneOut = true;
    972      });
    973 
    974  if (!ref) {
    975    ref = ServiceWorker::Create(this, aDescriptor);
    976  }
    977 
    978  return ref;
    979 }
    980 
    981 RefPtr<ServiceWorkerRegistration>
    982 WorkerGlobalScope::GetServiceWorkerRegistration(
    983    const ServiceWorkerRegistrationDescriptor& aDescriptor) const {
    984  AssertIsOnWorkerThread();
    985  RefPtr<ServiceWorkerRegistration> ref;
    986  ForEachGlobalTeardownObserver(
    987      [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) {
    988        RefPtr<ServiceWorkerRegistration> swr = do_QueryObject(aObserver);
    989        if (!swr || !swr->MatchesDescriptor(aDescriptor)) {
    990          return;
    991        }
    992 
    993        ref = std::move(swr);
    994        *aDoneOut = true;
    995      });
    996  return ref;
    997 }
    998 
    999 RefPtr<ServiceWorkerRegistration>
   1000 WorkerGlobalScope::GetOrCreateServiceWorkerRegistration(
   1001    const ServiceWorkerRegistrationDescriptor& aDescriptor) {
   1002  AssertIsOnWorkerThread();
   1003  RefPtr<ServiceWorkerRegistration> ref =
   1004      GetServiceWorkerRegistration(aDescriptor);
   1005  if (!ref) {
   1006    ref = ServiceWorkerRegistration::CreateForWorker(mWorkerPrivate, this,
   1007                                                     aDescriptor);
   1008  }
   1009  return ref;
   1010 }
   1011 
   1012 mozilla::dom::StorageManager* WorkerGlobalScope::GetStorageManager() {
   1013  return RefPtr(Navigator())->Storage();
   1014 }
   1015 
   1016 // https://html.spec.whatwg.org/multipage/web-messaging.html#eligible-for-messaging
   1017 // * a WorkerGlobalScope object whose closing flag is false and whose worker
   1018 //   is not a suspendable worker.
   1019 bool WorkerGlobalScope::IsEligibleForMessaging() {
   1020  return mIsEligibleForMessaging;
   1021 }
   1022 
   1023 void WorkerGlobalScope::ReportToConsole(
   1024    uint32_t aErrorFlags, const nsCString& aCategory,
   1025    nsContentUtils::PropertiesFile aFile, const nsCString& aMessageName,
   1026    const nsTArray<nsString>& aParams,
   1027    const mozilla::SourceLocation& aLocation) {
   1028  WorkerPrivate::ReportErrorToConsole(aErrorFlags, aCategory, aFile,
   1029                                      aMessageName, aParams, aLocation);
   1030 }
   1031 
   1032 void WorkerGlobalScope::StorageAccessPermissionGranted() {
   1033  // Reset the IndexedDB factory.
   1034  mIndexedDB = nullptr;
   1035 
   1036  // Reset DOM Cache
   1037  mCacheStorage = nullptr;
   1038 }
   1039 
   1040 TrustedTypePolicyFactory* WorkerGlobalScope::TrustedTypes() {
   1041  AssertIsOnWorkerThread();
   1042  if (!mTrustedTypePolicyFactory) {
   1043    mTrustedTypePolicyFactory = MakeRefPtr<TrustedTypePolicyFactory>(this);
   1044  }
   1045 
   1046  return mTrustedTypePolicyFactory;
   1047 }
   1048 
   1049 bool WorkerGlobalScope::WindowInteractionAllowed() const {
   1050  AssertIsOnWorkerThread();
   1051  return mWindowInteractionsAllowed > 0;
   1052 }
   1053 
   1054 void WorkerGlobalScope::AllowWindowInteraction() {
   1055  AssertIsOnWorkerThread();
   1056  mWindowInteractionsAllowed++;
   1057 }
   1058 
   1059 void WorkerGlobalScope::ConsumeWindowInteraction() {
   1060  AssertIsOnWorkerThread();
   1061  MOZ_ASSERT(mWindowInteractionsAllowed);
   1062  mWindowInteractionsAllowed--;
   1063 }
   1064 
   1065 NS_IMPL_CYCLE_COLLECTION_INHERITED(DedicatedWorkerGlobalScope,
   1066                                   WorkerGlobalScope, mFrameRequestManager)
   1067 
   1068 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DedicatedWorkerGlobalScope,
   1069                                               WorkerGlobalScope)
   1070 NS_IMPL_CYCLE_COLLECTION_TRACE_END
   1071 
   1072 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(DedicatedWorkerGlobalScope,
   1073                                               WorkerGlobalScope)
   1074 
   1075 DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(
   1076    WorkerPrivate* aWorkerPrivate, UniquePtr<ClientSource> aClientSource,
   1077    const nsString& aName)
   1078    : WorkerGlobalScope(std::move(aWorkerPrivate), std::move(aClientSource)),
   1079      NamedWorkerGlobalScopeMixin(aName) {}
   1080 
   1081 bool DedicatedWorkerGlobalScope::WrapGlobalObject(
   1082    JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
   1083  AssertIsOnWorkerThread();
   1084  MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());
   1085 
   1086  JS::RealmOptions options;
   1087  mWorkerPrivate->CopyJSRealmOptions(options);
   1088 
   1089  xpc::SetPrefableRealmOptions(options);
   1090 
   1091  return DedicatedWorkerGlobalScope_Binding::Wrap(
   1092      aCx, this, this, options,
   1093      nsJSPrincipals::get(mWorkerPrivate->GetPrincipal()), aReflector);
   1094 }
   1095 
   1096 void DedicatedWorkerGlobalScope::PostMessage(
   1097    JSContext* aCx, JS::Handle<JS::Value> aMessage,
   1098    const Sequence<JSObject*>& aTransferable, ErrorResult& aRv) {
   1099  AssertIsOnWorkerThread();
   1100  mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv);
   1101 }
   1102 
   1103 void DedicatedWorkerGlobalScope::PostMessage(
   1104    JSContext* aCx, JS::Handle<JS::Value> aMessage,
   1105    const StructuredSerializeOptions& aOptions, ErrorResult& aRv) {
   1106  AssertIsOnWorkerThread();
   1107  mWorkerPrivate->PostMessageToParent(aCx, aMessage, aOptions.mTransfer, aRv);
   1108 }
   1109 
   1110 void DedicatedWorkerGlobalScope::Close() {
   1111  AssertIsOnWorkerThread();
   1112  mWorkerPrivate->CloseInternal();
   1113 }
   1114 
   1115 uint32_t DedicatedWorkerGlobalScope::RequestAnimationFrame(
   1116    FrameRequestCallback& aCallback, ErrorResult& aError) {
   1117  AssertIsOnWorkerThread();
   1118 
   1119  DebuggerNotificationDispatch(this,
   1120                               DebuggerNotificationType::RequestAnimationFrame);
   1121 
   1122  // Ensure the worker is associated with a window.
   1123  if (mWorkerPrivate->WindowID() == UINT64_MAX) {
   1124    aError.ThrowNotSupportedError("Worker has no associated owner Window");
   1125    return 0;
   1126  }
   1127 
   1128  if (!mVsyncChild) {
   1129    PBackgroundChild* bgChild = BackgroundChild::GetOrCreateForCurrentThread();
   1130    mVsyncChild = MakeRefPtr<VsyncWorkerChild>();
   1131 
   1132    if (!bgChild || !mVsyncChild->Initialize(mWorkerPrivate) ||
   1133        !bgChild->SendPVsyncConstructor(mVsyncChild)) {
   1134      mVsyncChild->Destroy();
   1135      mVsyncChild = nullptr;
   1136      aError.ThrowNotSupportedError(
   1137          "Worker failed to register for vsync to drive event loop");
   1138      return 0;
   1139    }
   1140  }
   1141 
   1142  if (!mDocListener) {
   1143    mDocListener = WorkerDocumentListener::Create(mWorkerPrivate);
   1144    if (!mDocListener) {
   1145      aError.ThrowNotSupportedError(
   1146          "Worker failed to register for document visibility events");
   1147      return 0;
   1148    }
   1149  }
   1150 
   1151  uint32_t handle = 0;
   1152  aError = mFrameRequestManager.Schedule(aCallback, &handle);
   1153  if (!aError.Failed() && mDocumentVisible) {
   1154    mVsyncChild->TryObserve();
   1155  }
   1156  return handle;
   1157 }
   1158 
   1159 void DedicatedWorkerGlobalScope::CancelAnimationFrame(uint32_t aHandle,
   1160                                                      ErrorResult& aError) {
   1161  AssertIsOnWorkerThread();
   1162 
   1163  DebuggerNotificationDispatch(this,
   1164                               DebuggerNotificationType::CancelAnimationFrame);
   1165 
   1166  // Ensure the worker is associated with a window.
   1167  if (mWorkerPrivate->WindowID() == UINT64_MAX) {
   1168    aError.ThrowNotSupportedError("Worker has no associated owner Window");
   1169    return;
   1170  }
   1171 
   1172  mFrameRequestManager.Cancel(aHandle);
   1173  if (mVsyncChild && mFrameRequestManager.IsEmpty()) {
   1174    mVsyncChild->TryUnobserve();
   1175  }
   1176 }
   1177 
   1178 void DedicatedWorkerGlobalScope::OnDocumentVisible(bool aVisible) {
   1179  AssertIsOnWorkerThread();
   1180 
   1181  mDocumentVisible = aVisible;
   1182 
   1183  // We only change state immediately when we become visible. If we become
   1184  // hidden, then we wait for the next vsync tick to apply that.
   1185  if (aVisible && !mFrameRequestManager.IsEmpty()) {
   1186    mVsyncChild->TryObserve();
   1187  }
   1188 }
   1189 
   1190 void DedicatedWorkerGlobalScope::OnVsync(const VsyncEvent& aVsync) {
   1191  AssertIsOnWorkerThread();
   1192 
   1193  if (mFrameRequestManager.IsEmpty() || !mDocumentVisible) {
   1194    // If we ever receive a vsync event, and there are still no callbacks to
   1195    // process, or we remain hidden, we should disable observing them. By
   1196    // waiting an extra tick, we ensure we minimize extra IPC for content that
   1197    // does not call requestFrameAnimation directly during the callback, or
   1198    // that is rapidly toggling between hidden and visible.
   1199    mVsyncChild->TryUnobserve();
   1200    return;
   1201  }
   1202 
   1203  RefPtr<DedicatedWorkerGlobalScope> scope(this);
   1204  CallbackDebuggerNotificationGuard guard(
   1205      scope, DebuggerNotificationType::RequestAnimationFrameCallback);
   1206 
   1207  // This is similar to what we do in nsRefreshDriver::RunFrameRequestCallbacks
   1208  // and Performance::TimeStampToDOMHighResForRendering in order to have the
   1209  // same behaviour for requestAnimationFrame on both the main and worker
   1210  // threads.
   1211  DOMHighResTimeStamp timeStamp = 0;
   1212  if (!aVsync.mTime.IsNull()) {
   1213    timeStamp = mWorkerPrivate->TimeStampToDOMHighRes(aVsync.mTime);
   1214    // 0 is an inappropriate mixin for this this area; however CSS Animations
   1215    // needs to have it's Time Reduction Logic refactored, so it's currently
   1216    // only clamping for RFP mode. RFP mode gives a much lower time precision,
   1217    // so we accept the security leak here for now.
   1218    timeStamp = nsRFPService::ReduceTimePrecisionAsMSecsRFPOnly(
   1219        timeStamp, 0, this->GetRTPCallerType());
   1220  }
   1221 
   1222  FrameRequestManager::FiringCallbacks callbacks(mFrameRequestManager);
   1223 
   1224  for (auto& callback : callbacks.mList) {
   1225    if (callback.mCancelled) {
   1226      continue;
   1227    }
   1228 
   1229    // MOZ_KnownLive is OK, because the stack array `callbacks` keeps the
   1230    // callback alive and the mCallback strong reference can't be mutated by
   1231    // the call.
   1232    LogFrameRequestCallback::Run run(callback.mCallback);
   1233    MOZ_KnownLive(callback.mCallback)->Call(timeStamp);
   1234  }
   1235 }
   1236 
   1237 SharedWorkerGlobalScope::SharedWorkerGlobalScope(
   1238    WorkerPrivate* aWorkerPrivate, UniquePtr<ClientSource> aClientSource,
   1239    const nsString& aName)
   1240    : WorkerGlobalScope(std::move(aWorkerPrivate), std::move(aClientSource)),
   1241      NamedWorkerGlobalScopeMixin(aName) {}
   1242 
   1243 bool SharedWorkerGlobalScope::WrapGlobalObject(
   1244    JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
   1245  AssertIsOnWorkerThread();
   1246  MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
   1247 
   1248  JS::RealmOptions options;
   1249  mWorkerPrivate->CopyJSRealmOptions(options);
   1250 
   1251  return SharedWorkerGlobalScope_Binding::Wrap(
   1252      aCx, this, this, options,
   1253      nsJSPrincipals::get(mWorkerPrivate->GetPrincipal()), aReflector);
   1254 }
   1255 
   1256 void SharedWorkerGlobalScope::Close() {
   1257  AssertIsOnWorkerThread();
   1258  mWorkerPrivate->CloseInternal();
   1259 }
   1260 
   1261 NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope,
   1262                                   mClients, mExtensionBrowser, mRegistration,
   1263                                   mCookieStore)
   1264 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerGlobalScope)
   1265 NS_INTERFACE_MAP_END_INHERITING(WorkerGlobalScope)
   1266 
   1267 NS_IMPL_ADDREF_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
   1268 NS_IMPL_RELEASE_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
   1269 
   1270 ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(
   1271    WorkerPrivate* aWorkerPrivate, UniquePtr<ClientSource> aClientSource,
   1272    const ServiceWorkerRegistrationDescriptor& aRegistrationDescriptor)
   1273    : WorkerGlobalScope(std::move(aWorkerPrivate), std::move(aClientSource)),
   1274      mScope(NS_ConvertUTF8toUTF16(aRegistrationDescriptor.Scope()))
   1275 
   1276      // Eagerly create the registration because we will need to receive
   1277      // updates about the state of the registration.  We can't wait until
   1278      // first access to start receiving these.
   1279      ,
   1280      mRegistration(
   1281          GetOrCreateServiceWorkerRegistration(aRegistrationDescriptor)) {}
   1282 
   1283 ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope() = default;
   1284 
   1285 bool ServiceWorkerGlobalScope::WrapGlobalObject(
   1286    JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
   1287  AssertIsOnWorkerThread();
   1288  MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
   1289 
   1290  JS::RealmOptions options;
   1291  mWorkerPrivate->CopyJSRealmOptions(options);
   1292 
   1293  return ServiceWorkerGlobalScope_Binding::Wrap(
   1294      aCx, this, this, options,
   1295      nsJSPrincipals::get(mWorkerPrivate->GetPrincipal()), aReflector);
   1296 }
   1297 
   1298 already_AddRefed<Clients> ServiceWorkerGlobalScope::GetClients() {
   1299  if (!mClients) {
   1300    mClients = new Clients(this);
   1301  }
   1302 
   1303  RefPtr<Clients> ref = mClients;
   1304  return ref.forget();
   1305 }
   1306 
   1307 ServiceWorkerRegistration* ServiceWorkerGlobalScope::Registration() {
   1308  return mRegistration;
   1309 }
   1310 
   1311 EventHandlerNonNull* ServiceWorkerGlobalScope::GetOnfetch() {
   1312  AssertIsOnWorkerThread();
   1313 
   1314  return GetEventHandler(nsGkAtoms::onfetch);
   1315 }
   1316 
   1317 namespace {
   1318 
   1319 class ReportFetchListenerWarningRunnable final : public Runnable {
   1320  const nsCString mScope;
   1321  mozilla::JSCallingLocation mCaller;
   1322 
   1323 public:
   1324  explicit ReportFetchListenerWarningRunnable(const nsString& aScope)
   1325      : mozilla::Runnable("ReportFetchListenerWarningRunnable"),
   1326        mScope(NS_ConvertUTF16toUTF8(aScope)) {
   1327    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
   1328    MOZ_ASSERT(workerPrivate);
   1329    JSContext* cx = workerPrivate->GetJSContext();
   1330    MOZ_ASSERT(cx);
   1331 
   1332    mCaller = JSCallingLocation::Get(cx);
   1333  }
   1334 
   1335  NS_IMETHOD
   1336  Run() override {
   1337    AssertIsOnMainThread();
   1338 
   1339    ServiceWorkerManager::LocalizeAndReportToAllClients(
   1340        mScope, "ServiceWorkerNoFetchHandler", nsTArray<nsString>{},
   1341        nsIScriptError::warningFlag, mCaller.FileName(), u""_ns, mCaller.mLine,
   1342        mCaller.mColumn);
   1343 
   1344    return NS_OK;
   1345  }
   1346 };
   1347 
   1348 }  // anonymous namespace
   1349 
   1350 void ServiceWorkerGlobalScope::NoteFetchHandlerWasAdded() const {
   1351  if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
   1352    RefPtr<Runnable> r = new ReportFetchListenerWarningRunnable(mScope);
   1353    mWorkerPrivate->DispatchToMainThreadForMessaging(r.forget());
   1354  }
   1355  mWorkerPrivate->SetFetchHandlerWasAdded();
   1356 }
   1357 
   1358 void ServiceWorkerGlobalScope::SetOnfetch(
   1359    mozilla::dom::EventHandlerNonNull* aCallback) {
   1360  AssertIsOnWorkerThread();
   1361 
   1362  if (aCallback) {
   1363    NoteFetchHandlerWasAdded();
   1364  }
   1365  SetEventHandler(nsGkAtoms::onfetch, aCallback);
   1366 }
   1367 
   1368 void ServiceWorkerGlobalScope::EventListenerAdded(nsAtom* aType) {
   1369  AssertIsOnWorkerThread();
   1370 
   1371  if (aType == nsGkAtoms::onfetch) {
   1372    NoteFetchHandlerWasAdded();
   1373  }
   1374 }
   1375 
   1376 already_AddRefed<Promise> ServiceWorkerGlobalScope::SkipWaiting(
   1377    ErrorResult& aRv) {
   1378  AssertIsOnWorkerThread();
   1379  MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
   1380 
   1381  RefPtr<Promise> promise = Promise::Create(this, aRv);
   1382  if (NS_WARN_IF(aRv.Failed())) {
   1383    return nullptr;
   1384  }
   1385 
   1386  using MozPromiseType =
   1387      decltype(mWorkerPrivate->SetServiceWorkerSkipWaitingFlag())::element_type;
   1388  auto holder = MakeRefPtr<DOMMozPromiseRequestHolder<MozPromiseType>>(this);
   1389 
   1390  mWorkerPrivate->SetServiceWorkerSkipWaitingFlag()
   1391      ->Then(GetCurrentSerialEventTarget(), __func__,
   1392             [holder, promise](const MozPromiseType::ResolveOrRejectValue&) {
   1393               holder->Complete();
   1394               promise->MaybeResolveWithUndefined();
   1395             })
   1396      ->Track(*holder);
   1397 
   1398  return promise.forget();
   1399 }
   1400 
   1401 SafeRefPtr<extensions::ExtensionBrowser>
   1402 ServiceWorkerGlobalScope::AcquireExtensionBrowser() {
   1403  if (!mExtensionBrowser) {
   1404    mExtensionBrowser = MakeSafeRefPtr<extensions::ExtensionBrowser>(this);
   1405  }
   1406 
   1407  return mExtensionBrowser.clonePtr();
   1408 }
   1409 
   1410 already_AddRefed<CookieStore> ServiceWorkerGlobalScope::CookieStore() {
   1411  if (!mCookieStore) {
   1412    mCookieStore = CookieStore::Create(this);
   1413  }
   1414 
   1415  return do_AddRef(mCookieStore);
   1416 }
   1417 
   1418 bool WorkerDebuggerGlobalScope::WrapGlobalObject(
   1419    JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
   1420  AssertIsOnWorkerThread();
   1421 
   1422  JS::RealmOptions options;
   1423  mWorkerPrivate->CopyJSRealmOptions(options);
   1424 
   1425  return WorkerDebuggerGlobalScope_Binding::Wrap(
   1426      aCx, this, this, options,
   1427      nsJSPrincipals::get(mWorkerPrivate->GetPrincipal()), aReflector);
   1428 }
   1429 
   1430 void WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
   1431                                          JS::MutableHandle<JSObject*> aGlobal,
   1432                                          ErrorResult& aRv) {
   1433  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
   1434  if (!scope) {
   1435    aRv.Throw(NS_ERROR_FAILURE);
   1436    return;
   1437  }
   1438 
   1439  aGlobal.set(scope->GetWrapper());
   1440 }
   1441 
   1442 void WorkerDebuggerGlobalScope::CreateSandbox(
   1443    JSContext* aCx, const nsAString& aName, JS::Handle<JSObject*> aPrototype,
   1444    JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv) {
   1445  AssertIsOnWorkerThread();
   1446 
   1447  aResult.set(nullptr);
   1448 
   1449  JS::Rooted<JS::Value> protoVal(aCx);
   1450  protoVal.setObjectOrNull(aPrototype);
   1451  JS::Rooted<JSObject*> sandbox(
   1452      aCx,
   1453      SimpleGlobalObject::Create(
   1454          SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox, protoVal));
   1455 
   1456  if (!sandbox) {
   1457    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
   1458    return;
   1459  }
   1460 
   1461  if (!JS_WrapObject(aCx, &sandbox)) {
   1462    aRv.NoteJSContextException(aCx);
   1463    return;
   1464  }
   1465 
   1466  aResult.set(sandbox);
   1467 }
   1468 
   1469 void WorkerDebuggerGlobalScope::LoadSubScript(
   1470    JSContext* aCx, const nsAString& aURL,
   1471    const Optional<JS::Handle<JSObject*>>& aSandbox, ErrorResult& aRv) {
   1472  AssertIsOnWorkerThread();
   1473 
   1474  Maybe<JSAutoRealm> ar;
   1475  if (aSandbox.WasPassed()) {
   1476    // We only care about worker debugger sandbox objects here, so
   1477    // CheckedUnwrapStatic is fine.
   1478    JS::Rooted<JSObject*> sandbox(aCx,
   1479                                  js::CheckedUnwrapStatic(aSandbox.Value()));
   1480    if (!sandbox || !IsWorkerDebuggerSandbox(sandbox)) {
   1481      aRv.Throw(NS_ERROR_INVALID_ARG);
   1482      return;
   1483    }
   1484 
   1485    ar.emplace(aCx, sandbox);
   1486  }
   1487 
   1488  nsTArray<nsString> urls;
   1489  urls.AppendElement(aURL);
   1490  workerinternals::Load(mWorkerPrivate, nullptr, urls, DebuggerScript, aRv);
   1491 }
   1492 
   1493 void WorkerDebuggerGlobalScope::EnterEventLoop() {
   1494  // We're on the worker thread here, and WorkerPrivate's refcounting is
   1495  // non-threadsafe: you can only do it on the parent thread.  What that
   1496  // means in practice is that we're relying on it being kept alive while
   1497  // we run.  Hopefully.
   1498  MOZ_KnownLive(mWorkerPrivate)->EnterDebuggerEventLoop();
   1499 }
   1500 
   1501 void WorkerDebuggerGlobalScope::LeaveEventLoop() {
   1502  mWorkerPrivate->LeaveDebuggerEventLoop();
   1503 }
   1504 
   1505 void WorkerDebuggerGlobalScope::PostMessage(const nsAString& aMessage) {
   1506  mWorkerPrivate->PostMessageToDebugger(aMessage);
   1507 }
   1508 
   1509 void WorkerDebuggerGlobalScope::SetImmediate(Function& aHandler,
   1510                                             ErrorResult& aRv) {
   1511  mWorkerPrivate->SetDebuggerImmediate(aHandler, aRv);
   1512 }
   1513 
   1514 void WorkerDebuggerGlobalScope::ReportError(JSContext* aCx,
   1515                                            const nsAString& aMessage) {
   1516  auto caller = JSCallingLocation::Get(aCx);
   1517  mWorkerPrivate->ReportErrorToDebugger(caller.FileName(), caller.mLine,
   1518                                        aMessage);
   1519 }
   1520 
   1521 void WorkerDebuggerGlobalScope::RetrieveConsoleEvents(
   1522    JSContext* aCx, nsTArray<JS::Value>& aEvents, ErrorResult& aRv) {
   1523  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
   1524  if (!scope) {
   1525    aRv.Throw(NS_ERROR_FAILURE);
   1526    return;
   1527  }
   1528 
   1529  RefPtr<Console> console = scope->GetConsole(aRv);
   1530  if (NS_WARN_IF(aRv.Failed())) {
   1531    return;
   1532  }
   1533 
   1534  console->RetrieveConsoleEvents(aCx, aEvents, aRv);
   1535 }
   1536 
   1537 void WorkerDebuggerGlobalScope::ClearConsoleEvents(JSContext* aCx,
   1538                                                   ErrorResult& aRv) {
   1539  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
   1540  if (!scope) {
   1541    aRv.Throw(NS_ERROR_FAILURE);
   1542    return;
   1543  }
   1544 
   1545  RefPtr<Console> console = scope->GetConsoleIfExists();
   1546  if (console) {
   1547    console->ClearStorage();
   1548  }
   1549 }
   1550 
   1551 void WorkerDebuggerGlobalScope::SetConsoleEventHandler(JSContext* aCx,
   1552                                                       AnyCallback* aHandler,
   1553                                                       ErrorResult& aRv) {
   1554  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
   1555  if (!scope) {
   1556    aRv.Throw(NS_ERROR_FAILURE);
   1557    return;
   1558  }
   1559 
   1560  RefPtr<Console> console = scope->GetConsole(aRv);
   1561  if (NS_WARN_IF(aRv.Failed())) {
   1562    return;
   1563  }
   1564 
   1565  console->SetConsoleEventHandler(aHandler);
   1566 }
   1567 
   1568 void WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
   1569                                     const Optional<nsAString>& aString) const {
   1570  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
   1571  if (scope) {
   1572    scope->Dump(aString);
   1573  }
   1574 }
   1575 
   1576 bool IsWorkerGlobal(JSObject* object) {
   1577  return IS_INSTANCE_OF(WorkerGlobalScope, object);
   1578 }
   1579 
   1580 bool IsWorkerDebuggerGlobal(JSObject* object) {
   1581  return IS_INSTANCE_OF(WorkerDebuggerGlobalScope, object);
   1582 }
   1583 
   1584 bool IsWorkerDebuggerSandbox(JSObject* object) {
   1585  return SimpleGlobalObject::SimpleGlobalType(object) ==
   1586         SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox;
   1587 }
   1588 
   1589 }  // namespace mozilla::dom