michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ 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 mozilla_dom_indexeddb_idbobjectstore_h__ michael@0: #define mozilla_dom_indexeddb_idbobjectstore_h__ michael@0: michael@0: #include "mozilla/dom/indexedDB/IndexedDatabase.h" michael@0: michael@0: #include "js/TypeDecls.h" michael@0: #include "mozilla/dom/IDBCursorBinding.h" michael@0: #include "mozilla/dom/IDBIndexBinding.h" michael@0: #include "mozilla/dom/IDBObjectStoreBinding.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "MainThreadUtils.h" michael@0: michael@0: #include "mozilla/dom/indexedDB/IDBRequest.h" michael@0: #include "mozilla/dom/indexedDB/IDBTransaction.h" michael@0: #include "mozilla/dom/indexedDB/KeyPath.h" michael@0: michael@0: class nsIDOMBlob; michael@0: class nsIScriptContext; michael@0: class nsPIDOMWindow; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class ContentParent; michael@0: class PBlobChild; michael@0: class PBlobParent; michael@0: } michael@0: } michael@0: michael@0: BEGIN_INDEXEDDB_NAMESPACE michael@0: michael@0: class AsyncConnectionHelper; michael@0: class FileManager; michael@0: class IDBCursor; michael@0: class IDBKeyRange; michael@0: class IDBRequest; michael@0: class IndexedDBObjectStoreChild; michael@0: class IndexedDBObjectStoreParent; michael@0: class Key; michael@0: michael@0: struct IndexInfo; michael@0: struct IndexUpdateInfo; michael@0: struct ObjectStoreInfo; michael@0: michael@0: struct FileHandleData; michael@0: struct BlobOrFileData; michael@0: michael@0: class IDBObjectStore MOZ_FINAL : public nsISupports, michael@0: public nsWrapperCache michael@0: { michael@0: public: michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBObjectStore) michael@0: michael@0: static already_AddRefed michael@0: Create(IDBTransaction* aTransaction, michael@0: ObjectStoreInfo* aInfo, michael@0: const nsACString& aDatabaseId, michael@0: bool aCreating); michael@0: michael@0: static nsresult michael@0: AppendIndexUpdateInfo(int64_t aIndexID, michael@0: const KeyPath& aKeyPath, michael@0: bool aUnique, michael@0: bool aMultiEntry, michael@0: JSContext* aCx, michael@0: JS::Handle aObject, michael@0: nsTArray& aUpdateInfoArray); michael@0: michael@0: static nsresult michael@0: UpdateIndexes(IDBTransaction* aTransaction, michael@0: int64_t aObjectStoreId, michael@0: const Key& aObjectStoreKey, michael@0: bool aOverwrite, michael@0: int64_t aObjectDataId, michael@0: const nsTArray& aUpdateInfoArray); michael@0: michael@0: static nsresult michael@0: GetStructuredCloneReadInfoFromStatement(mozIStorageStatement* aStatement, michael@0: uint32_t aDataIndex, michael@0: uint32_t aFileIdsIndex, michael@0: IDBDatabase* aDatabase, michael@0: StructuredCloneReadInfo& aInfo); michael@0: michael@0: static void michael@0: ClearCloneReadInfo(StructuredCloneReadInfo& aReadInfo); michael@0: michael@0: static void michael@0: ClearCloneWriteInfo(StructuredCloneWriteInfo& aWriteInfo); michael@0: michael@0: static bool michael@0: DeserializeValue(JSContext* aCx, michael@0: StructuredCloneReadInfo& aCloneReadInfo, michael@0: JS::MutableHandle aValue); michael@0: michael@0: static bool michael@0: SerializeValue(JSContext* aCx, michael@0: StructuredCloneWriteInfo& aCloneWriteInfo, michael@0: JS::Handle aValue); michael@0: michael@0: template michael@0: static JSObject* michael@0: StructuredCloneReadCallback(JSContext* aCx, michael@0: JSStructuredCloneReader* aReader, michael@0: uint32_t aTag, michael@0: uint32_t aData, michael@0: void* aClosure); michael@0: static bool michael@0: StructuredCloneWriteCallback(JSContext* aCx, michael@0: JSStructuredCloneWriter* aWriter, michael@0: JS::Handle aObj, michael@0: void* aClosure); michael@0: michael@0: static nsresult michael@0: ConvertFileIdsToArray(const nsAString& aFileIds, michael@0: nsTArray& aResult); michael@0: michael@0: // Called only in the main process. michael@0: static nsresult michael@0: ConvertBlobsToActors(ContentParent* aContentParent, michael@0: FileManager* aFileManager, michael@0: const nsTArray& aFiles, michael@0: InfallibleTArray& aActors); michael@0: michael@0: // Called only in the child process. michael@0: static void michael@0: ConvertActorsToBlobs(const InfallibleTArray& aActors, michael@0: nsTArray& aFiles); michael@0: michael@0: const nsString& Name() const michael@0: { michael@0: return mName; michael@0: } michael@0: michael@0: bool IsAutoIncrement() const michael@0: { michael@0: return mAutoIncrement; michael@0: } michael@0: michael@0: bool IsWriteAllowed() const michael@0: { michael@0: return mTransaction->IsWriteAllowed(); michael@0: } michael@0: michael@0: int64_t Id() const michael@0: { michael@0: NS_ASSERTION(mId != INT64_MIN, "Don't ask for this yet!"); michael@0: return mId; michael@0: } michael@0: michael@0: const KeyPath& GetKeyPath() const michael@0: { michael@0: return mKeyPath; michael@0: } michael@0: michael@0: const bool HasValidKeyPath() const michael@0: { michael@0: return mKeyPath.IsValid(); michael@0: } michael@0: michael@0: IDBTransaction* Transaction() michael@0: { michael@0: return mTransaction; michael@0: } michael@0: michael@0: ObjectStoreInfo* Info() michael@0: { michael@0: return mInfo; michael@0: } michael@0: michael@0: void michael@0: SetActor(IndexedDBObjectStoreChild* aActorChild) michael@0: { michael@0: NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!"); michael@0: mActorChild = aActorChild; michael@0: } michael@0: michael@0: void michael@0: SetActor(IndexedDBObjectStoreParent* aActorParent) michael@0: { michael@0: NS_ASSERTION(!aActorParent || !mActorParent, michael@0: "Shouldn't have more than one!"); michael@0: mActorParent = aActorParent; michael@0: } michael@0: michael@0: IndexedDBObjectStoreChild* michael@0: GetActorChild() const michael@0: { michael@0: return mActorChild; michael@0: } michael@0: michael@0: IndexedDBObjectStoreParent* michael@0: GetActorParent() const michael@0: { michael@0: return mActorParent; michael@0: } michael@0: michael@0: already_AddRefed michael@0: CreateIndexInternal(const IndexInfo& aInfo, michael@0: ErrorResult& aRv); michael@0: michael@0: nsresult AddOrPutInternal( michael@0: const SerializedStructuredCloneWriteInfo& aCloneWriteInfo, michael@0: const Key& aKey, michael@0: const InfallibleTArray& aUpdateInfoArray, michael@0: const nsTArray >& aBlobs, michael@0: bool aOverwrite, michael@0: IDBRequest** _retval); michael@0: michael@0: already_AddRefed michael@0: GetInternal(IDBKeyRange* aKeyRange, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: GetAllInternal(IDBKeyRange* aKeyRange, michael@0: uint32_t aLimit, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: GetAllKeysInternal(IDBKeyRange* aKeyRange, michael@0: uint32_t aLimit, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: DeleteInternal(IDBKeyRange* aKeyRange, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: CountInternal(IDBKeyRange* aKeyRange, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: OpenCursorInternal(IDBKeyRange* aKeyRange, michael@0: size_t aDirection, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: OpenKeyCursorInternal(IDBKeyRange* aKeyRange, michael@0: size_t aDirection, michael@0: ErrorResult& aRv); michael@0: michael@0: nsresult michael@0: OpenCursorFromChildProcess( michael@0: IDBRequest* aRequest, michael@0: size_t aDirection, michael@0: const Key& aKey, michael@0: const SerializedStructuredCloneReadInfo& aCloneInfo, michael@0: nsTArray& aBlobs, michael@0: IDBCursor** _retval); michael@0: michael@0: nsresult michael@0: OpenCursorFromChildProcess(IDBRequest* aRequest, michael@0: size_t aDirection, michael@0: const Key& aKey, michael@0: IDBCursor** _retval); michael@0: michael@0: void michael@0: SetInfo(ObjectStoreInfo* aInfo); michael@0: michael@0: static const JSClass sDummyPropJSClass; michael@0: michael@0: // nsWrapperCache michael@0: virtual JSObject* michael@0: WrapObject(JSContext* aCx) MOZ_OVERRIDE; michael@0: michael@0: // WebIDL michael@0: IDBTransaction* michael@0: GetParentObject() const michael@0: { michael@0: return mTransaction; michael@0: } michael@0: michael@0: void michael@0: GetName(nsString& aName) const michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: aName.Assign(mName); michael@0: } michael@0: michael@0: void michael@0: GetKeyPath(JSContext* aCx, JS::MutableHandle aResult, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: GetIndexNames(ErrorResult& aRv); michael@0: michael@0: IDBTransaction* michael@0: Transaction() const michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: return mTransaction; michael@0: } michael@0: michael@0: bool michael@0: AutoIncrement() const michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: return mAutoIncrement; michael@0: } michael@0: michael@0: already_AddRefed michael@0: Put(JSContext* aCx, JS::Handle aValue, michael@0: JS::Handle aKey, ErrorResult& aRv) michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: return AddOrPut(aCx, aValue, aKey, true, aRv); michael@0: } michael@0: michael@0: already_AddRefed michael@0: Add(JSContext* aCx, JS::Handle aValue, michael@0: JS::Handle aKey, ErrorResult& aRv) michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: return AddOrPut(aCx, aValue, aKey, false, aRv); michael@0: } michael@0: michael@0: already_AddRefed michael@0: Delete(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: Get(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: Clear(ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: OpenCursor(JSContext* aCx, JS::Handle aRange, michael@0: IDBCursorDirection aDirection, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: CreateIndex(JSContext* aCx, const nsAString& aName, const nsAString& aKeyPath, michael@0: const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: CreateIndex(JSContext* aCx, const nsAString& aName, michael@0: const Sequence& aKeyPath, michael@0: const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: Index(const nsAString& aName, ErrorResult &aRv); michael@0: michael@0: void michael@0: DeleteIndex(const nsAString& aIndexName, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: Count(JSContext* aCx, JS::Handle aKey, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: GetAll(JSContext* aCx, JS::Handle aKey, michael@0: const Optional& aLimit, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: GetAllKeys(JSContext* aCx, JS::Handle aKey, michael@0: const Optional& aLimit, ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: OpenKeyCursor(JSContext* aCx, JS::Handle aRange, michael@0: IDBCursorDirection aDirection, ErrorResult& aRv); michael@0: michael@0: protected: michael@0: IDBObjectStore(); michael@0: ~IDBObjectStore(); michael@0: michael@0: nsresult GetAddInfo(JSContext* aCx, michael@0: JS::Handle aValue, michael@0: JS::Handle aKeyVal, michael@0: StructuredCloneWriteInfo& aCloneWriteInfo, michael@0: Key& aKey, michael@0: nsTArray& aUpdateInfoArray); michael@0: michael@0: already_AddRefed michael@0: AddOrPut(JSContext* aCx, JS::Handle aValue, michael@0: JS::Handle aKey, bool aOverwrite, michael@0: ErrorResult& aRv); michael@0: michael@0: already_AddRefed michael@0: CreateIndex(JSContext* aCx, const nsAString& aName, KeyPath& aKeyPath, michael@0: const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv); michael@0: michael@0: static void michael@0: ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer); michael@0: michael@0: static bool michael@0: ReadFileHandle(JSStructuredCloneReader* aReader, michael@0: FileHandleData* aRetval); michael@0: michael@0: static bool michael@0: ReadBlobOrFile(JSStructuredCloneReader* aReader, michael@0: uint32_t aTag, michael@0: BlobOrFileData* aRetval); michael@0: private: michael@0: nsRefPtr mTransaction; michael@0: michael@0: int64_t mId; michael@0: nsString mName; michael@0: KeyPath mKeyPath; michael@0: JS::Heap mCachedKeyPath; michael@0: bool mRooted; michael@0: bool mAutoIncrement; michael@0: nsCString mDatabaseId; michael@0: nsRefPtr mInfo; michael@0: michael@0: nsTArray > mCreatedIndexes; michael@0: michael@0: IndexedDBObjectStoreChild* mActorChild; michael@0: IndexedDBObjectStoreParent* mActorParent; michael@0: }; michael@0: michael@0: END_INDEXEDDB_NAMESPACE michael@0: michael@0: #endif // mozilla_dom_indexeddb_idbobjectstore_h__