forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			227 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* 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/SafeRefPtr.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::AbortOperationsForLocks()
 | |
| //     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 : public SafeRefCounted<Context> {
 | |
|   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 : public AtomicSafeRefCounted<ThreadsafeHandle> {
 | |
|     friend class Context;
 | |
| 
 | |
|    public:
 | |
|     explicit ThreadsafeHandle(SafeRefPtr<Context> aContext);
 | |
|     ~ThreadsafeHandle();
 | |
| 
 | |
|     MOZ_DECLARE_REFCOUNTED_TYPENAME(cache::Context::ThreadsafeHandle)
 | |
| 
 | |
|     void AllowToClose();
 | |
|     void InvalidateAndAllowToClose();
 | |
| 
 | |
|    private:
 | |
|     void AllowToCloseOnOwningThread();
 | |
|     void InvalidateAndAllowToCloseOnOwningThread();
 | |
| 
 | |
|     void ContextDestroyed(Context& aContext);
 | |
| 
 | |
|     // Cleared to allow the Context to close.  Only safe to access on
 | |
|     // owning thread.
 | |
|     SafeRefPtr<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<nsISerialEventTarget> mOwningEventTarget;
 | |
|   };
 | |
| 
 | |
|   // 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 SafeRefPtr<Context> Create(SafeRefPtr<Manager> aManager,
 | |
|                                     nsISerialEventTarget* aTarget,
 | |
|                                     SafeRefPtr<Action> aInitAction,
 | |
|                                     Maybe<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(SafeRefPtr<Action> aAction);
 | |
| 
 | |
|   Maybe<DirectoryLock&> MaybeDirectoryLockRef() const;
 | |
| 
 | |
|   // 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;
 | |
|     SafeRefPtr<Action> mAction;
 | |
|   };
 | |
| 
 | |
|   void Init(Maybe<Context&> aOldContext);
 | |
|   void Start();
 | |
|   void DispatchAction(SafeRefPtr<Action> aAction, bool aDoomData = false);
 | |
|   void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
 | |
|                    already_AddRefed<DirectoryLock> aDirectoryLock);
 | |
| 
 | |
|   SafeRefPtr<ThreadsafeHandle> CreateThreadsafeHandle();
 | |
| 
 | |
|   void SetNextContext(SafeRefPtr<Context> aNextContext);
 | |
| 
 | |
|   void DoomTargetData();
 | |
| 
 | |
|   SafeRefPtr<Manager> mManager;
 | |
|   nsCOMPtr<nsISerialEventTarget> mTarget;
 | |
|   RefPtr<Data> mData;
 | |
|   State mState;
 | |
|   bool mOrphanedData;
 | |
|   QuotaInfo mQuotaInfo;
 | |
|   RefPtr<QuotaInitRunnable> mInitRunnable;
 | |
|   SafeRefPtr<Action> mInitAction;
 | |
|   nsTArray<PendingAction> mPendingActions;
 | |
| 
 | |
|   // Weak refs since activites must remove themselves from this list before
 | |
|   // being destroyed by calling RemoveActivity().
 | |
|   nsTObserverArray<NotNull<Activity*>> 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.
 | |
|   SafeRefPtr<ThreadsafeHandle> mThreadsafeHandle;
 | |
| 
 | |
|   RefPtr<DirectoryLock> mDirectoryLock;
 | |
|   SafeRefPtr<Context> mNextContext;
 | |
| 
 | |
|  public:
 | |
|   // XXX Consider adding a private guard parameter.
 | |
|   Context(SafeRefPtr<Manager> aManager, nsISerialEventTarget* aTarget,
 | |
|           SafeRefPtr<Action> aInitAction);
 | |
|   ~Context();
 | |
| 
 | |
|   NS_DECL_OWNINGTHREAD
 | |
|   MOZ_DECLARE_REFCOUNTED_TYPENAME(cache::Context)
 | |
| };
 | |
| 
 | |
| }  // namespace cache
 | |
| }  // namespace dom
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif  // mozilla_dom_cache_Context_h
 | 
