void setJSIDBDatabaseOnversionchange(ExecState* exec, JSObject* thisObject, JSValue value) { UNUSED_PARAM(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(thisObject); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); imp->setOnversionchange(createJSAttributeEventListener(exec, value, thisObject)); }
EncodedJSValue JSC_HOST_CALL jsIDBDatabasePrototypeFunctionCreateObjectStore(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBDatabase::s_info)) return throwVMTypeError(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(thisValue)); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); ExceptionCode ec = 0; const String& name(ustringToString(exec->argument(0).toString(exec))); if (exec->hadException()) return JSValue::encode(jsUndefined()); int argsCount = exec->argumentCount(); if (argsCount <= 1) { JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->createObjectStore(name, ec))); setDOMException(exec, ec); return JSValue::encode(result); } OptionsObject* options(toOptionsObject(exec->argument(1))); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->createObjectStore(name, options, ec))); setDOMException(exec, ec); return JSValue::encode(result); }
void IDBOpenDBRequest::onUpgradeNeeded(int64_t oldVersion, PassOwnPtr<WebIDBDatabase> backend, const IDBDatabaseMetadata& metadata, WebIDBDataLoss dataLoss, String dataLossMessage) { IDB_TRACE("IDBOpenDBRequest::onUpgradeNeeded()"); if (m_contextStopped || !executionContext()) { OwnPtr<WebIDBDatabase> db = backend; db->abort(m_transactionId); db->close(); return; } if (!shouldEnqueueEvent()) return; ASSERT(m_databaseCallbacks); IDBDatabase* idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release()); idbDatabase->setMetadata(metadata); if (oldVersion == IDBDatabaseMetadata::NoIntVersion) { // This database hasn't had an integer version before. oldVersion = IDBDatabaseMetadata::DefaultIntVersion; } IDBDatabaseMetadata oldMetadata(metadata); oldMetadata.intVersion = oldVersion; m_transaction = IDBTransaction::create(scriptState(), m_transactionId, idbDatabase, this, oldMetadata); setResult(IDBAny::create(idbDatabase)); if (m_version == IDBDatabaseMetadata::NoIntVersion) m_version = 1; enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::upgradeneeded, oldVersion, m_version, dataLoss, dataLossMessage)); }
void IDBConnectionProxy::registerDatabaseConnection(IDBDatabase& database) { Locker<Lock> locker(m_databaseConnectionMapLock); ASSERT(!m_databaseConnectionMap.contains(database.databaseConnectionIdentifier())); m_databaseConnectionMap.set(database.databaseConnectionIdentifier(), &database); }
void IDBOpenDBRequest::onSuccess(PassOwnPtr<WebIDBDatabase> backend, const IDBDatabaseMetadata& metadata) { IDB_TRACE("IDBOpenDBRequest::onSuccess()"); if (m_contextStopped || !executionContext()) { OwnPtr<WebIDBDatabase> db = backend; if (db) db->close(); return; } if (!shouldEnqueueEvent()) return; IDBDatabase* idbDatabase = nullptr; if (resultAsAny()) { // Previous onUpgradeNeeded call delivered the backend. ASSERT(!backend.get()); idbDatabase = resultAsAny()->idbDatabase(); ASSERT(idbDatabase); ASSERT(!m_databaseCallbacks); } else { ASSERT(backend.get()); ASSERT(m_databaseCallbacks); idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release()); setResult(IDBAny::create(idbDatabase)); } idbDatabase->setMetadata(metadata); enqueueEvent(Event::create(EventTypeNames::success)); }
void IDBConnectionProxy::unregisterDatabaseConnection(IDBDatabase& database) { Locker<Lock> locker(m_databaseConnectionMapLock); ASSERT(!m_databaseConnectionMap.contains(database.databaseConnectionIdentifier()) || m_databaseConnectionMap.get(database.databaseConnectionIdentifier()) == &database); m_databaseConnectionMap.remove(database.databaseConnectionIdentifier()); }
JSValue jsIDBDatabaseObjectStoreNames(ExecState* exec, JSValue slotBase, const Identifier&) { JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(slotBase)); UNUSED_PARAM(exec); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->objectStoreNames())); return result; }
JSValue jsIDBDatabaseVersion(ExecState* exec, JSValue slotBase, const Identifier&) { JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(slotBase)); UNUSED_PARAM(exec); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); JSValue result = jsString(exec, imp->version()); return result; }
IDBDatabase* IDBDatabase::create(ExecutionContext* context, std::unique_ptr<WebIDBDatabase> database, IDBDatabaseCallbacks* callbacks) { IDBDatabase* idbDatabase = new IDBDatabase(context, std::move(database), callbacks); idbDatabase->suspendIfNeeded(); return idbDatabase; }
EncodedJSValue JSC_HOST_CALL jsIDBDatabasePrototypeFunctionClose(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBDatabase::s_info)) return throwVMTypeError(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(thisValue)); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); imp->close(); return JSValue::encode(jsUndefined()); }
EncodedJSValue JSC_HOST_CALL jsIDBDatabasePrototypeFunctionRemoveEventListener(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBDatabase::s_info)) return throwVMTypeError(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(thisValue)); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); JSValue listener = exec->argument(1); if (!listener.isObject()) return JSValue::encode(jsUndefined()); imp->removeEventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), castedThis, false, currentWorld(exec)).get(), exec->argument(2).toBoolean(exec)); return JSValue::encode(jsUndefined()); }
JSValue jsIDBDatabaseOnversionchange(ExecState* exec, JSValue slotBase, const Identifier&) { JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(slotBase)); UNUSED_PARAM(exec); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); if (EventListener* listener = imp->onversionchange()) { if (const JSEventListener* jsListener = JSEventListener::cast(listener)) { if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext())) return jsFunction; } } return jsNull(); }
EncodedJSValue JSC_HOST_CALL jsIDBDatabasePrototypeFunctionDeleteObjectStore(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBDatabase::s_info)) return throwVMTypeError(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(thisValue)); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); ExceptionCode ec = 0; const String& name(ustringToString(exec->argument(0).toString(exec))); if (exec->hadException()) return JSValue::encode(jsUndefined()); imp->deleteObjectStore(name, ec); setDOMException(exec, ec); return JSValue::encode(jsUndefined()); }
IDBTransaction::IDBTransaction(IDBDatabase& database, const IDBTransactionInfo& info) : WebCore::IDBTransaction(database.scriptExecutionContext()) , m_database(database) , m_info(info) , m_operationTimer(*this, &IDBTransaction::operationTimerFired) { relaxAdoptionRequirement(); if (m_info.mode() == IndexedDB::TransactionMode::VersionChange) { m_originalDatabaseInfo = std::make_unique<IDBDatabaseInfo>(m_database->info()); m_startedOnServer = true; } else { activate(); RefPtr<IDBTransaction> self; JSC::VM& vm = JSDOMWindowBase::commonVM(); vm.whenIdle([self, this]() { deactivate(); }); establishOnServer(); } suspendIfNeeded(); }
IDBTransaction::IDBTransaction(IDBDatabase& database, const IDBTransactionInfo& info, IDBOpenDBRequest* request) : WebCore::IDBTransaction(database.scriptExecutionContext()) , m_database(database) , m_info(info) , m_operationTimer(*this, &IDBTransaction::operationTimerFired) , m_openDBRequest(request) { LOG(IndexedDB, "IDBTransaction::IDBTransaction - %s", m_info.loggingString().utf8().data()); relaxAdoptionRequirement(); if (m_info.mode() == IndexedDB::TransactionMode::VersionChange) { ASSERT(m_openDBRequest); m_openDBRequest->setVersionChangeTransaction(*this); m_startedOnServer = true; } else { activate(); RefPtr<IDBTransaction> self; JSC::VM& vm = JSDOMWindowBase::commonVM(); vm.whenIdle([self, this]() { deactivate(); }); establishOnServer(); } suspendIfNeeded(); }
EncodedJSValue JSC_HOST_CALL jsIDBDatabasePrototypeFunctionDispatchEvent(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBDatabase::s_info)) return throwVMTypeError(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(thisValue)); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); ExceptionCode ec = 0; Event* evt(toEvent(exec->argument(0))); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSC::JSValue result = jsBoolean(imp->dispatchEvent(evt, ec)); setDOMException(exec, ec); return JSValue::encode(result); }
EncodedJSValue JSC_HOST_CALL jsIDBDatabasePrototypeFunctionSetVersion(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBDatabase::s_info)) return throwVMTypeError(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(thisValue)); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); ExceptionCode ec = 0; ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); if (!scriptContext) return JSValue::encode(jsUndefined()); const String& version(ustringToString(exec->argument(0).toString(exec))); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->setVersion(scriptContext, version, ec))); setDOMException(exec, ec); return JSValue::encode(result); }
// static already_AddRefed<IDBCursor> IDBCursor::CreateCommon(IDBRequest* aRequest, IDBTransaction* aTransaction, IDBObjectStore* aObjectStore, Direction aDirection, const Key& aRangeKey, const nsACString& aContinueQuery, const nsACString& aContinueToQuery) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aRequest, "Null pointer!"); NS_ASSERTION(aTransaction, "Null pointer!"); NS_ASSERTION(aObjectStore, "Null pointer!"); NS_ASSERTION(!aContinueQuery.IsEmpty(), "Empty query!"); NS_ASSERTION(!aContinueToQuery.IsEmpty(), "Empty query!"); nsRefPtr<IDBCursor> cursor = new IDBCursor(); IDBDatabase* database = aTransaction->Database(); cursor->mScriptOwner = database->GetScriptOwner(); if (cursor->mScriptOwner) { if (NS_FAILED(NS_HOLD_JS_OBJECTS(cursor, IDBCursor))) { return nsnull; } cursor->mRooted = true; } cursor->mRequest = aRequest; cursor->mTransaction = aTransaction; cursor->mObjectStore = aObjectStore; cursor->mDirection = aDirection; cursor->mContinueQuery = aContinueQuery; cursor->mContinueToQuery = aContinueToQuery; cursor->mRangeKey = aRangeKey; return cursor.forget(); }
EncodedJSValue JSC_HOST_CALL jsIDBDatabasePrototypeFunctionTransaction(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBDatabase::s_info)) return throwVMTypeError(exec); JSIDBDatabase* castedThis = static_cast<JSIDBDatabase*>(asObject(thisValue)); IDBDatabase* imp = static_cast<IDBDatabase*>(castedThis->impl()); ExceptionCode ec = 0; ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); if (!scriptContext) return JSValue::encode(jsUndefined()); int argsCount = exec->argumentCount(); if (argsCount <= 0) { JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->transaction(scriptContext, ec))); setDOMException(exec, ec); return JSValue::encode(result); } DOMStringList* storeNames(toDOMStringList(exec->argument(0))); if (exec->hadException()) return JSValue::encode(jsUndefined()); if (argsCount <= 1) { JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->transaction(scriptContext, storeNames, ec))); setDOMException(exec, ec); return JSValue::encode(result); } unsigned short mode(exec->argument(1).toUInt32(exec)); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->transaction(scriptContext, storeNames, mode, ec))); setDOMException(exec, ec); return JSValue::encode(result); }
// static already_AddRefed<IDBIndex> IDBIndex::Create(IDBObjectStore* aObjectStore, const IndexInfo* aIndexInfo) { NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aObjectStore, "Null pointer!"); NS_ASSERTION(aIndexInfo, "Null pointer!"); IDBDatabase* database = aObjectStore->Transaction()->Database(); nsRefPtr<IDBIndex> index = new IDBIndex(); index->mScriptContext = database->ScriptContext(); index->mOwner = database->Owner(); index->mObjectStore = aObjectStore; index->mId = aIndexInfo->id; index->mName = aIndexInfo->name; index->mKeyPath = aIndexInfo->keyPath; index->mUnique = aIndexInfo->unique; index->mAutoIncrement = aIndexInfo->autoIncrement; return index.forget(); }
NS_IMETHODIMP CommitHelper::Run() { if (NS_IsMainThread()) { NS_ASSERTION(mDoomedObjects.IsEmpty(), "Didn't release doomed objects!"); mTransaction->mReadyState = IDBTransaction::DONE; // Release file infos on the main thread, so they will eventually get // destroyed on correct thread. mTransaction->ClearCreatedFileInfos(); if (mUpdateFileRefcountFunction) { mUpdateFileRefcountFunction->ClearFileInfoEntries(); mUpdateFileRefcountFunction = nullptr; } nsCOMPtr<nsIDOMEvent> event; if (NS_FAILED(mAbortCode)) { if (mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE) { // This will make the database take a snapshot of it's DatabaseInfo mTransaction->Database()->Close(); // Then remove the info from the hash as it contains invalid data. DatabaseInfo::Remove(mTransaction->Database()->Id()); } event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR), eDoesBubble, eNotCancelable); // The transaction may already have an error object (e.g. if one of the // requests failed). If it doesn't, and it wasn't aborted // programmatically, create one now. if (!mTransaction->mError && mAbortCode != NS_ERROR_DOM_INDEXEDDB_ABORT_ERR) { mTransaction->mError = DOMError::CreateForNSResult(mAbortCode); } } else { event = CreateGenericEvent(NS_LITERAL_STRING(COMPLETE_EVT_STR), eDoesNotBubble, eNotCancelable); } NS_ENSURE_TRUE(event, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (mListener) { mListener->NotifyTransactionPreComplete(mTransaction); } bool dummy; if (NS_FAILED(mTransaction->DispatchEvent(event, &dummy))) { NS_WARNING("Dispatch failed!"); } #ifdef DEBUG mTransaction->mFiredCompleteOrAbort = true; #endif if (mListener) { mListener->NotifyTransactionPostComplete(mTransaction); } mTransaction = nullptr; return NS_OK; } IDBDatabase* database = mTransaction->Database(); if (database->IsInvalidated()) { mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (mConnection) { QuotaManager::SetCurrentWindow(database->GetOwner()); if (NS_SUCCEEDED(mAbortCode) && mUpdateFileRefcountFunction && NS_FAILED(mUpdateFileRefcountFunction->WillCommit(mConnection))) { mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (NS_SUCCEEDED(mAbortCode) && NS_FAILED(WriteAutoIncrementCounts())) { mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (NS_SUCCEEDED(mAbortCode)) { NS_NAMED_LITERAL_CSTRING(release, "COMMIT TRANSACTION"); nsresult rv = mConnection->ExecuteSimpleSQL(release); if (NS_SUCCEEDED(rv)) { if (mUpdateFileRefcountFunction) { mUpdateFileRefcountFunction->DidCommit(); } CommitAutoIncrementCounts(); } else if (rv == NS_ERROR_FILE_NO_DEVICE_SPACE) { // mozstorage translates SQLITE_FULL to NS_ERROR_FILE_NO_DEVICE_SPACE, // which we know better as NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR. mAbortCode = NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR; } else { mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } if (NS_FAILED(mAbortCode)) { if (mUpdateFileRefcountFunction) { mUpdateFileRefcountFunction->DidAbort(); } RevertAutoIncrementCounts(); NS_NAMED_LITERAL_CSTRING(rollback, "ROLLBACK TRANSACTION"); if (NS_FAILED(mConnection->ExecuteSimpleSQL(rollback))) { NS_WARNING("Failed to rollback transaction!"); } } } mDoomedObjects.Clear(); if (mConnection) { if (mUpdateFileRefcountFunction) { nsresult rv = mConnection->RemoveFunction( NS_LITERAL_CSTRING("update_refcount")); if (NS_FAILED(rv)) { NS_WARNING("Failed to remove function!"); } } mConnection->Close(); mConnection = nullptr; QuotaManager::SetCurrentWindow(nullptr); } return NS_OK; }
IDBDatabase* IDBDatabase::create(ExecutionContext* context, PassOwnPtr<WebIDBDatabase> database, IDBDatabaseCallbacks* callbacks) { IDBDatabase* idbDatabase = new IDBDatabase(context, database, callbacks); idbDatabase->suspendIfNeeded(); return idbDatabase; }
void IDBConnectionToServer::databaseConnectionClosed(IDBDatabase& database) { LOG(IndexedDB, "IDBConnectionToServer::databaseConnectionClosed"); m_delegate->databaseConnectionClosed(database.databaseConnectionIdentifier()); }
void IDBConnectionToServer::registerDatabaseConnection(IDBDatabase& database) { ASSERT(!m_databaseConnectionMap.contains(database.databaseConnectionIdentifier())); m_databaseConnectionMap.set(database.databaseConnectionIdentifier(), &database); }
void IDBConnectionToServer::unregisterDatabaseConnection(IDBDatabase& database) { ASSERT(m_databaseConnectionMap.contains(database.databaseConnectionIdentifier())); ASSERT(m_databaseConnectionMap.get(database.databaseConnectionIdentifier()) == &database); m_databaseConnectionMap.remove(database.databaseConnectionIdentifier()); }
void IDBConnectionProxy::confirmDidCloseFromServer(IDBDatabase& database) { callConnectionOnMainThread(&IDBConnectionToServer::confirmDidCloseFromServer, database.databaseConnectionIdentifier()); }
void IDBConnectionProxy::databaseConnectionClosed(IDBDatabase& database) { callConnectionOnMainThread(&IDBConnectionToServer::databaseConnectionClosed, database.databaseConnectionIdentifier()); }
nsresult DataStoreDB::UpgradeSchema(nsIDOMEvent* aEvent) { MOZ_ASSERT(NS_IsMainThread()); // This DB has been just created and we have to inform the callback about // this. mCreatedSchema = true; #ifdef DEBUG nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent); MOZ_ASSERT(event); Nullable<uint64_t> version = event->GetNewVersion(); MOZ_ASSERT(!version.IsNull()); MOZ_ASSERT(version.Value() == DATASTOREDB_VERSION); #endif ErrorResult error; JS::Rooted<JS::Value> result(nsContentUtils::RootingCx()); mRequest->GetResult(&result, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } MOZ_ASSERT(result.isObject()); IDBDatabase* database = nullptr; nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database); if (NS_FAILED(rv)) { NS_WARNING("Didn't get the object we expected!"); return rv; } { IDBObjectStoreParameters params; params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }")); RefPtr<IDBObjectStore> store = database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_NAME), params, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } } RefPtr<IDBObjectStore> store; { IDBObjectStoreParameters params; params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }")); store = database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), params, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } } { IDBIndexParameters params; params.Init(NS_LITERAL_STRING("{ \"unique\": true }")); RefPtr<IDBIndex> index = store->CreateIndex(NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX), NS_LITERAL_STRING("revisionId"), params, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } } return NS_OK; }