1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "IDBDatabase.h"
11 #include "mozilla/EventDispatcher.h"
12 #include "mozilla/Mutex.h"
13 #include "mozilla/storage.h"
14 #include "mozilla/dom/nsIContentParent.h"
15 #include "mozilla/dom/DOMStringList.h"
16 #include "mozilla/dom/DOMStringListBinding.h"
17 #include "mozilla/dom/quota/Client.h"
18 #include "mozilla/dom/quota/QuotaManager.h"
19 #include "nsJSUtils.h"
20 #include "nsProxyRelease.h"
21 #include "nsThreadUtils.h"
23 #include "AsyncConnectionHelper.h"
24 #include "DatabaseInfo.h"
25 #include "IDBEvents.h"
26 #include "IDBFactory.h"
28 #include "IDBMutableFile.h"
29 #include "IDBObjectStore.h"
30 #include "IDBTransaction.h"
31 #include "IDBFactory.h"
32 #include "ProfilerHelpers.h"
33 #include "ReportInternalError.h"
34 #include "TransactionThreadPool.h"
36 #include "ipc/IndexedDBChild.h"
37 #include "ipc/IndexedDBParent.h"
39 #include "mozilla/dom/IDBDatabaseBinding.h"
41 USING_INDEXEDDB_NAMESPACE
42 using mozilla::dom::nsIContentParent
;
43 using mozilla::dom::quota::AssertIsOnIOThread
;
44 using mozilla::dom::quota::Client
;
45 using mozilla::dom::quota::QuotaManager
;
46 using mozilla::ErrorResult
;
47 using namespace mozilla
;
48 using namespace mozilla::dom
;
52 class NoRequestDatabaseHelper
: public AsyncConnectionHelper
55 NoRequestDatabaseHelper(IDBTransaction
* aTransaction
)
56 : AsyncConnectionHelper(aTransaction
, nullptr)
58 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
59 NS_ASSERTION(aTransaction
, "Null transaction!");
62 virtual ChildProcessSendResult
63 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
66 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
)
69 virtual nsresult
OnSuccess() MOZ_OVERRIDE
;
71 virtual void OnError() MOZ_OVERRIDE
;
74 class CreateObjectStoreHelper
: public NoRequestDatabaseHelper
77 CreateObjectStoreHelper(IDBTransaction
* aTransaction
,
78 IDBObjectStore
* aObjectStore
)
79 : NoRequestDatabaseHelper(aTransaction
), mObjectStore(aObjectStore
)
82 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
85 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE
;
88 nsRefPtr
<IDBObjectStore
> mObjectStore
;
91 class DeleteObjectStoreHelper
: public NoRequestDatabaseHelper
94 DeleteObjectStoreHelper(IDBTransaction
* aTransaction
,
95 int64_t aObjectStoreId
)
96 : NoRequestDatabaseHelper(aTransaction
), mObjectStoreId(aObjectStoreId
)
99 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
104 int64_t mObjectStoreId
;
107 class CreateFileHelper
: public AsyncConnectionHelper
110 CreateFileHelper(IDBDatabase
* aDatabase
,
111 IDBRequest
* aRequest
,
112 const nsAString
& aName
,
113 const nsAString
& aType
)
114 : AsyncConnectionHelper(aDatabase
, aRequest
),
115 mName(aName
), mType(aType
)
121 nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
);
122 nsresult
GetSuccessResult(JSContext
* aCx
,
123 JS::MutableHandle
<JS::Value
> aVal
);
124 void ReleaseMainThreadObjects()
127 AsyncConnectionHelper::ReleaseMainThreadObjects();
130 virtual ChildProcessSendResult
SendResponseToChildProcess(
131 nsresult aResultCode
)
134 return Success_NotSent
;
137 virtual nsresult
UnpackResponseFromParentProcess(
138 const ResponseValue
& aResponseValue
)
141 MOZ_CRASH("Should never get here!");
150 nsRefPtr
<FileInfo
> mFileInfo
;
153 class MOZ_STACK_CLASS AutoRemoveObjectStore
156 AutoRemoveObjectStore(DatabaseInfo
* aInfo
, const nsAString
& aName
)
157 : mInfo(aInfo
), mName(aName
)
160 ~AutoRemoveObjectStore()
163 mInfo
->RemoveObjectStore(mName
);
177 } // anonymous namespace
180 already_AddRefed
<IDBDatabase
>
181 IDBDatabase::Create(IDBWrapperCache
* aOwnerCache
,
182 IDBFactory
* aFactory
,
183 already_AddRefed
<DatabaseInfo
> aDatabaseInfo
,
184 const nsACString
& aASCIIOrigin
,
185 FileManager
* aFileManager
,
186 mozilla::dom::nsIContentParent
* aContentParent
)
188 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
189 NS_ASSERTION(aFactory
, "Null pointer!");
190 NS_ASSERTION(!aASCIIOrigin
.IsEmpty(), "Empty origin!");
192 nsRefPtr
<DatabaseInfo
> databaseInfo(aDatabaseInfo
);
193 NS_ASSERTION(databaseInfo
, "Null pointer!");
195 nsRefPtr
<IDBDatabase
> db(new IDBDatabase(aOwnerCache
));
197 db
->SetScriptOwner(aOwnerCache
->GetScriptOwner());
198 db
->mFactory
= aFactory
;
199 db
->mDatabaseId
= databaseInfo
->id
;
200 db
->mName
= databaseInfo
->name
;
201 db
->mFilePath
= databaseInfo
->filePath
;
202 db
->mPersistenceType
= databaseInfo
->persistenceType
;
203 db
->mGroup
= databaseInfo
->group
;
204 databaseInfo
.swap(db
->mDatabaseInfo
);
205 db
->mASCIIOrigin
= aASCIIOrigin
;
206 db
->mFileManager
= aFileManager
;
207 db
->mContentParent
= aContentParent
;
209 QuotaManager
* quotaManager
= QuotaManager::Get();
210 NS_ASSERTION(quotaManager
, "This should never be null!");
212 db
->mQuotaClient
= quotaManager
->GetClient(Client::IDB
);
213 NS_ASSERTION(db
->mQuotaClient
, "This shouldn't fail!");
215 if (!quotaManager
->RegisterStorage(db
)) {
216 // Either out of memory or shutting down.
220 db
->mRegistered
= true;
227 IDBDatabase::FromStorage(nsIOfflineStorage
* aStorage
)
229 return aStorage
->GetClient()->GetType() == Client::IDB
?
230 static_cast<IDBDatabase
*>(aStorage
) : nullptr;
233 IDBDatabase::IDBDatabase(IDBWrapperCache
* aOwnerCache
)
234 : IDBWrapperCache(aOwnerCache
),
235 mActorChild(nullptr),
236 mActorParent(nullptr),
237 mContentParent(nullptr),
241 mRunningVersionChange(false)
243 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
246 IDBDatabase::~IDBDatabase()
248 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
252 IDBDatabase::LastRelease()
254 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
256 NS_ASSERTION(!mActorParent
, "Actor parent owns us, how can we be dying?!");
258 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
259 mActorChild
->Send__delete__(mActorChild
);
260 NS_ASSERTION(!mActorChild
, "Should have cleared in Send__delete__!");
266 QuotaManager
* quotaManager
= QuotaManager::Get();
268 quotaManager
->UnregisterStorage(this);
275 IDBDatabase::Invalidate()
277 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
279 InvalidateInternal(/* aIsDead */ false);
283 IDBDatabase::InvalidateInternal(bool aIsDead
)
285 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
287 if (IsInvalidated()) {
293 // Make sure we're closed too.
296 // When the IndexedDatabaseManager needs to invalidate databases, all it has
297 // is an origin, so we call into the quota manager here to cancel any prompts
299 nsPIDOMWindow
* owner
= GetOwner();
301 QuotaManager::CancelPromptsForWindow(owner
);
304 // We want to forcefully remove in the child when the parent has invalidated
305 // us in IPC mode because the database might no longer exist.
306 // We don't want to forcefully remove in the parent when a child dies since
307 // other child processes may be using the referenced DatabaseInfo.
309 DatabaseInfo::Remove(mDatabaseId
);
312 // And let the child process know as well.
314 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
315 mActorParent
->Invalidate();
320 IDBDatabase::DisconnectFromActorParent()
322 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
323 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
325 // Make sure we're closed too.
328 // Kill any outstanding prompts.
329 nsPIDOMWindow
* owner
= GetOwner();
331 QuotaManager::CancelPromptsForWindow(owner
);
336 IDBDatabase::CloseInternal(bool aIsDead
)
338 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
343 // If we're getting called from Unlink, avoid cloning the DatabaseInfo.
345 nsRefPtr
<DatabaseInfo
> previousInfo
;
346 mDatabaseInfo
.swap(previousInfo
);
349 mDatabaseInfo
= previousInfo
->Clone();
353 QuotaManager
* quotaManager
= QuotaManager::Get();
355 quotaManager
->OnStorageClosed(this);
358 // And let the parent process know as well.
359 if (mActorChild
&& !IsInvalidated()) {
360 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
361 mActorChild
->SendClose(aIsDead
);
367 IDBDatabase::IsClosed()
369 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
374 IDBDatabase::EnterSetVersionTransaction()
376 NS_ASSERTION(!mRunningVersionChange
, "How did that happen?");
378 mPreviousDatabaseInfo
= mDatabaseInfo
->Clone();
380 mRunningVersionChange
= true;
384 IDBDatabase::ExitSetVersionTransaction()
386 NS_ASSERTION(mRunningVersionChange
, "How did that happen?");
388 mPreviousDatabaseInfo
= nullptr;
390 mRunningVersionChange
= false;
394 IDBDatabase::RevertToPreviousState()
396 mDatabaseInfo
= mPreviousDatabaseInfo
;
397 mPreviousDatabaseInfo
= nullptr;
401 IDBDatabase::OnUnlink()
403 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
405 // We've been unlinked, at the very least we should be able to prevent further
406 // transactions from starting and unblock any other SetVersion callers.
409 // No reason for the QuotaManager to track us any longer.
410 QuotaManager
* quotaManager
= QuotaManager::Get();
411 if (mRegistered
&& quotaManager
) {
412 quotaManager
->UnregisterStorage(this);
414 // Don't try to unregister again in the destructor.
419 already_AddRefed
<IDBObjectStore
>
420 IDBDatabase::CreateObjectStoreInternal(IDBTransaction
* aTransaction
,
421 const ObjectStoreInfoGuts
& aInfo
,
424 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
425 NS_ASSERTION(aTransaction
, "Null transaction!");
427 DatabaseInfo
* databaseInfo
= aTransaction
->DBInfo();
429 nsRefPtr
<ObjectStoreInfo
> newInfo
= new ObjectStoreInfo();
430 *static_cast<ObjectStoreInfoGuts
*>(newInfo
.get()) = aInfo
;
432 newInfo
->nextAutoIncrementId
= aInfo
.autoIncrement
? 1 : 0;
433 newInfo
->comittedAutoIncrementId
= newInfo
->nextAutoIncrementId
;
435 if (!databaseInfo
->PutObjectStore(newInfo
)) {
436 IDB_WARNING("Put failed!");
437 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
441 // Don't leave this in the hash if we fail below!
442 AutoRemoveObjectStore
autoRemove(databaseInfo
, newInfo
->name
);
444 nsRefPtr
<IDBObjectStore
> objectStore
=
445 aTransaction
->GetOrCreateObjectStore(newInfo
->name
, newInfo
, true);
447 IDB_WARNING("Failed to get objectStore!");
448 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
452 if (IndexedDatabaseManager::IsMainProcess()) {
453 nsRefPtr
<CreateObjectStoreHelper
> helper
=
454 new CreateObjectStoreHelper(aTransaction
, objectStore
);
456 nsresult rv
= helper
->DispatchToTransactionPool();
458 IDB_WARNING("Failed to dispatch!");
459 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
466 IDB_PROFILER_MARK("IndexedDB Pseudo-request: "
467 "database(%s).transaction(%s).createObjectStore(%s)",
468 "MT IDBDatabase.createObjectStore()",
469 IDB_PROFILER_STRING(this),
470 IDB_PROFILER_STRING(aTransaction
),
471 IDB_PROFILER_STRING(objectStore
));
473 return objectStore
.forget();
476 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBDatabase
)
478 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase
, IDBWrapperCache
)
479 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory
)
480 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
482 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase
, IDBWrapperCache
)
483 // Don't unlink mFactory!
487 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
489 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBDatabase
)
490 NS_INTERFACE_MAP_ENTRY(nsIOfflineStorage
)
491 NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache
)
493 NS_IMPL_ADDREF_INHERITED(IDBDatabase
, IDBWrapperCache
)
494 NS_IMPL_RELEASE_INHERITED(IDBDatabase
, IDBWrapperCache
)
497 IDBDatabase::WrapObject(JSContext
* aCx
)
499 return IDBDatabaseBinding::Wrap(aCx
, this);
503 IDBDatabase::Version() const
505 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
506 DatabaseInfo
* info
= Info();
507 return info
->version
;
510 already_AddRefed
<DOMStringList
>
511 IDBDatabase::GetObjectStoreNames(ErrorResult
& aRv
) const
513 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
515 DatabaseInfo
* info
= Info();
517 nsRefPtr
<DOMStringList
> list(new DOMStringList());
518 if (!info
->GetObjectStoreNames(list
->StringArray())) {
519 IDB_WARNING("Couldn't get names!");
520 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
524 return list
.forget();
527 already_AddRefed
<IDBObjectStore
>
528 IDBDatabase::CreateObjectStore(
529 JSContext
* aCx
, const nsAString
& aName
,
530 const IDBObjectStoreParameters
& aOptionalParameters
,
533 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
535 IDBTransaction
* transaction
= AsyncConnectionHelper::GetCurrentTransaction();
538 transaction
->Database() != this ||
539 transaction
->GetMode() != IDBTransaction::VERSION_CHANGE
) {
540 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR
);
544 DatabaseInfo
* databaseInfo
= transaction
->DBInfo();
547 if (NS_FAILED(KeyPath::Parse(aCx
, aOptionalParameters
.mKeyPath
, &keyPath
))) {
548 aRv
.Throw(NS_ERROR_DOM_SYNTAX_ERR
);
552 if (databaseInfo
->ContainsStoreName(aName
)) {
553 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR
);
557 if (!keyPath
.IsAllowedForObjectStore(aOptionalParameters
.mAutoIncrement
)) {
558 aRv
.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR
);
562 ObjectStoreInfoGuts guts
;
565 guts
.id
= databaseInfo
->nextObjectStoreId
++;
566 guts
.keyPath
= keyPath
;
567 guts
.autoIncrement
= aOptionalParameters
.mAutoIncrement
;
569 return CreateObjectStoreInternal(transaction
, guts
, aRv
);
573 IDBDatabase::DeleteObjectStore(const nsAString
& aName
, ErrorResult
& aRv
)
575 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
577 IDBTransaction
* transaction
= AsyncConnectionHelper::GetCurrentTransaction();
580 transaction
->Database() != this ||
581 transaction
->GetMode() != IDBTransaction::VERSION_CHANGE
) {
582 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR
);
586 DatabaseInfo
* info
= transaction
->DBInfo();
587 ObjectStoreInfo
* objectStoreInfo
= info
->GetObjectStore(aName
);
588 if (!objectStoreInfo
) {
589 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR
);
593 if (IndexedDatabaseManager::IsMainProcess()) {
594 nsRefPtr
<DeleteObjectStoreHelper
> helper
=
595 new DeleteObjectStoreHelper(transaction
, objectStoreInfo
->id
);
597 nsresult rv
= helper
->DispatchToTransactionPool();
599 IDB_WARNING("Failed to dispatch!");
600 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
605 IndexedDBTransactionChild
* actor
= transaction
->GetActorChild();
606 NS_ASSERTION(actor
, "Must have an actor here!");
608 actor
->SendDeleteObjectStore(nsString(aName
));
611 transaction
->RemoveObjectStore(aName
);
613 IDB_PROFILER_MARK("IndexedDB Pseudo-request: "
614 "database(%s).transaction(%s).deleteObjectStore(\"%s\")",
615 "MT IDBDatabase.deleteObjectStore()",
616 IDB_PROFILER_STRING(this),
617 IDB_PROFILER_STRING(transaction
),
618 NS_ConvertUTF16toUTF8(aName
).get());
621 already_AddRefed
<indexedDB::IDBTransaction
>
622 IDBDatabase::Transaction(const Sequence
<nsString
>& aStoreNames
,
623 IDBTransactionMode aMode
, ErrorResult
& aRv
)
625 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
627 if (QuotaManager::IsShuttingDown()) {
628 IDB_REPORT_INTERNAL_ERR();
629 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
634 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR
);
638 if (mRunningVersionChange
) {
639 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR
);
643 if (aStoreNames
.IsEmpty()) {
644 aRv
.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR
);
648 IDBTransaction::Mode transactionMode
= IDBTransaction::READ_ONLY
;
650 case IDBTransactionMode::Readonly
:
651 transactionMode
= IDBTransaction::READ_ONLY
;
653 case IDBTransactionMode::Readwrite
:
654 transactionMode
= IDBTransaction::READ_WRITE
;
656 case IDBTransactionMode::Versionchange
:
657 transactionMode
= IDBTransaction::VERSION_CHANGE
;
660 MOZ_CRASH("Unknown mode!");
663 // Now check to make sure the object store names we collected actually exist.
664 DatabaseInfo
* info
= Info();
665 for (uint32_t index
= 0; index
< aStoreNames
.Length(); index
++) {
666 if (!info
->ContainsStoreName(aStoreNames
[index
])) {
667 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR
);
672 nsRefPtr
<IDBTransaction
> transaction
=
673 IDBTransaction::Create(this, aStoreNames
, transactionMode
, false);
675 IDB_WARNING("Failed to create the transaction!");
676 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
680 IDB_PROFILER_MARK("IndexedDB Transaction %llu: database(%s).transaction(%s)",
681 "IDBTransaction[%llu] MT Started",
682 transaction
->GetSerialNumber(), IDB_PROFILER_STRING(this),
683 IDB_PROFILER_STRING(transaction
));
685 return transaction
.forget();
688 already_AddRefed
<IDBRequest
>
689 IDBDatabase::CreateMutableFile(const nsAString
& aName
,
690 const Optional
<nsAString
>& aType
,
693 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
695 if (!IndexedDatabaseManager::IsMainProcess()) {
696 IDB_WARNING("Not supported yet!");
697 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
701 if (QuotaManager::IsShuttingDown()) {
702 IDB_REPORT_INTERNAL_ERR();
703 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
708 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR
);
712 nsRefPtr
<IDBRequest
> request
= IDBRequest::Create(this, nullptr);
714 nsRefPtr
<CreateFileHelper
> helper
=
715 new CreateFileHelper(this, request
, aName
,
716 aType
.WasPassed() ? aType
.Value() : EmptyString());
718 QuotaManager
* quotaManager
= QuotaManager::Get();
719 NS_ASSERTION(quotaManager
, "We should definitely have a manager here");
721 nsresult rv
= helper
->Dispatch(quotaManager
->IOThread());
723 IDB_WARNING("Failed to dispatch!");
724 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
728 return request
.forget();
734 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
736 CloseInternal(false);
738 NS_ASSERTION(mClosed
, "Should have set the closed flag!");
743 NS_IMETHODIMP_(const nsACString
&)
749 NS_IMETHODIMP_(mozilla::dom::quota::Client
*)
750 IDBDatabase::GetClient()
756 IDBDatabase::IsOwned(nsPIDOMWindow
* aOwner
)
758 return GetOwner() == aOwner
;
761 NS_IMETHODIMP_(const nsACString
&)
762 IDBDatabase::Origin()
768 IDBDatabase::PostHandleEvent(EventChainPostVisitor
& aVisitor
)
770 return IndexedDatabaseManager::FireWindowOnError(GetOwner(), aVisitor
);
773 AsyncConnectionHelper::ChildProcessSendResult
774 NoRequestDatabaseHelper::SendResponseToChildProcess(nsresult aResultCode
)
776 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
777 return Success_NotSent
;
781 NoRequestDatabaseHelper::UnpackResponseFromParentProcess(
782 const ResponseValue
& aResponseValue
)
784 MOZ_CRASH("Should never get here!");
788 NoRequestDatabaseHelper::OnSuccess()
790 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
795 NoRequestDatabaseHelper::OnError()
797 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
798 mTransaction
->Abort(GetResultCode());
802 CreateObjectStoreHelper::DoDatabaseWork(mozIStorageConnection
* aConnection
)
804 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
805 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
807 PROFILER_LABEL("CreateObjectStoreHelper", "DoDatabaseWork",
808 js::ProfileEntry::Category::STORAGE
);
810 if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
811 NS_WARNING("Refusing to create additional objectStore because disk space "
813 return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR
;
816 nsCOMPtr
<mozIStorageStatement
> stmt
=
817 mTransaction
->GetCachedStatement(NS_LITERAL_CSTRING(
818 "INSERT INTO object_store (id, auto_increment, name, key_path) "
819 "VALUES (:id, :auto_increment, :name, :key_path)"
821 IDB_ENSURE_TRUE(stmt
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
823 mozStorageStatementScoper
scoper(stmt
);
825 nsresult rv
= stmt
->BindInt64ByName(NS_LITERAL_CSTRING("id"),
827 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
829 rv
= stmt
->BindInt32ByName(NS_LITERAL_CSTRING("auto_increment"),
830 mObjectStore
->IsAutoIncrement() ? 1 : 0);
831 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
833 rv
= stmt
->BindStringByName(NS_LITERAL_CSTRING("name"), mObjectStore
->Name());
834 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
836 const KeyPath
& keyPath
= mObjectStore
->GetKeyPath();
837 if (keyPath
.IsValid()) {
838 nsAutoString keyPathSerialization
;
839 keyPath
.SerializeToString(keyPathSerialization
);
840 rv
= stmt
->BindStringByName(NS_LITERAL_CSTRING("key_path"),
841 keyPathSerialization
);
842 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
845 rv
= stmt
->BindNullByName(NS_LITERAL_CSTRING("key_path"));
846 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
849 rv
= stmt
->Execute();
850 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
856 CreateObjectStoreHelper::ReleaseMainThreadObjects()
858 mObjectStore
= nullptr;
859 NoRequestDatabaseHelper::ReleaseMainThreadObjects();
863 DeleteObjectStoreHelper::DoDatabaseWork(mozIStorageConnection
* aConnection
)
865 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
866 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
868 PROFILER_LABEL("DeleteObjectStoreHelper", "DoDatabaseWork",
869 js::ProfileEntry::Category::STORAGE
);
871 nsCOMPtr
<mozIStorageStatement
> stmt
=
872 mTransaction
->GetCachedStatement(NS_LITERAL_CSTRING(
873 "DELETE FROM object_store "
876 IDB_ENSURE_TRUE(stmt
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
878 mozStorageStatementScoper
scoper(stmt
);
880 nsresult rv
= stmt
->BindInt64ByName(NS_LITERAL_CSTRING("id"), mObjectStoreId
);
881 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
883 rv
= stmt
->Execute();
884 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
890 CreateFileHelper::DoDatabaseWork(mozIStorageConnection
* aConnection
)
892 AssertIsOnIOThread();
893 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
895 PROFILER_LABEL("CreateFileHelper", "DoDatabaseWork",
896 js::ProfileEntry::Category::STORAGE
);
898 if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
899 NS_WARNING("Refusing to create file because disk space is low!");
900 return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR
;
903 FileManager
* fileManager
= mDatabase
->Manager();
905 mFileInfo
= fileManager
->GetNewFileInfo();
906 IDB_ENSURE_TRUE(mFileInfo
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
908 const int64_t& fileId
= mFileInfo
->Id();
910 nsCOMPtr
<nsIFile
> directory
= fileManager
->EnsureJournalDirectory();
911 NS_ENSURE_TRUE(directory
, NS_ERROR_FAILURE
);
913 nsCOMPtr
<nsIFile
> file
= fileManager
->GetFileForId(directory
, fileId
);
914 NS_ENSURE_TRUE(file
, NS_ERROR_FAILURE
);
916 nsresult rv
= file
->Create(nsIFile::NORMAL_FILE_TYPE
, 0644);
917 NS_ENSURE_SUCCESS(rv
, rv
);
919 directory
= fileManager
->GetDirectory();
920 IDB_ENSURE_TRUE(directory
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
922 file
= fileManager
->GetFileForId(directory
, fileId
);
923 IDB_ENSURE_TRUE(file
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
925 rv
= file
->Create(nsIFile::NORMAL_FILE_TYPE
, 0644);
926 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
932 CreateFileHelper::GetSuccessResult(JSContext
* aCx
,
933 JS::MutableHandle
<JS::Value
> aVal
)
935 nsRefPtr
<IDBMutableFile
> mutableFile
=
936 IDBMutableFile::Create(mName
, mType
, mDatabase
, mFileInfo
.forget());
937 IDB_ENSURE_TRUE(mutableFile
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
939 return WrapNative(aCx
, NS_ISUPPORTS_CAST(EventTarget
*, mutableFile
), aVal
);