ServiceWorkerProxy.cpp (3755B)
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 "ServiceWorkerProxy.h" 8 9 #include "ServiceWorkerCloneData.h" 10 #include "ServiceWorkerInfo.h" 11 #include "ServiceWorkerManager.h" 12 #include "ServiceWorkerParent.h" 13 #include "mozilla/SchedulerGroup.h" 14 #include "mozilla/ScopeExit.h" 15 #include "mozilla/dom/ClientState.h" 16 #include "mozilla/ipc/BackgroundParent.h" 17 18 namespace mozilla::dom { 19 20 using mozilla::ipc::AssertIsOnBackgroundThread; 21 22 ServiceWorkerProxy::~ServiceWorkerProxy() { 23 // Any thread 24 MOZ_DIAGNOSTIC_ASSERT(!mActor); 25 MOZ_DIAGNOSTIC_ASSERT(!mInfo); 26 } 27 28 void ServiceWorkerProxy::MaybeShutdownOnBGThread() { 29 AssertIsOnBackgroundThread(); 30 if (!mActor) { 31 return; 32 } 33 mActor->MaybeSendDelete(); 34 } 35 36 void ServiceWorkerProxy::InitOnMainThread() { 37 AssertIsOnMainThread(); 38 39 auto scopeExit = MakeScopeExit([&] { MaybeShutdownOnMainThread(); }); 40 41 RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); 42 NS_ENSURE_TRUE_VOID(swm); 43 44 RefPtr<ServiceWorkerRegistrationInfo> reg = 45 swm->GetRegistration(mDescriptor.PrincipalInfo(), mDescriptor.Scope()); 46 NS_ENSURE_TRUE_VOID(reg); 47 48 RefPtr<ServiceWorkerInfo> info = reg->GetByDescriptor(mDescriptor); 49 NS_ENSURE_TRUE_VOID(info); 50 51 scopeExit.release(); 52 53 mInfo = new nsMainThreadPtrHolder<ServiceWorkerInfo>( 54 "ServiceWorkerProxy::mInfo", info); 55 } 56 57 void ServiceWorkerProxy::MaybeShutdownOnMainThread() { 58 AssertIsOnMainThread(); 59 60 nsCOMPtr<nsIRunnable> r = NewRunnableMethod( 61 __func__, this, &ServiceWorkerProxy::MaybeShutdownOnBGThread); 62 63 MOZ_ALWAYS_SUCCEEDS(mEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL)); 64 } 65 66 void ServiceWorkerProxy::StopListeningOnMainThread() { 67 AssertIsOnMainThread(); 68 mInfo = nullptr; 69 } 70 71 ServiceWorkerProxy::ServiceWorkerProxy( 72 const ServiceWorkerDescriptor& aDescriptor) 73 : mEventTarget(GetCurrentSerialEventTarget()), mDescriptor(aDescriptor) {} 74 75 void ServiceWorkerProxy::Init(ServiceWorkerParent* aActor) { 76 AssertIsOnBackgroundThread(); 77 MOZ_DIAGNOSTIC_ASSERT(aActor); 78 MOZ_DIAGNOSTIC_ASSERT(!mActor); 79 MOZ_DIAGNOSTIC_ASSERT(mEventTarget); 80 81 mActor = aActor; 82 83 // Note, this must be done from a separate Init() method and not in 84 // the constructor. If done from the constructor the runnable can 85 // execute, complete, and release its reference before the constructor 86 // returns. 87 nsCOMPtr<nsIRunnable> r = NewRunnableMethod( 88 "ServiceWorkerProxy::Init", this, &ServiceWorkerProxy::InitOnMainThread); 89 MOZ_ALWAYS_SUCCEEDS(SchedulerGroup::Dispatch(r.forget())); 90 } 91 92 void ServiceWorkerProxy::RevokeActor(ServiceWorkerParent* aActor) { 93 AssertIsOnBackgroundThread(); 94 MOZ_DIAGNOSTIC_ASSERT(mActor); 95 MOZ_DIAGNOSTIC_ASSERT(mActor == aActor); 96 mActor = nullptr; 97 98 nsCOMPtr<nsIRunnable> r = NewRunnableMethod( 99 __func__, this, &ServiceWorkerProxy::StopListeningOnMainThread); 100 MOZ_ALWAYS_SUCCEEDS(SchedulerGroup::Dispatch(r.forget())); 101 } 102 103 void ServiceWorkerProxy::PostMessage(RefPtr<ServiceWorkerCloneData>&& aData, 104 const PostMessageSource& aSource) { 105 AssertIsOnBackgroundThread(); 106 RefPtr<ServiceWorkerProxy> self = this; 107 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 108 __func__, [self, data = std::move(aData), aSource]() mutable { 109 if (!self->mInfo) { 110 return; 111 } 112 self->mInfo->PostMessage(std::move(data), aSource); 113 }); 114 MOZ_ALWAYS_SUCCEEDS(SchedulerGroup::Dispatch(r.forget())); 115 } 116 117 } // namespace mozilla::dom