Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / dom / cache / Context.h
blobd0a2a3a5f35a02f1a65655a80afa763815436ae4
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 #ifndef mozilla_dom_cache_Context_h
8 #define mozilla_dom_cache_Context_h
10 #include "CacheCipherKeyManager.h"
11 #include "mozilla/dom/SafeRefPtr.h"
12 #include "mozilla/dom/cache/Types.h"
13 #include "mozilla/dom/quota/StringifyUtils.h"
14 #include "nsCOMPtr.h"
15 #include "nsISupportsImpl.h"
16 #include "nsProxyRelease.h"
17 #include "nsString.h"
18 #include "nsTArray.h"
19 #include "nsTObserverArray.h"
21 class nsIEventTarget;
22 class nsIThread;
24 namespace mozilla::dom {
26 namespace quota {
28 class DirectoryLock;
30 } // namespace quota
32 namespace cache {
34 class Action;
35 class Manager;
37 // The Context class is RAII-style class for managing IO operations within the
38 // Cache.
40 // When a Context is created it performs the complicated steps necessary to
41 // initialize the QuotaManager. Action objects dispatched on the Context are
42 // delayed until this initialization is complete. They are then allow to
43 // execute on any specified thread. Once all references to the Context are
44 // gone, then the steps necessary to release the QuotaManager are performed.
45 // After initialization the Context holds a self reference, so it will stay
46 // alive until one of three conditions occur:
48 // 1) The Manager will call Context::AllowToClose() when all of the actors
49 // have removed themselves as listener. This means an idle context with
50 // no active DOM objects will close gracefully.
51 // 2) The QuotaManager aborts all operations so it can delete the files.
52 // In this case the QuotaManager calls Client::AbortOperationsForLocks()
53 // which in turn cancels all existing Action objects and then marks the
54 // Manager as invalid.
55 // 3) Browser shutdown occurs and the Manager calls Context::CancelAll().
57 // In either case, though, the Action objects must be destroyed first to
58 // allow the Context to be destroyed.
60 // While the Context performs operations asynchronously on threads, all of
61 // methods in its public interface must be called on the same thread
62 // originally used to create the Context.
64 // As an invariant, all Context objects must be destroyed before permitting
65 // the "profile-before-change" shutdown event to complete. This is ensured
66 // via the code in ShutdownObserver.cpp.
67 class Context final : public SafeRefCounted<Context>, public Stringifyable {
68 using DirectoryLock = mozilla::dom::quota::DirectoryLock;
70 public:
71 // Define a class allowing other threads to hold the Context alive. This also
72 // allows these other threads to safely close or cancel the Context.
73 class ThreadsafeHandle final : public AtomicSafeRefCounted<ThreadsafeHandle> {
74 friend class Context;
76 public:
77 explicit ThreadsafeHandle(SafeRefPtr<Context> aContext);
78 ~ThreadsafeHandle();
80 MOZ_DECLARE_REFCOUNTED_TYPENAME(cache::Context::ThreadsafeHandle)
82 void AllowToClose();
83 void InvalidateAndAllowToClose();
85 private:
86 void AllowToCloseOnOwningThread();
87 void InvalidateAndAllowToCloseOnOwningThread();
89 void ContextDestroyed(Context& aContext);
91 // Cleared to allow the Context to close. Only safe to access on
92 // owning thread.
93 SafeRefPtr<Context> mStrongRef;
95 // Used to support cancelation even while the Context is already allowed
96 // to close. Cleared by ~Context() calling ContextDestroyed(). Only
97 // safe to access on owning thread.
98 Context* mWeakRef;
100 nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
103 // Different objects hold references to the Context while some work is being
104 // performed asynchronously. These objects must implement the Activity
105 // interface and register themselves with the AddActivity(). When they are
106 // destroyed they must call RemoveActivity(). This allows the Context to
107 // cancel any outstanding Activity work when the Context is cancelled.
108 class Activity : public Stringifyable {
109 public:
110 virtual void Cancel() = 0;
111 virtual bool MatchesCacheId(CacheId aCacheId) const = 0;
114 // Create a Context attached to the given Manager. The given Action
115 // will run on the QuotaManager IO thread. Note, this Action must
116 // be execute synchronously.
117 static SafeRefPtr<Context> Create(SafeRefPtr<Manager> aManager,
118 nsISerialEventTarget* aTarget,
119 SafeRefPtr<Action> aInitAction,
120 Maybe<Context&> aOldContext);
122 // Execute given action on the target once the quota manager has been
123 // initialized.
125 // Only callable from the thread that created the Context.
126 void Dispatch(SafeRefPtr<Action> aAction);
128 Maybe<DirectoryLock&> MaybeDirectoryLockRef() const;
130 CipherKeyManager& MutableCipherKeyManagerRef();
132 const Maybe<CacheDirectoryMetadata>& MaybeCacheDirectoryMetadataRef() const;
134 // Cancel any Actions running or waiting to run. This should allow the
135 // Context to be released and Listener::RemoveContext() will be called
136 // when complete.
138 // Only callable from the thread that created the Context.
139 void CancelAll();
141 // True if CancelAll() has been called.
142 bool IsCanceled() const;
144 // Like CancelAll(), but also marks the Manager as "invalid".
145 void Invalidate();
147 // Remove any self references and allow the Context to be released when
148 // there are no more Actions to process.
149 void AllowToClose();
151 // Cancel any Actions running or waiting to run that operate on the given
152 // cache ID.
154 // Only callable from the thread that created the Context.
155 void CancelForCacheId(CacheId aCacheId);
157 void AddActivity(Activity& aActivity);
158 void RemoveActivity(Activity& aActivity);
160 // Tell the Context that some state information has been orphaned in the
161 // data store and won't be cleaned up. The Context will leave the marker
162 // in place to trigger cleanup the next times its opened.
163 void NoteOrphanedData();
165 private:
166 class Data;
167 class QuotaInitRunnable;
168 class ActionRunnable;
170 enum State {
171 STATE_CONTEXT_PREINIT,
172 STATE_CONTEXT_INIT,
173 STATE_CONTEXT_READY,
174 STATE_CONTEXT_CANCELED
177 struct PendingAction {
178 nsCOMPtr<nsIEventTarget> mTarget;
179 SafeRefPtr<Action> mAction;
182 void Init(Maybe<Context&> aOldContext);
183 void Start();
184 void DispatchAction(SafeRefPtr<Action> aAction, bool aDoomData = false);
185 void OnQuotaInit(nsresult aRv,
186 const Maybe<CacheDirectoryMetadata>& aDirectoryMetadata,
187 RefPtr<DirectoryLock> aDirectoryLock,
188 RefPtr<CipherKeyManager> aCipherKeyManager);
190 SafeRefPtr<ThreadsafeHandle> CreateThreadsafeHandle();
192 void SetNextContext(SafeRefPtr<Context> aNextContext);
194 void DoomTargetData();
196 void DoStringify(nsACString& aData) override;
198 SafeRefPtr<Manager> mManager;
199 nsCOMPtr<nsISerialEventTarget> mTarget;
200 RefPtr<Data> mData;
201 State mState;
202 bool mOrphanedData;
203 Maybe<CacheDirectoryMetadata> mDirectoryMetadata;
204 RefPtr<QuotaInitRunnable> mInitRunnable;
205 SafeRefPtr<Action> mInitAction;
206 nsTArray<PendingAction> mPendingActions;
208 // Weak refs since activites must remove themselves from this list before
209 // being destroyed by calling RemoveActivity().
210 nsTObserverArray<NotNull<Activity*>> mActivityList;
212 // The ThreadsafeHandle may have a strong ref back to us. This creates
213 // a ref-cycle that keeps the Context alive. The ref-cycle is broken
214 // when ThreadsafeHandle::AllowToClose() is called.
215 SafeRefPtr<ThreadsafeHandle> mThreadsafeHandle;
217 RefPtr<DirectoryLock> mDirectoryLock;
218 RefPtr<CipherKeyManager> mCipherKeyManager;
219 SafeRefPtr<Context> mNextContext;
221 public:
222 // XXX Consider adding a private guard parameter.
223 Context(SafeRefPtr<Manager> aManager, nsISerialEventTarget* aTarget,
224 SafeRefPtr<Action> aInitAction);
225 ~Context();
227 NS_DECL_OWNINGTHREAD
228 MOZ_DECLARE_REFCOUNTED_TYPENAME(cache::Context)
231 } // namespace cache
232 } // namespace mozilla::dom
234 #endif // mozilla_dom_cache_Context_h