/* 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_indexeddb_ipc_indexeddbparent_h__ #define mozilla_dom_indexeddb_ipc_indexeddbparent_h__ #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "mozilla/dom/indexedDB/IndexedDatabase.h" #include "mozilla/dom/indexedDB/PIndexedDBParent.h" #include "mozilla/dom/indexedDB/PIndexedDBCursorParent.h" #include "mozilla/dom/indexedDB/PIndexedDBDatabaseParent.h" #include "mozilla/dom/indexedDB/PIndexedDBDeleteDatabaseRequestParent.h" #include "mozilla/dom/indexedDB/PIndexedDBIndexParent.h" #include "mozilla/dom/indexedDB/PIndexedDBObjectStoreParent.h" #include "mozilla/dom/indexedDB/PIndexedDBRequestParent.h" #include "mozilla/dom/indexedDB/PIndexedDBTransactionParent.h" #include "nsIDOMEventListener.h" namespace mozilla { namespace dom { class ContentParent; class PBlobParent; class TabParent; } } class nsIDOMBlob; class nsIDOMEvent; BEGIN_INDEXEDDB_NAMESPACE class IDBCursor; class IDBDatabase; class IDBFactory; class IDBIndex; class IDBObjectStore; class IDBOpenDBRequest; class IDBTransaction; class IndexedDBCursorParent; class IndexedDBDatabaseParent; class IndexedDBDeleteDatabaseRequestParent; class IndexedDBIndexParent; class IndexedDBObjectStoreParent; class IndexedDBTransactionParent; class IndexedDBVersionChangeTransactionParent; class IndexedDBVersionChangeObjectStoreParent; /******************************************************************************* * AutoSetCurrentTransaction ******************************************************************************/ class AutoSetCurrentTransaction { public: AutoSetCurrentTransaction(IDBTransaction* aTransaction); ~AutoSetCurrentTransaction(); }; /******************************************************************************* * WeakEventListener ******************************************************************************/ class WeakEventListenerBase : public nsIDOMEventListener { public: NS_DECL_ISUPPORTS NS_DECL_NSIDOMEVENTLISTENER protected: WeakEventListenerBase() { } virtual ~WeakEventListenerBase() { } }; template class WeakEventListener : public WeakEventListenerBase { T* mActor; public: WeakEventListener(T* aActor) : mActor(aActor) { } void NoteDyingActor() { mActor = nullptr; } NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE { return mActor ? mActor->HandleEvent(aEvent) : NS_OK; } protected: virtual ~WeakEventListener() { } }; template class AutoWeakEventListener { nsRefPtr > mEventListener; public: AutoWeakEventListener(T* aActor) { mEventListener = new WeakEventListener(aActor); } ~AutoWeakEventListener() { mEventListener->NoteDyingActor(); } template operator U*() { return mEventListener; } T* operator ->() { return mEventListener; } }; /******************************************************************************* * IndexedDBParent ******************************************************************************/ class IndexedDBParent : private PIndexedDBParent { friend class mozilla::dom::ContentParent; friend class mozilla::dom::TabParent; friend class IndexedDBDatabaseParent; friend class IndexedDBDeleteDatabaseRequestParent; nsRefPtr mFactory; nsCString mASCIIOrigin; ContentParent* mManagerContent; TabParent* mManagerTab; bool mDisconnected; public: IndexedDBParent(ContentParent* aContentParent); IndexedDBParent(TabParent* aTabParent); virtual ~IndexedDBParent(); const nsCString& GetASCIIOrigin() const { return mASCIIOrigin; } void Disconnect(); bool IsDisconnected() const { return mDisconnected; } ContentParent* GetManagerContent() const { return mManagerContent; } TabParent* GetManagerTab() const { return mManagerTab; } bool CheckReadPermission(const nsAString& aDatabaseName); bool CheckWritePermission(const nsAString& aDatabaseName); mozilla::ipc::IProtocol* CloneProtocol(Channel* aChannel, mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE; protected: bool CheckPermissionInternal(const nsAString& aDatabaseName, const nsACString& aPermission); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvPIndexedDBDatabaseConstructor(PIndexedDBDatabaseParent* aActor, const nsString& aName, const uint64_t& aVersion, const PersistenceType& aPersistenceType) MOZ_OVERRIDE; virtual bool RecvPIndexedDBDeleteDatabaseRequestConstructor( PIndexedDBDeleteDatabaseRequestParent* aActor, const nsString& aName, const PersistenceType& aPersistenceType) MOZ_OVERRIDE; virtual PIndexedDBDatabaseParent* AllocPIndexedDBDatabaseParent(const nsString& aName, const uint64_t& aVersion, const PersistenceType& aPersistenceType) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBDatabaseParent(PIndexedDBDatabaseParent* aActor) MOZ_OVERRIDE; virtual PIndexedDBDeleteDatabaseRequestParent* AllocPIndexedDBDeleteDatabaseRequestParent( const nsString& aName, const PersistenceType& aPersistenceType) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBDeleteDatabaseRequestParent( PIndexedDBDeleteDatabaseRequestParent* aActor) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBDatabaseParent ******************************************************************************/ class IndexedDBDatabaseParent : private PIndexedDBDatabaseParent { friend class IndexedDBParent; friend class IndexedDBTransactionParent; friend class IndexedDBVersionChangeTransactionParent; AutoWeakEventListener mEventListener; nsRefPtr mOpenRequest; nsRefPtr mDatabase; public: IndexedDBDatabaseParent(); virtual ~IndexedDBDatabaseParent(); nsresult SetOpenRequest(IDBOpenDBRequest* aRequest); nsresult HandleEvent(nsIDOMEvent* aEvent); void Disconnect(); bool IsDisconnected() const { return static_cast(Manager())->IsDisconnected(); } bool CheckWritePermission(const nsAString& aDatabaseName); void Invalidate(); protected: nsresult HandleRequestEvent(nsIDOMEvent* aEvent, const nsAString& aType); nsresult HandleDatabaseEvent(nsIDOMEvent* aEvent, const nsAString& aType); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvClose(const bool& aUnlinked) MOZ_OVERRIDE; virtual bool RecvPIndexedDBTransactionConstructor(PIndexedDBTransactionParent* aActor, const TransactionParams& aParams) MOZ_OVERRIDE; virtual PIndexedDBTransactionParent* AllocPIndexedDBTransactionParent(const TransactionParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBTransactionParent(PIndexedDBTransactionParent* aActor) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBTransactionParent ******************************************************************************/ class IndexedDBTransactionParent : protected PIndexedDBTransactionParent { friend class IndexedDBCursorParent; friend class IndexedDBDatabaseParent; friend class IndexedDBObjectStoreParent; protected: AutoWeakEventListener mEventListener; nsRefPtr mTransaction; bool mArtificialRequestCount; public: IndexedDBTransactionParent(); virtual ~IndexedDBTransactionParent(); bool IsDisconnected() const { return static_cast(Manager())->IsDisconnected(); } nsresult SetTransaction(IDBTransaction* aTransaction); IDBTransaction* GetTransaction() const { return mTransaction; } nsresult HandleEvent(nsIDOMEvent* aEvent); protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvAbort(const nsresult& aAbortCode) MOZ_OVERRIDE; virtual bool RecvAllRequestsFinished() MOZ_OVERRIDE; virtual bool RecvDeleteObjectStore(const nsString& aName) MOZ_OVERRIDE; virtual bool RecvPIndexedDBObjectStoreConstructor( PIndexedDBObjectStoreParent* aActor, const ObjectStoreConstructorParams& aParams) MOZ_OVERRIDE; virtual PIndexedDBObjectStoreParent* AllocPIndexedDBObjectStoreParent(const ObjectStoreConstructorParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBObjectStoreParent(PIndexedDBObjectStoreParent* aActor) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBVersionChangeTransactionParent ******************************************************************************/ class IndexedDBVersionChangeTransactionParent : public IndexedDBTransactionParent { friend class IndexedDBVersionChangeObjectStoreParent; public: IndexedDBVersionChangeTransactionParent(); virtual ~IndexedDBVersionChangeTransactionParent(); bool IsDisconnected() const { return static_cast(Manager())->IsDisconnected(); } protected: virtual bool RecvDeleteObjectStore(const nsString& aName) MOZ_OVERRIDE; virtual bool RecvPIndexedDBObjectStoreConstructor( PIndexedDBObjectStoreParent* aActor, const ObjectStoreConstructorParams& aParams) MOZ_OVERRIDE; virtual PIndexedDBObjectStoreParent* AllocPIndexedDBObjectStoreParent(const ObjectStoreConstructorParams& aParams) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBCursorParent ******************************************************************************/ class IndexedDBCursorParent : private PIndexedDBCursorParent { friend class IndexedDBIndexParent; friend class IndexedDBObjectStoreParent; nsRefPtr mCursor; public: IDBCursor* GetCursor() const { return mCursor; } bool IsDisconnected() const; protected: IndexedDBCursorParent(IDBCursor* aCursor); virtual ~IndexedDBCursorParent(); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvPIndexedDBRequestConstructor(PIndexedDBRequestParent* aActor, const CursorRequestParams& aParams) MOZ_OVERRIDE; virtual PIndexedDBRequestParent* AllocPIndexedDBRequestParent(const CursorRequestParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBRequestParent(PIndexedDBRequestParent* aActor) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBObjectStoreParent ******************************************************************************/ class IndexedDBObjectStoreParent : protected PIndexedDBObjectStoreParent { friend class IndexedDBIndexParent; friend class IndexedDBTransactionParent; friend class IndexedDBVersionChangeTransactionParent; typedef mozilla::dom::indexedDB::ipc::OpenCursorResponse OpenCursorResponse; protected: nsRefPtr mObjectStore; public: IndexedDBObjectStoreParent(); virtual ~IndexedDBObjectStoreParent(); void SetObjectStore(IDBObjectStore* aObjectStore); IDBObjectStore* GetObjectStore() const { return mObjectStore; } bool IsDisconnected() const { IndexedDBTransactionParent* manager = static_cast(Manager()); return manager->IsDisconnected(); } // Ordinarily callers could just do this manually using // PIndexedDBObjectStoreParent::SendPIndexedDBCursorConstructor but we're // inheriting the abstract protocol class privately to prevent outside code // from sending messages without checking the disconnected state. Therefore // we need a helper method. bool OpenCursor(IDBCursor* aCursor, const ObjectStoreCursorConstructorParams& aParams, OpenCursorResponse& aResponse) NS_WARN_UNUSED_RESULT { if (IsDisconnected()) { return true; } IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(aCursor); if (!SendPIndexedDBCursorConstructor(cursorActor, aParams)) { return false; } aResponse = cursorActor; return true; } protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvDeleteIndex(const nsString& aName) MOZ_OVERRIDE; virtual bool RecvPIndexedDBRequestConstructor(PIndexedDBRequestParent* aActor, const ObjectStoreRequestParams& aParams) MOZ_OVERRIDE; virtual bool RecvPIndexedDBIndexConstructor(PIndexedDBIndexParent* aActor, const IndexConstructorParams& aParams) MOZ_OVERRIDE; virtual PIndexedDBRequestParent* AllocPIndexedDBRequestParent(const ObjectStoreRequestParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBRequestParent(PIndexedDBRequestParent* aActor) MOZ_OVERRIDE; virtual PIndexedDBIndexParent* AllocPIndexedDBIndexParent(const IndexConstructorParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBIndexParent(PIndexedDBIndexParent* aActor) MOZ_OVERRIDE; virtual PIndexedDBCursorParent* AllocPIndexedDBCursorParent(const ObjectStoreCursorConstructorParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBCursorParent(PIndexedDBCursorParent* aActor) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBVersionChangeObjectStoreParent ******************************************************************************/ class IndexedDBVersionChangeObjectStoreParent : public IndexedDBObjectStoreParent { friend class IndexedDBVersionChangeTransactionParent; public: IndexedDBVersionChangeObjectStoreParent(); virtual ~IndexedDBVersionChangeObjectStoreParent(); protected: bool IsDisconnected() const { IndexedDBVersionChangeTransactionParent* manager = static_cast(Manager()); return manager->IsDisconnected(); } virtual bool RecvDeleteIndex(const nsString& aName) MOZ_OVERRIDE; virtual bool RecvPIndexedDBIndexConstructor(PIndexedDBIndexParent* aActor, const IndexConstructorParams& aParams) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBIndexParent ******************************************************************************/ class IndexedDBIndexParent : private PIndexedDBIndexParent { friend class IndexedDBObjectStoreParent; friend class IndexedDBVersionChangeObjectStoreParent; typedef mozilla::dom::indexedDB::ipc::OpenCursorResponse OpenCursorResponse; nsRefPtr mIndex; public: IndexedDBIndexParent(); virtual ~IndexedDBIndexParent(); void SetIndex(IDBIndex* aObjectStore); IDBIndex* GetIndex() const { return mIndex; } // Ordinarily callers could just do this manually using // PIndexedDBIndexParent::SendPIndexedDBCursorConstructor but we're // inheriting the abstract protocol class privately to prevent outside code // from sending messages without checking the disconnected state. Therefore // we need a helper method. bool OpenCursor(IDBCursor* aCursor, const IndexCursorConstructorParams& aParams, OpenCursorResponse& aResponse) NS_WARN_UNUSED_RESULT { if (IsDisconnected()) { return true; } IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(aCursor); if (!SendPIndexedDBCursorConstructor(cursorActor, aParams)) { return false; } aResponse = cursorActor; return true; } bool IsDisconnected() const { IndexedDBObjectStoreParent* manager = static_cast(Manager()); return manager->IsDisconnected(); } protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvPIndexedDBRequestConstructor(PIndexedDBRequestParent* aActor, const IndexRequestParams& aParams) MOZ_OVERRIDE; virtual PIndexedDBRequestParent* AllocPIndexedDBRequestParent(const IndexRequestParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBRequestParent(PIndexedDBRequestParent* aActor) MOZ_OVERRIDE; virtual PIndexedDBCursorParent* AllocPIndexedDBCursorParent(const IndexCursorConstructorParams& aParams) MOZ_OVERRIDE; virtual bool DeallocPIndexedDBCursorParent(PIndexedDBCursorParent* aActor) MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBRequestParentBase ******************************************************************************/ class IndexedDBRequestParentBase : public PIndexedDBRequestParent { public: bool SendResponse(const ResponseValue& aResponse) NS_WARN_UNUSED_RESULT { if (IsDisconnected()) { return true; } return Send__delete__(this, aResponse); } protected: // Don't let anyone call this directly, instead go through SendResponse. using PIndexedDBRequestParent::Send__delete__; typedef ipc::ResponseValue ResponseValue; typedef PIndexedDBRequestParent::PBlobParent PBlobParent; nsRefPtr mRequest; IndexedDBRequestParentBase(); virtual ~IndexedDBRequestParentBase(); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool IsDisconnected() = 0; }; /******************************************************************************* * IndexedDBObjectStoreRequestParent ******************************************************************************/ class IndexedDBObjectStoreRequestParent : public IndexedDBRequestParentBase { friend class IndexedDBObjectStoreParent; nsRefPtr mObjectStore; typedef ipc::ObjectStoreRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; DebugOnly mRequestType; typedef ipc::AddParams AddParams; typedef ipc::PutParams PutParams; typedef ipc::ClearParams ClearParams; typedef ipc::DeleteParams DeleteParams; typedef ipc::GetParams GetParams; typedef ipc::GetAllParams GetAllParams; typedef ipc::GetAllKeysParams GetAllKeysParams; typedef ipc::CountParams CountParams; typedef ipc::OpenCursorParams OpenCursorParams; typedef ipc::OpenKeyCursorParams OpenKeyCursorParams; public: IndexedDBObjectStoreRequestParent(IDBObjectStore* aObjectStore, RequestType aRequestType); virtual ~IndexedDBObjectStoreRequestParent(); bool Get(const GetParams& aParams); bool GetAll(const GetAllParams& aParams); bool GetAllKeys(const GetAllKeysParams& aParams); bool Add(const AddParams& aParams); bool Put(const PutParams& aParams); bool Delete(const DeleteParams& aParams); bool Clear(const ClearParams& aParams); bool Count(const CountParams& aParams); bool OpenCursor(const OpenCursorParams& aParams); bool OpenKeyCursor(const OpenKeyCursorParams& aParams); protected: void ConvertBlobActors(const InfallibleTArray& aActors, nsTArray >& aBlobs); private: virtual bool IsDisconnected() MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBIndexRequestParent ******************************************************************************/ class IndexedDBIndexRequestParent : public IndexedDBRequestParentBase { friend class IndexedDBIndexParent; nsRefPtr mIndex; typedef ipc::IndexRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; DebugOnly mRequestType; typedef ipc::GetKeyParams GetKeyParams; typedef ipc::GetAllKeysParams GetAllKeysParams; typedef ipc::OpenKeyCursorParams OpenKeyCursorParams; typedef ipc::GetParams GetParams; typedef ipc::GetAllParams GetAllParams; typedef ipc::CountParams CountParams; typedef ipc::OpenCursorParams OpenCursorParams; public: IndexedDBIndexRequestParent(IDBIndex* aIndex, RequestType aRequestType); virtual ~IndexedDBIndexRequestParent(); bool Get(const GetParams& aParams); bool GetKey(const GetKeyParams& aParams); bool GetAll(const GetAllParams& aParams); bool GetAllKeys(const GetAllKeysParams& aParams); bool Count(const CountParams& aParams); bool OpenCursor(const OpenCursorParams& aParams); bool OpenKeyCursor(const OpenKeyCursorParams& aParams); private: virtual bool IsDisconnected() MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBCursorRequestParent ******************************************************************************/ class IndexedDBCursorRequestParent : public IndexedDBRequestParentBase { friend class IndexedDBCursorParent; nsRefPtr mCursor; typedef ipc::CursorRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; DebugOnly mRequestType; typedef ipc::ContinueParams ContinueParams; public: IndexedDBCursorRequestParent(IDBCursor* aCursor, RequestType aRequestType); virtual ~IndexedDBCursorRequestParent(); bool Continue(const ContinueParams& aParams); private: virtual bool IsDisconnected() MOZ_OVERRIDE; }; /******************************************************************************* * IndexedDBDeleteDatabaseRequestParent ******************************************************************************/ class IndexedDBDeleteDatabaseRequestParent : private PIndexedDBDeleteDatabaseRequestParent { friend class IndexedDBParent; AutoWeakEventListener mEventListener; nsRefPtr mFactory; nsRefPtr mOpenRequest; public: nsresult HandleEvent(nsIDOMEvent* aEvent); protected: IndexedDBDeleteDatabaseRequestParent(IDBFactory* aFactory); virtual ~IndexedDBDeleteDatabaseRequestParent(); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; nsresult SetOpenRequest(IDBOpenDBRequest* aOpenRequest); bool IsDisconnected() const { return static_cast(Manager())->IsDisconnected(); } }; END_INDEXEDDB_NAMESPACE #endif // mozilla_dom_indexeddb_ipc_indexeddbparent_h__