123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- /* -*- 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_Manager_h
- #define mozilla_dom_cache_Manager_h
- #include "mozilla/dom/cache/Types.h"
- #include "nsCOMPtr.h"
- #include "nsISupportsImpl.h"
- #include "mozilla/RefPtr.h"
- #include "nsString.h"
- #include "nsTArray.h"
- class nsIInputStream;
- class nsIThread;
- namespace mozilla {
- class ErrorResult;
- namespace dom {
- namespace cache {
- class CacheOpArgs;
- class CacheOpResult;
- class CacheRequestResponse;
- class Context;
- class ManagerId;
- struct SavedRequest;
- struct SavedResponse;
- class StreamList;
- // The Manager is class is responsible for performing all of the underlying
- // work for a Cache or CacheStorage operation. The DOM objects and IPC actors
- // are basically just plumbing to get the request to the right Manager object
- // running in the parent process.
- //
- // There should be exactly one Manager object for each origin or app using the
- // Cache API. This uniqueness is defined by the ManagerId equality operator.
- // The uniqueness is enforced by the Manager GetOrCreate() factory method.
- //
- // The life cycle of Manager objects is somewhat complex. While code may
- // hold a strong reference to the Manager, it will invalidate itself once it
- // believes it has become completely idle. This is currently determined when
- // all of the following conditions occur:
- //
- // 1) There are no more Manager::Listener objects registered with the Manager
- // by performing a Cache or Storage operation.
- // 2) There are no more CacheId references noted via Manager::AddRefCacheId().
- // 3) There are no more BodyId references noted via Manager::AddRefBodyId().
- //
- // In order to keep your Manager alive you should perform an operation to set
- // a Listener, call AddRefCacheId(), or call AddRefBodyId().
- //
- // Even once a Manager becomes invalid, however, it may still continue to
- // exist. This is allowed so that any in-progress Actions can gracefully
- // complete.
- //
- // As an invariant, all Manager objects must cease all IO before shutdown. This
- // is enforced by the Manager::Factory. If content still holds references to
- // Cache DOM objects during shutdown, then all operations will begin rejecting.
- class Manager final
- {
- public:
- // Callback interface implemented by clients of Manager, such as CacheParent
- // and CacheStorageParent. In general, if you call a Manager method you
- // should expect to receive exactly one On*() callback. For example, if
- // you call Manager::CacheMatch(), then you should expect to receive
- // OnCacheMatch() back in response.
- //
- // Listener objects are set on a per-operation basis. So you pass the
- // Listener to a call like Manager::CacheMatch(). Once set in this way,
- // the Manager will continue to reference the Listener until RemoveListener()
- // is called. This is done to allow the same listener to be used for
- // multiple operations simultaneously without having to maintain an exact
- // count of operations-in-flight.
- //
- // Note, the Manager only holds weak references to Listener objects.
- // Listeners must call Manager::RemoveListener() before they are destroyed
- // to clear these weak references.
- //
- // All public methods should be invoked on the same thread used to create
- // the Manager.
- class Listener
- {
- public:
- // convenience routines
- void
- OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult);
- void
- OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
- CacheId aOpenedCacheId);
- void
- OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
- const SavedResponse& aSavedResponse,
- StreamList* aStreamList);
- void
- OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
- const nsTArray<SavedResponse>& aSavedResponseList,
- StreamList* aStreamList);
- void
- OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
- const nsTArray<SavedRequest>& aSavedRequestList,
- StreamList* aStreamList);
- // interface to be implemented
- virtual void
- OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
- CacheId aOpenedCacheId,
- const nsTArray<SavedResponse>& aSavedResponseList,
- const nsTArray<SavedRequest>& aSavedRequestList,
- StreamList* aStreamList) { }
- protected:
- ~Listener() { }
- };
- enum State
- {
- Open,
- Closing
- };
- static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut);
- static already_AddRefed<Manager> Get(ManagerId* aManagerId);
- // Synchronously shutdown. This spins the event loop.
- static void ShutdownAll();
- // Cancel actions for given origin or all actions if passed string is null.
- static void Abort(const nsACString& aOrigin);
- // Must be called by Listener objects before they are destroyed.
- void RemoveListener(Listener* aListener);
- // Must be called by Context objects before they are destroyed.
- void RemoveContext(Context* aContext);
- // Marks the Manager "invalid". Once the Context completes no new operations
- // will be permitted with this Manager. New actors will get a new Manager.
- void NoteClosing();
- State GetState() const;
- // If an actor represents a long term reference to a cache or body stream,
- // then they must call AddRefCacheId() or AddRefBodyId(). This will
- // cause the Manager to keep the backing data store alive for the given
- // object. The actor must then call ReleaseCacheId() or ReleaseBodyId()
- // exactly once for every AddRef*() call it made. Any delayed deletion
- // will then be performed.
- void AddRefCacheId(CacheId aCacheId);
- void ReleaseCacheId(CacheId aCacheId);
- void AddRefBodyId(const nsID& aBodyId);
- void ReleaseBodyId(const nsID& aBodyId);
- already_AddRefed<ManagerId> GetManagerId() const;
- // Methods to allow a StreamList to register themselves with the Manager.
- // StreamList objects must call RemoveStreamList() before they are destroyed.
- void AddStreamList(StreamList* aStreamList);
- void RemoveStreamList(StreamList* aStreamList);
- void ExecuteCacheOp(Listener* aListener, CacheId aCacheId,
- const CacheOpArgs& aOpArgs);
- void ExecutePutAll(Listener* aListener, CacheId aCacheId,
- const nsTArray<CacheRequestResponse>& aPutList,
- const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
- const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList);
- void ExecuteStorageOp(Listener* aListener, Namespace aNamespace,
- const CacheOpArgs& aOpArgs);
- private:
- class Factory;
- class BaseAction;
- class DeleteOrphanedCacheAction;
- class CacheMatchAction;
- class CacheMatchAllAction;
- class CachePutAllAction;
- class CacheDeleteAction;
- class CacheKeysAction;
- class StorageMatchAction;
- class StorageHasAction;
- class StorageOpenAction;
- class StorageDeleteAction;
- class StorageKeysAction;
- typedef uint64_t ListenerId;
- Manager(ManagerId* aManagerId, nsIThread* aIOThread);
- ~Manager();
- void Init(Manager* aOldManager);
- void Shutdown();
- void Abort();
- ListenerId SaveListener(Listener* aListener);
- Listener* GetListener(ListenerId aListenerId) const;
- bool SetCacheIdOrphanedIfRefed(CacheId aCacheId);
- bool SetBodyIdOrphanedIfRefed(const nsID& aBodyId);
- void NoteOrphanedBodyIdList(const nsTArray<nsID>& aDeletedBodyIdList);
- void MaybeAllowContextToClose();
- RefPtr<ManagerId> mManagerId;
- nsCOMPtr<nsIThread> mIOThread;
- // Weak reference cleared by RemoveContext() in Context destructor.
- Context* MOZ_NON_OWNING_REF mContext;
- // Weak references cleared by RemoveListener() in Listener destructors.
- struct ListenerEntry
- {
- ListenerEntry()
- : mId(UINT64_MAX)
- , mListener(nullptr)
- {
- }
- ListenerEntry(ListenerId aId, Listener* aListener)
- : mId(aId)
- , mListener(aListener)
- {
- }
- ListenerId mId;
- Listener* mListener;
- };
- class ListenerEntryIdComparator
- {
- public:
- bool Equals(const ListenerEntry& aA, const ListenerId& aB) const
- {
- return aA.mId == aB;
- }
- };
- class ListenerEntryListenerComparator
- {
- public:
- bool Equals(const ListenerEntry& aA, const Listener* aB) const
- {
- return aA.mListener == aB;
- }
- };
- typedef nsTArray<ListenerEntry> ListenerList;
- ListenerList mListeners;
- static ListenerId sNextListenerId;
- // Weak references cleared by RemoveStreamList() in StreamList destructors.
- nsTArray<StreamList*> mStreamLists;
- bool mShuttingDown;
- State mState;
- struct CacheIdRefCounter
- {
- CacheId mCacheId;
- MozRefCountType mCount;
- bool mOrphaned;
- };
- nsTArray<CacheIdRefCounter> mCacheIdRefs;
- struct BodyIdRefCounter
- {
- nsID mBodyId;
- MozRefCountType mCount;
- bool mOrphaned;
- };
- nsTArray<BodyIdRefCounter> mBodyIdRefs;
- public:
- NS_INLINE_DECL_REFCOUNTING(cache::Manager)
- };
- } // namespace cache
- } // namespace dom
- } // namespace mozilla
- #endif // mozilla_dom_cache_Manager_h
|