tor-browser

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

Context.h (8417B)


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