michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsDOMStorageIPC_h___ michael@0: #define nsDOMStorageIPC_h___ michael@0: michael@0: #include "mozilla/dom/PStorageChild.h" michael@0: #include "mozilla/dom/PStorageParent.h" michael@0: #include "DOMStorageDBThread.h" michael@0: #include "DOMStorageCache.h" michael@0: #include "DOMStorageObserver.h" michael@0: #include "mozilla/Mutex.h" michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: class DOMLocalStorageManager; michael@0: michael@0: // Child side of the IPC protocol, exposes as DB interface but michael@0: // is responsible to send all requests to the parent process michael@0: // and expects asynchronous answers. Those are then transparently michael@0: // forwarded back to consumers on the child process. michael@0: class DOMStorageDBChild MOZ_FINAL : public DOMStorageDBBridge michael@0: , public PStorageChild michael@0: { michael@0: public: michael@0: DOMStorageDBChild(DOMLocalStorageManager* aManager); michael@0: virtual ~DOMStorageDBChild(); michael@0: michael@0: NS_IMETHOD_(MozExternalRefCountType) AddRef(void); michael@0: NS_IMETHOD_(MozExternalRefCountType) Release(void); michael@0: michael@0: void AddIPDLReference(); michael@0: void ReleaseIPDLReference(); michael@0: michael@0: virtual nsresult Init(); michael@0: virtual nsresult Shutdown(); michael@0: michael@0: virtual void AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority = false); michael@0: virtual void AsyncGetUsage(DOMStorageUsageBridge* aUsage); michael@0: michael@0: virtual void SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync = false); michael@0: michael@0: virtual nsresult AsyncAddItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue); michael@0: virtual nsresult AsyncUpdateItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue); michael@0: virtual nsresult AsyncRemoveItem(DOMStorageCacheBridge* aCache, const nsAString& aKey); michael@0: virtual nsresult AsyncClear(DOMStorageCacheBridge* aCache); michael@0: michael@0: virtual void AsyncClearAll() michael@0: { michael@0: if (mScopesHavingData) { michael@0: mScopesHavingData->Clear(); /* NO-OP on the child process otherwise */ michael@0: } michael@0: } michael@0: michael@0: virtual void AsyncClearMatchingScope(const nsACString& aScope) michael@0: { /* NO-OP on the child process */ } michael@0: michael@0: virtual void AsyncFlush() michael@0: { SendAsyncFlush(); } michael@0: michael@0: virtual bool ShouldPreloadScope(const nsACString& aScope); michael@0: virtual void GetScopesHavingData(InfallibleTArray* aScopes) michael@0: { NS_NOTREACHED("Not implemented for child process"); } michael@0: michael@0: private: michael@0: bool RecvObserve(const nsCString& aTopic, michael@0: const nsCString& aScopePrefix); michael@0: bool RecvLoadItem(const nsCString& aScope, michael@0: const nsString& aKey, michael@0: const nsString& aValue); michael@0: bool RecvLoadDone(const nsCString& aScope, michael@0: const nsresult& aRv); michael@0: bool RecvScopesHavingData(const InfallibleTArray& aScopes); michael@0: bool RecvLoadUsage(const nsCString& aScope, michael@0: const int64_t& aUsage); michael@0: bool RecvError(const nsresult& aRv); michael@0: michael@0: nsTHashtable& ScopesHavingData(); michael@0: michael@0: ThreadSafeAutoRefCnt mRefCnt; michael@0: NS_DECL_OWNINGTHREAD michael@0: michael@0: // Held to get caches to forward answers to. michael@0: nsRefPtr mManager; michael@0: michael@0: // Scopes having data hash, for optimization purposes only michael@0: nsAutoPtr > mScopesHavingData; michael@0: michael@0: // List of caches waiting for preload. This ensures the contract that michael@0: // AsyncPreload call references the cache for time of the preload. michael@0: nsTHashtable > mLoadingCaches; michael@0: michael@0: // Status of the remote database michael@0: nsresult mStatus; michael@0: michael@0: bool mIPCOpen; michael@0: }; michael@0: michael@0: michael@0: // Receives async requests from child processes and is responsible michael@0: // to send back responses from the DB thread. Exposes as a fake michael@0: // DOMStorageCache consumer. michael@0: // Also responsible for forwardning all chrome operation notifications michael@0: // such as cookie cleaning etc to the child process. michael@0: class DOMStorageDBParent MOZ_FINAL : public PStorageParent michael@0: , public DOMStorageObserverSink michael@0: { michael@0: public: michael@0: DOMStorageDBParent(); michael@0: virtual ~DOMStorageDBParent(); michael@0: michael@0: virtual mozilla::ipc::IProtocol* michael@0: CloneProtocol(Channel* aChannel, michael@0: mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD_(MozExternalRefCountType) AddRef(void); michael@0: NS_IMETHOD_(MozExternalRefCountType) Release(void); michael@0: michael@0: void AddIPDLReference(); michael@0: void ReleaseIPDLReference(); michael@0: michael@0: bool IPCOpen() { return mIPCOpen; } michael@0: michael@0: public: michael@0: // Fake cache class receiving async callbacks from DB thread, sending michael@0: // them back to appropriate cache object on the child process. michael@0: class CacheParentBridge : public DOMStorageCacheBridge { michael@0: public: michael@0: CacheParentBridge(DOMStorageDBParent* aParentDB, const nsACString& aScope) michael@0: : mParent(aParentDB), mScope(aScope), mLoaded(false), mLoadedCount(0) {} michael@0: virtual ~CacheParentBridge() {} michael@0: michael@0: // DOMStorageCacheBridge michael@0: virtual const nsCString& Scope() const michael@0: { return mScope; } michael@0: virtual bool Loaded() michael@0: { return mLoaded; } michael@0: virtual uint32_t LoadedCount() michael@0: { return mLoadedCount; } michael@0: michael@0: virtual bool LoadItem(const nsAString& aKey, const nsString& aValue); michael@0: virtual void LoadDone(nsresult aRv); michael@0: virtual void LoadWait(); michael@0: michael@0: private: michael@0: nsRefPtr mParent; michael@0: nsCString mScope; michael@0: bool mLoaded; michael@0: uint32_t mLoadedCount; michael@0: }; michael@0: michael@0: // Fake usage class receiving async callbacks from DB thread michael@0: class UsageParentBridge : public DOMStorageUsageBridge michael@0: { michael@0: public: michael@0: UsageParentBridge(DOMStorageDBParent* aParentDB, const nsACString& aScope) michael@0: : mParent(aParentDB), mScope(aScope) {} michael@0: virtual ~UsageParentBridge() {} michael@0: michael@0: // DOMStorageUsageBridge michael@0: virtual const nsCString& Scope() { return mScope; } michael@0: virtual void LoadUsage(const int64_t usage); michael@0: michael@0: private: michael@0: nsRefPtr mParent; michael@0: nsCString mScope; michael@0: }; michael@0: michael@0: private: michael@0: // IPC michael@0: bool RecvAsyncPreload(const nsCString& aScope, const bool& aPriority); michael@0: bool RecvPreload(const nsCString& aScope, const uint32_t& aAlreadyLoadedCount, michael@0: InfallibleTArray* aKeys, InfallibleTArray* aValues, michael@0: nsresult* aRv); michael@0: bool RecvAsyncGetUsage(const nsCString& aScope); michael@0: bool RecvAsyncAddItem(const nsCString& aScope, const nsString& aKey, const nsString& aValue); michael@0: bool RecvAsyncUpdateItem(const nsCString& aScope, const nsString& aKey, const nsString& aValue); michael@0: bool RecvAsyncRemoveItem(const nsCString& aScope, const nsString& aKey); michael@0: bool RecvAsyncClear(const nsCString& aScope); michael@0: bool RecvAsyncFlush(); michael@0: michael@0: // DOMStorageObserverSink michael@0: virtual nsresult Observe(const char* aTopic, const nsACString& aScopePrefix); michael@0: michael@0: private: michael@0: CacheParentBridge* NewCache(const nsACString& aScope); michael@0: michael@0: ThreadSafeAutoRefCnt mRefCnt; michael@0: NS_DECL_OWNINGTHREAD michael@0: michael@0: // True when IPC channel is open and Send*() methods are OK to use. michael@0: bool mIPCOpen; michael@0: }; michael@0: michael@0: } // ::dom michael@0: } // ::mozilla michael@0: michael@0: #endif