123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef mozilla_dom_cache_Context_h
- #define mozilla_dom_cache_Context_h
- #include "mozilla/dom/cache/Types.h"
- #include "nsCOMPtr.h"
- #include "nsISupportsImpl.h"
- #include "nsProxyRelease.h"
- #include "nsString.h"
- #include "nsTArray.h"
- #include "nsTObserverArray.h"
- class nsIEventTarget;
- class nsIThread;
- namespace mozilla {
- namespace dom {
- namespace quota {
- class DirectoryLock;
- } // namespace quota
- namespace cache {
- class Action;
- class Manager;
- // The Context class is RAII-style class for managing IO operations within the
- // Cache.
- //
- // When a Context is created it performs the complicated steps necessary to
- // initialize the QuotaManager. Action objects dispatched on the Context are
- // delayed until this initialization is complete. They are then allow to
- // execute on any specified thread. Once all references to the Context are
- // gone, then the steps necessary to release the QuotaManager are performed.
- // After initialization the Context holds a self reference, so it will stay
- // alive until one of three conditions occur:
- //
- // 1) The Manager will call Context::AllowToClose() when all of the actors
- // have removed themselves as listener. This means an idle context with
- // no active DOM objects will close gracefully.
- // 2) The QuotaManager aborts all operations so it can delete the files.
- // In this case the QuotaManager calls Client::AbortOperations() which
- // in turn cancels all existing Action objects and then marks the Manager
- // as invalid.
- // 3) Browser shutdown occurs and the Manager calls Context::CancelAll().
- //
- // In either case, though, the Action objects must be destroyed first to
- // allow the Context to be destroyed.
- //
- // While the Context performs operations asynchronously on threads, all of
- // methods in its public interface must be called on the same thread
- // originally used to create the Context.
- //
- // As an invariant, all Context objects must be destroyed before permitting
- // the "profile-before-change" shutdown event to complete. This is ensured
- // via the code in ShutdownObserver.cpp.
- class Context final
- {
- typedef mozilla::dom::quota::DirectoryLock DirectoryLock;
- public:
- // Define a class allowing other threads to hold the Context alive. This also
- // allows these other threads to safely close or cancel the Context.
- class ThreadsafeHandle final
- {
- friend class Context;
- public:
- void AllowToClose();
- void InvalidateAndAllowToClose();
- private:
- explicit ThreadsafeHandle(Context* aContext);
- ~ThreadsafeHandle();
- // disallow copying
- ThreadsafeHandle(const ThreadsafeHandle&) = delete;
- ThreadsafeHandle& operator=(const ThreadsafeHandle&) = delete;
- void AllowToCloseOnOwningThread();
- void InvalidateAndAllowToCloseOnOwningThread();
- void ContextDestroyed(Context* aContext);
- // Cleared to allow the Context to close. Only safe to access on
- // owning thread.
- RefPtr<Context> mStrongRef;
- // Used to support cancelation even while the Context is already allowed
- // to close. Cleared by ~Context() calling ContextDestroyed(). Only
- // safe to access on owning thread.
- Context* mWeakRef;
- nsCOMPtr<nsIThread> mOwningThread;
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(cache::Context::ThreadsafeHandle)
- };
- // Different objects hold references to the Context while some work is being
- // performed asynchronously. These objects must implement the Activity
- // interface and register themselves with the AddActivity(). When they are
- // destroyed they must call RemoveActivity(). This allows the Context to
- // cancel any outstanding Activity work when the Context is cancelled.
- class Activity
- {
- public:
- virtual void Cancel() = 0;
- virtual bool MatchesCacheId(CacheId aCacheId) const = 0;
- };
- // Create a Context attached to the given Manager. The given Action
- // will run on the QuotaManager IO thread. Note, this Action must
- // be execute synchronously.
- static already_AddRefed<Context>
- Create(Manager* aManager, nsIThread* aTarget,
- Action* aInitAction, Context* aOldContext);
- // Execute given action on the target once the quota manager has been
- // initialized.
- //
- // Only callable from the thread that created the Context.
- void Dispatch(Action* aAction);
- // Cancel any Actions running or waiting to run. This should allow the
- // Context to be released and Listener::RemoveContext() will be called
- // when complete.
- //
- // Only callable from the thread that created the Context.
- void CancelAll();
- // True if CancelAll() has been called.
- bool IsCanceled() const;
- // Like CancelAll(), but also marks the Manager as "invalid".
- void Invalidate();
- // Remove any self references and allow the Context to be released when
- // there are no more Actions to process.
- void AllowToClose();
- // Cancel any Actions running or waiting to run that operate on the given
- // cache ID.
- //
- // Only callable from the thread that created the Context.
- void CancelForCacheId(CacheId aCacheId);
- void AddActivity(Activity* aActivity);
- void RemoveActivity(Activity* aActivity);
- const QuotaInfo&
- GetQuotaInfo() const
- {
- return mQuotaInfo;
- }
- // Tell the Context that some state information has been orphaned in the
- // data store and won't be cleaned up. The Context will leave the marker
- // in place to trigger cleanup the next times its opened.
- void NoteOrphanedData();
- private:
- class Data;
- class QuotaInitRunnable;
- class ActionRunnable;
- enum State
- {
- STATE_CONTEXT_PREINIT,
- STATE_CONTEXT_INIT,
- STATE_CONTEXT_READY,
- STATE_CONTEXT_CANCELED
- };
- struct PendingAction
- {
- nsCOMPtr<nsIEventTarget> mTarget;
- RefPtr<Action> mAction;
- };
- Context(Manager* aManager, nsIThread* aTarget, Action* aInitAction);
- ~Context();
- void Init(Context* aOldContext);
- void Start();
- void DispatchAction(Action* aAction, bool aDoomData = false);
- void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
- already_AddRefed<DirectoryLock> aDirectoryLock);
- already_AddRefed<ThreadsafeHandle>
- CreateThreadsafeHandle();
- void
- SetNextContext(Context* aNextContext);
- void
- DoomTargetData();
- RefPtr<Manager> mManager;
- nsCOMPtr<nsIThread> mTarget;
- RefPtr<Data> mData;
- State mState;
- bool mOrphanedData;
- QuotaInfo mQuotaInfo;
- RefPtr<QuotaInitRunnable> mInitRunnable;
- RefPtr<Action> mInitAction;
- nsTArray<PendingAction> mPendingActions;
- // Weak refs since activites must remove themselves from this list before
- // being destroyed by calling RemoveActivity().
- typedef nsTObserverArray<Activity*> ActivityList;
- ActivityList mActivityList;
- // The ThreadsafeHandle may have a strong ref back to us. This creates
- // a ref-cycle that keeps the Context alive. The ref-cycle is broken
- // when ThreadsafeHandle::AllowToClose() is called.
- RefPtr<ThreadsafeHandle> mThreadsafeHandle;
- RefPtr<DirectoryLock> mDirectoryLock;
- RefPtr<Context> mNextContext;
- public:
- NS_INLINE_DECL_REFCOUNTING(cache::Context)
- };
- } // namespace cache
- } // namespace dom
- } // namespace mozilla
- #endif // mozilla_dom_cache_Context_h
|