void IDBIndex::SetName(const nsAString& aName, ErrorResult& aRv) { AssertIsOnOwningThread(); IDBTransaction* transaction = mObjectStore->Transaction(); if (transaction->GetMode() != IDBTransaction::VERSION_CHANGE || mDeletedMetadata) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return; } if (aName == mMetadata->name()) { return; } // Cache logging string of this index before renaming. const LoggingString loggingOldIndex(this); const int64_t indexId = Id(); nsresult rv = transaction->Database()->RenameIndex(mObjectStore->Id(), indexId, aName); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } // Don't do this in the macro because we always need to increment the serial // number to keep in sync with the parent. const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "rename(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.rename()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), requestSerialNumber, IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), loggingOldIndex.get(), IDB_LOG_STRINGIFY(this)); transaction->RenameIndex(mObjectStore, indexId, aName); }
void TransactionThreadPool::AbortTransactionsForDatabase(IDBDatabase* aDatabase) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aDatabase, "Null pointer!"); // Get list of transactions for this database id DatabaseTransactionInfo* dbTransactionInfo; if (!mTransactionsInProgress.Get(aDatabase->Id(), &dbTransactionInfo)) { // If there are no running transactions, there can't be any pending ones return; } nsAutoTArray<nsRefPtr<IDBTransaction>, 50> transactions; // Collect any running transactions nsTArray<TransactionInfo>& transactionsInProgress = dbTransactionInfo->transactions; PRUint32 transactionCount = transactionsInProgress.Length(); NS_ASSERTION(transactionCount, "Should never be 0!"); for (PRUint32 index = 0; index < transactionCount; index++) { // See if any transaction belongs to this IDBDatabase instance IDBTransaction* transaction = transactionsInProgress[index].transaction; if (transaction->Database() == aDatabase) { transactions.AppendElement(transaction); } } // Collect any pending transactions. for (PRUint32 index = 0; index < mDelayedDispatchQueue.Length(); index++) { // See if any transaction belongs to this IDBDatabase instance IDBTransaction* transaction = mDelayedDispatchQueue[index].transaction; if (transaction->Database() == aDatabase) { transactions.AppendElement(transaction); } } // Abort transactions. Do this after collecting the transactions in case // calling Abort() modifies the data structures we're iterating above. for (PRUint32 index = 0; index < transactions.Length(); index++) { // This can fail, for example if the transaction is in the process of // being comitted. That is expected and fine, so we ignore any returned // errors. transactions[index]->Abort(); } }
AsyncConnectionHelper::ChildProcessSendResult AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); // If there's no request, there could never have been an actor, and so there // is nothing to do. if (!mRequest) { return Success_NotSent; } IDBTransaction* trans = GetCurrentTransaction(); // We may not have a transaction, e.g. for deleteDatabase if (!trans) { return Success_NotSent; } // Are we shutting down the child? IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent(); if (dbActor && dbActor->IsDisconnected()) { return Success_ActorDisconnected; } IndexedDBRequestParentBase* actor = mRequest->GetActorParent(); if (!actor) { return Success_NotSent; } return SendResponseToChildProcess(aResultCode); }
already_AddRefed<IDBRequest> IDBIndex::Count(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv) { AssertIsOnOwningThread(); if (mDeletedMetadata) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } RefPtr<IDBKeyRange> keyRange; aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); if (aRv.Failed()) { return nullptr; } IndexCountParams params; params.objectStoreId() = mObjectStore->Id(); params.indexId() = Id(); if (keyRange) { SerializedKeyRange serializedKeyRange; keyRange->ToSerialized(serializedKeyRange); params.optionalKeyRange() = serializedKeyRange; } else { params.optionalKeyRange() = void_t(); } RefPtr<IDBRequest> request = GenerateRequest(this); MOZ_ASSERT(request); IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "count(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange)); transaction->StartRequest(request, params); return request.forget(); }
void IDBDatabase::DeleteObjectStore(const nsAString& aName, ErrorResult& aRv) { AssertIsOnOwningThread(); IDBTransaction* transaction = IDBTransaction::GetCurrent(); if (!transaction || transaction->Database() != this || transaction->GetMode() != IDBTransaction::VERSION_CHANGE) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return; } if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return; } nsTArray<ObjectStoreSpec>& specArray = mSpec->objectStores(); int64_t objectStoreId = 0; for (uint32_t specCount = specArray.Length(), specIndex = 0; specIndex < specCount; specIndex++) { const ObjectStoreMetadata& metadata = specArray[specIndex].metadata(); MOZ_ASSERT(metadata.id()); if (aName == metadata.name()) { objectStoreId = metadata.id(); // Must do this before altering the metadata array! transaction->DeleteObjectStore(objectStoreId); specArray.RemoveElementAt(specIndex); RefreshSpec(/* aMayDelete */ false); break; } } if (!objectStoreId) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR); return; } // Don't do this in the macro because we always need to increment the serial // number to keep in sync with the parent. const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).deleteObjectStore(\"%s\")", "IndexedDB %s: C T[%lld] R[%llu]: " "IDBDatabase.deleteObjectStore()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), requestSerialNumber, IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(transaction), NS_ConvertUTF16toUTF8(aName).get()); }
already_AddRefed<IDBObjectStore> IDBDatabase::CreateObjectStore( const nsAString& aName, const IDBObjectStoreParameters& aOptionalParameters, ErrorResult& aRv) { AssertIsOnOwningThread(); IDBTransaction* transaction = IDBTransaction::GetCurrent(); if (!transaction || transaction->Database() != this || transaction->GetMode() != IDBTransaction::VERSION_CHANGE) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } KeyPath keyPath(0); if (NS_FAILED(KeyPath::Parse(aOptionalParameters.mKeyPath, &keyPath))) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return nullptr; } nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores(); for (uint32_t count = objectStores.Length(), index = 0; index < count; index++) { if (aName == objectStores[index].metadata().name()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR); return nullptr; } } if (!keyPath.IsAllowedForObjectStore(aOptionalParameters.mAutoIncrement)) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return nullptr; } const ObjectStoreSpec* oldSpecElements = objectStores.IsEmpty() ? nullptr : objectStores.Elements(); ObjectStoreSpec* newSpec = objectStores.AppendElement(); newSpec->metadata() = ObjectStoreMetadata(transaction->NextObjectStoreId(), nsString(aName), keyPath, aOptionalParameters.mAutoIncrement); if (oldSpecElements && oldSpecElements != objectStores.Elements()) { MOZ_ASSERT(objectStores.Length() > 1); // Array got moved, update the spec pointers for all live objectStores and // indexes. RefreshSpec(/* aMayDelete */ false); } RefPtr<IDBObjectStore> objectStore = transaction->CreateObjectStore(*newSpec); MOZ_ASSERT(objectStore); // Don't do this in the macro because we always need to increment the serial // number to keep in sync with the parent. const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).createObjectStore(%s)", "IndexedDB %s: C T[%lld] R[%llu]: " "IDBDatabase.createObjectStore()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), requestSerialNumber, IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(objectStore)); return objectStore.forget(); }
already_AddRefed<IDBRequest> IDBIndex::OpenCursorInternal(bool aKeysOnly, JSContext* aCx, JS::Handle<JS::Value> aRange, IDBCursorDirection aDirection, ErrorResult& aRv) { AssertIsOnOwningThread(); if (mDeletedMetadata) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } RefPtr<IDBKeyRange> keyRange; aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange)); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } int64_t objectStoreId = mObjectStore->Id(); int64_t indexId = Id(); OptionalKeyRange optionalKeyRange; if (keyRange) { SerializedKeyRange serializedKeyRange; keyRange->ToSerialized(serializedKeyRange); optionalKeyRange = Move(serializedKeyRange); } else { optionalKeyRange = void_t(); } IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection); OpenCursorParams params; if (aKeysOnly) { IndexOpenKeyCursorParams openParams; openParams.objectStoreId() = objectStoreId; openParams.indexId() = indexId; openParams.optionalKeyRange() = Move(optionalKeyRange); openParams.direction() = direction; params = Move(openParams); } else { IndexOpenCursorParams openParams; openParams.objectStoreId() = objectStoreId; openParams.indexId() = indexId; openParams.optionalKeyRange() = Move(optionalKeyRange); openParams.direction() = direction; params = Move(openParams); } RefPtr<IDBRequest> request = GenerateRequest(this); MOZ_ASSERT(request); if (aKeysOnly) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "openKeyCursor(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(direction)); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "openCursor(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: " "IDBObjectStore.openKeyCursor()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(direction)); } BackgroundCursorChild* actor = new BackgroundCursorChild(request, this, direction); mObjectStore->Transaction()->OpenCursor(actor, params); return request.forget(); }
already_AddRefed<IDBRequest> IDBIndex::GetAllInternal(bool aKeysOnly, JSContext* aCx, JS::Handle<JS::Value> aKey, const Optional<uint32_t>& aLimit, ErrorResult& aRv) { AssertIsOnOwningThread(); if (mDeletedMetadata) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } RefPtr<IDBKeyRange> keyRange; aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } const int64_t objectStoreId = mObjectStore->Id(); const int64_t indexId = Id(); OptionalKeyRange optionalKeyRange; if (keyRange) { SerializedKeyRange serializedKeyRange; keyRange->ToSerialized(serializedKeyRange); optionalKeyRange = serializedKeyRange; } else { optionalKeyRange = void_t(); } const uint32_t limit = aLimit.WasPassed() ? aLimit.Value() : 0; RequestParams params; if (aKeysOnly) { params = IndexGetAllKeysParams(objectStoreId, indexId, optionalKeyRange, limit); } else { params = IndexGetAllParams(objectStoreId, indexId, optionalKeyRange, limit); } RefPtr<IDBRequest> request = GenerateRequest(this); MOZ_ASSERT(request); if (aKeysOnly) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "getAllKeys(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(aLimit)); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "getAll(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAll()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(aLimit)); } transaction->StartRequest(request, params); return request.forget(); }
already_AddRefed<IDBRequest> IDBIndex::GetInternal(bool aKeyOnly, JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv) { AssertIsOnOwningThread(); if (mDeletedMetadata) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } RefPtr<IDBKeyRange> keyRange; aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } if (!keyRange) { // Must specify a key or keyRange for get() and getKey(). aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return nullptr; } const int64_t objectStoreId = mObjectStore->Id(); const int64_t indexId = Id(); SerializedKeyRange serializedKeyRange; keyRange->ToSerialized(serializedKeyRange); RequestParams params; if (aKeyOnly) { params = IndexGetKeyParams(objectStoreId, indexId, serializedKeyRange); } else { params = IndexGetParams(objectStoreId, indexId, serializedKeyRange); } RefPtr<IDBRequest> request = GenerateRequest(this); MOZ_ASSERT(request); if (aKeyOnly) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "getKey(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getKey()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange)); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "get(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.get()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange)); } transaction->StartRequest(request, params); return request.forget(); }