Backed out changeset b462e7b742d8 (bug 1908261) for causing multiple reftest failures...
[gecko.git] / dom / workers / WorkerDocumentListener.cpp
bloba5285f7ad933347a1c1ee117807f2e248f781ea5
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/. */
7 #include "WorkerDocumentListener.h"
8 #include "mozilla/dom/Document.h"
9 #include "mozilla/dom/WorkerPrivate.h"
10 #include "mozilla/dom/WorkerRef.h"
11 #include "mozilla/dom/WorkerRunnable.h"
12 #include "mozilla/dom/WorkerScope.h"
13 #include "nsGlobalWindowInner.h"
15 namespace mozilla::dom {
17 WorkerDocumentListener::WorkerDocumentListener()
18 : mMutex("mozilla::dom::WorkerDocumentListener::mMutex") {}
20 WorkerDocumentListener::~WorkerDocumentListener() = default;
22 RefPtr<WorkerDocumentListener> WorkerDocumentListener::Create(
23 WorkerPrivate* aWorkerPrivate) {
24 MOZ_ASSERT(aWorkerPrivate);
25 aWorkerPrivate->AssertIsOnWorkerThread();
27 auto listener = MakeRefPtr<WorkerDocumentListener>();
29 RefPtr<StrongWorkerRef> strongWorkerRef =
30 StrongWorkerRef::Create(aWorkerPrivate, "WorkerDocumentListener",
31 [listener]() { listener->Destroy(); });
32 if (NS_WARN_IF(!strongWorkerRef)) {
33 return nullptr;
36 listener->mWorkerRef = new ThreadSafeWorkerRef(strongWorkerRef);
37 uint64_t windowID = aWorkerPrivate->WindowID();
39 aWorkerPrivate->DispatchToMainThread(NS_NewRunnableFunction(
40 "WorkerDocumentListener::Create",
41 [listener, windowID] { listener->SetListening(windowID, true); }));
43 return listener;
46 void WorkerDocumentListener::OnVisible(bool aVisible) {
47 MOZ_ASSERT(NS_IsMainThread());
49 MutexAutoLock lock(mMutex);
50 if (!mWorkerRef) {
51 // We haven't handled the runnable to release this yet.
52 return;
55 class VisibleRunnable final : public WorkerThreadRunnable {
56 public:
57 VisibleRunnable(WorkerPrivate* aWorkerPrivate, bool aVisible)
58 : WorkerThreadRunnable("VisibleRunnable"), mVisible(aVisible) {}
60 bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) {
61 WorkerGlobalScope* scope = aWorkerPrivate->GlobalScope();
62 MOZ_ASSERT(scope);
63 scope->OnDocumentVisible(mVisible);
64 return true;
67 private:
68 const bool mVisible;
71 auto runnable = MakeRefPtr<VisibleRunnable>(mWorkerRef->Private(), aVisible);
72 runnable->Dispatch(mWorkerRef->Private());
75 void WorkerDocumentListener::SetListening(uint64_t aWindowID, bool aListen) {
76 MOZ_ASSERT(NS_IsMainThread());
78 auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowID);
79 Document* doc = window->GetExtantDoc();
80 if (NS_WARN_IF(!doc)) {
81 // This would typically happen during shutdown if there is an active worker
82 // listening for document events. The Document may already be freed when we
83 // try to deregister for notifications.
84 return;
87 if (aListen) {
88 doc->AddWorkerDocumentListener(this);
89 } else {
90 doc->RemoveWorkerDocumentListener(this);
94 void WorkerDocumentListener::Destroy() {
95 MutexAutoLock lock(mMutex);
97 MOZ_ASSERT(mWorkerRef);
98 WorkerPrivate* workerPrivate = mWorkerRef->Private();
99 MOZ_ASSERT(workerPrivate);
100 workerPrivate->AssertIsOnWorkerThread();
102 uint64_t windowID = workerPrivate->WindowID();
103 workerPrivate->DispatchToMainThread(NS_NewRunnableFunction(
104 "WorkerDocumentListener::Destroy", [self = RefPtr{this}, windowID] {
105 self->SetListening(windowID, false);
106 }));
107 mWorkerRef = nullptr;
110 } // namespace mozilla::dom