NS_IMETHODIMP IDBDatabase::DeleteObjectStore(const nsAString& aName) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction(); if (!transaction || transaction->Mode() != nsIIDBTransaction::VERSION_CHANGE) { return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; } DatabaseInfo* info = transaction->DBInfo(); ObjectStoreInfo* objectStoreInfo = info->GetObjectStore(aName); if (!objectStoreInfo) { return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR; } nsRefPtr<DeleteObjectStoreHelper> helper = new DeleteObjectStoreHelper(transaction, objectStoreInfo->id); nsresult rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); transaction->RemoveObjectStore(aName); return NS_OK; }
NS_IMETHODIMP IDBDatabase::CreateObjectStore(const nsAString& aName, const jsval& aOptions, JSContext* aCx, nsIIDBObjectStore** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction(); if (!transaction || transaction->Mode() != nsIIDBTransaction::VERSION_CHANGE) { return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; } DatabaseInfo* databaseInfo = transaction->DBInfo(); mozilla::dom::IDBObjectStoreParameters params; nsString keyPath; keyPath.SetIsVoid(true); nsTArray<nsString> keyPathArray; if (!JSVAL_IS_VOID(aOptions) && !JSVAL_IS_NULL(aOptions)) { nsresult rv = params.Init(aCx, &aOptions); NS_ENSURE_SUCCESS(rv, rv); // Get keyPath jsval val = params.keyPath; if (!JSVAL_IS_VOID(val) && !JSVAL_IS_NULL(val)) { if (!JSVAL_IS_PRIMITIVE(val) && JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(val))) { JSObject* obj = JSVAL_TO_OBJECT(val); jsuint length; if (!JS_GetArrayLength(aCx, obj, &length)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (!length) { return NS_ERROR_DOM_SYNTAX_ERR; } keyPathArray.SetCapacity(length); for (jsuint index = 0; index < length; index++) { jsval val; JSString* jsstr; nsDependentJSString str; if (!JS_GetElement(aCx, obj, index, &val) || !(jsstr = JS_ValueToString(aCx, val)) || !str.init(aCx, jsstr)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (!IDBObjectStore::IsValidKeyPath(aCx, str)) { return NS_ERROR_DOM_SYNTAX_ERR; } keyPathArray.AppendElement(str); } NS_ASSERTION(!keyPathArray.IsEmpty(), "This shouldn't have happened!"); } else { JSString* jsstr; nsDependentJSString str; if (!(jsstr = JS_ValueToString(aCx, val)) || !str.init(aCx, jsstr)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (!IDBObjectStore::IsValidKeyPath(aCx, str)) { return NS_ERROR_DOM_SYNTAX_ERR; } keyPath = str; } } } if (databaseInfo->ContainsStoreName(aName)) { return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR; } if (params.autoIncrement && ((!keyPath.IsVoid() && keyPath.IsEmpty()) || !keyPathArray.IsEmpty())) { return NS_ERROR_DOM_INVALID_ACCESS_ERR; } nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo()); newInfo->name = aName; newInfo->id = databaseInfo->nextObjectStoreId++; newInfo->keyPath = keyPath; newInfo->keyPathArray = keyPathArray; newInfo->nextAutoIncrementId = params.autoIncrement ? 1 : 0; newInfo->comittedAutoIncrementId = newInfo->nextAutoIncrementId; if (!databaseInfo->PutObjectStore(newInfo)) { NS_WARNING("Put failed!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } // Don't leave this in the hash if we fail below! AutoRemoveObjectStore autoRemove(databaseInfo, aName); nsRefPtr<IDBObjectStore> objectStore = transaction->GetOrCreateObjectStore(aName, newInfo); NS_ENSURE_TRUE(objectStore, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr<CreateObjectStoreHelper> helper = new CreateObjectStoreHelper(transaction, objectStore); nsresult rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); autoRemove.forget(); objectStore.forget(_retval); return NS_OK; }