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/cache/CacheWorkerHolder.h"
8 
9 #include "mozilla/dom/cache/ActorChild.h"
10 #include "mozilla/dom/WorkerPrivate.h"
11 
12 namespace mozilla {
13 namespace dom {
14 namespace cache {
15 
16 // static
Create(WorkerPrivate * aWorkerPrivate,Behavior aBehavior)17 already_AddRefed<CacheWorkerHolder> CacheWorkerHolder::Create(
18     WorkerPrivate* aWorkerPrivate, Behavior aBehavior) {
19   MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
20 
21   RefPtr<CacheWorkerHolder> workerHolder = new CacheWorkerHolder(aBehavior);
22   if (NS_WARN_IF(!workerHolder->HoldWorker(aWorkerPrivate, Terminating))) {
23     return nullptr;
24   }
25 
26   return workerHolder.forget();
27 }
28 
29 // static
PreferBehavior(CacheWorkerHolder * aCurrentHolder,Behavior aBehavior)30 already_AddRefed<CacheWorkerHolder> CacheWorkerHolder::PreferBehavior(
31     CacheWorkerHolder* aCurrentHolder, Behavior aBehavior) {
32   if (!aCurrentHolder) {
33     return nullptr;
34   }
35 
36   RefPtr<CacheWorkerHolder> orig = aCurrentHolder;
37   if (orig->GetBehavior() == aBehavior) {
38     return orig.forget();
39   }
40 
41   RefPtr<CacheWorkerHolder> replace = Create(orig->mWorkerPrivate, aBehavior);
42   if (!replace) {
43     return orig.forget();
44   }
45 
46   return replace.forget();
47 }
48 
AddActor(ActorChild * aActor)49 void CacheWorkerHolder::AddActor(ActorChild* aActor) {
50   NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
51   MOZ_DIAGNOSTIC_ASSERT(aActor);
52   MOZ_ASSERT(!mActorList.Contains(aActor));
53 
54   mActorList.AppendElement(aActor);
55 
56   // Allow an actor to be added after we've entered the Notifying case.  We
57   // can't stop the actor creation from racing with out destruction of the
58   // other actors and we need to wait for this extra one to close as well.
59   // Signal it should destroy itself right away.
60   if (mNotified) {
61     aActor->StartDestroy();
62   }
63 }
64 
RemoveActor(ActorChild * aActor)65 void CacheWorkerHolder::RemoveActor(ActorChild* aActor) {
66   NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
67   MOZ_DIAGNOSTIC_ASSERT(aActor);
68 
69 #if defined(RELEASE_OR_BETA)
70   mActorList.RemoveElement(aActor);
71 #else
72   MOZ_DIAGNOSTIC_ASSERT(mActorList.RemoveElement(aActor));
73 #endif
74 
75   MOZ_ASSERT(!mActorList.Contains(aActor));
76 }
77 
Notified() const78 bool CacheWorkerHolder::Notified() const { return mNotified; }
79 
Notify(WorkerStatus aStatus)80 bool CacheWorkerHolder::Notify(WorkerStatus aStatus) {
81   NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
82 
83   // When the service worker thread is stopped we will get Terminating,
84   // but nothing higher than that.  We must shut things down at Terminating.
85   if (aStatus < Terminating || mNotified) {
86     return true;
87   }
88 
89   mNotified = true;
90 
91   // Start the asynchronous destruction of our actors.  These will call back
92   // into RemoveActor() once the actor is destroyed.
93   for (uint32_t i = 0; i < mActorList.Length(); ++i) {
94     MOZ_DIAGNOSTIC_ASSERT(mActorList[i]);
95     mActorList[i]->StartDestroy();
96   }
97 
98   return true;
99 }
100 
CacheWorkerHolder(Behavior aBehavior)101 CacheWorkerHolder::CacheWorkerHolder(Behavior aBehavior)
102     : WorkerHolder("CacheWorkerHolder", aBehavior), mNotified(false) {}
103 
~CacheWorkerHolder()104 CacheWorkerHolder::~CacheWorkerHolder() {
105   NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
106   MOZ_DIAGNOSTIC_ASSERT(mActorList.IsEmpty());
107 }
108 
109 }  // namespace cache
110 }  // namespace dom
111 }  // namespace mozilla
112