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 "IDBFactory.h"
10 #include "nsIPrincipal.h"
11 #include "nsIScriptContext.h"
12 #include "nsIScriptSecurityManager.h"
13 #include "nsIXPConnect.h"
14 #include "nsIXPCScriptable.h"
17 #include "mozilla/dom/nsIContentParent.h"
18 #include "mozilla/dom/ContentChild.h"
19 #include "mozilla/dom/IDBFactoryBinding.h"
20 #include "mozilla/dom/PBrowserChild.h"
21 #include "mozilla/dom/quota/OriginOrPatternString.h"
22 #include "mozilla/dom/quota/QuotaManager.h"
23 #include "mozilla/dom/TabChild.h"
24 #include "mozilla/Preferences.h"
25 #include "mozilla/storage.h"
26 #include "nsComponentManagerUtils.h"
27 #include "nsCharSeparatedTokenizer.h"
28 #include "nsContentUtils.h"
29 #include "nsDOMClassInfoID.h"
30 #include "nsGlobalWindow.h"
31 #include "nsHashKeys.h"
32 #include "nsPIDOMWindow.h"
33 #include "nsServiceManagerUtils.h"
34 #include "nsThreadUtils.h"
35 #include "nsXPCOMCID.h"
37 #include "AsyncConnectionHelper.h"
38 #include "CheckPermissionsHelper.h"
39 #include "DatabaseInfo.h"
40 #include "IDBDatabase.h"
41 #include "IDBEvents.h"
42 #include "IDBKeyRange.h"
43 #include "IndexedDatabaseManager.h"
45 #include "ProfilerHelpers.h"
46 #include "ReportInternalError.h"
47 #include "nsNetUtil.h"
49 #include "ipc/IndexedDBChild.h"
51 #define PREF_INDEXEDDB_ENABLED "dom.indexedDB.enabled"
53 USING_INDEXEDDB_NAMESPACE
56 using mozilla::dom::ContentChild
;
57 using mozilla::dom::nsIContentParent
;
58 using mozilla::dom::IDBOpenDBOptions
;
59 using mozilla::dom::NonNull
;
60 using mozilla::dom::Optional
;
61 using mozilla::dom::TabChild
;
62 using mozilla::ErrorResult
;
63 using mozilla::Preferences
;
67 struct ObjectStoreInfoMap
70 : id(INT64_MIN
), info(nullptr) { }
73 ObjectStoreInfo
* info
;
76 } // anonymous namespace
78 IDBFactory::IDBFactory()
79 : mPrivilege(Content
), mDefaultPersistenceType(PERSISTENCE_TYPE_TEMPORARY
),
80 mOwningObject(nullptr), mActorChild(nullptr), mActorParent(nullptr),
81 mContentParent(nullptr), mRootedOwningObject(false)
86 IDBFactory::~IDBFactory()
88 NS_ASSERTION(!mActorParent
, "Actor parent owns us, how can we be dying?!");
90 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
91 mActorChild
->Send__delete__(mActorChild
);
92 NS_ASSERTION(!mActorChild
, "Should have cleared in Send__delete__!");
94 if (mRootedOwningObject
) {
95 mOwningObject
= nullptr;
96 mozilla::DropJSObjects(this);
102 IDBFactory::Create(nsPIDOMWindow
* aWindow
,
103 const nsACString
& aGroup
,
104 const nsACString
& aASCIIOrigin
,
105 nsIContentParent
* aContentParent
,
106 IDBFactory
** aFactory
)
108 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
109 NS_ASSERTION(aASCIIOrigin
.IsEmpty() || nsContentUtils::IsCallerChrome(),
110 "Non-chrome may not supply their own origin!");
112 IDB_ENSURE_TRUE(aWindow
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
114 if (aWindow
->IsOuterWindow()) {
115 aWindow
= aWindow
->GetCurrentInnerWindow();
116 IDB_ENSURE_TRUE(aWindow
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
119 // Make sure that the manager is up before we do anything here since lots of
120 // decisions depend on which process we're running in.
121 indexedDB::IndexedDatabaseManager
* mgr
=
122 indexedDB::IndexedDatabaseManager::GetOrCreate();
123 IDB_ENSURE_TRUE(mgr
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
127 nsCString
group(aGroup
);
128 nsCString
origin(aASCIIOrigin
);
129 StoragePrivilege privilege
;
130 PersistenceType defaultPersistenceType
;
131 if (origin
.IsEmpty()) {
132 NS_ASSERTION(aGroup
.IsEmpty(), "Should be empty too!");
134 rv
= QuotaManager::GetInfoFromWindow(aWindow
, &group
, &origin
, &privilege
,
135 &defaultPersistenceType
);
138 rv
= QuotaManager::GetInfoFromWindow(aWindow
, nullptr, nullptr, &privilege
,
139 &defaultPersistenceType
);
147 nsRefPtr
<IDBFactory
> factory
= new IDBFactory();
148 factory
->mGroup
= group
;
149 factory
->mASCIIOrigin
= origin
;
150 factory
->mPrivilege
= privilege
;
151 factory
->mDefaultPersistenceType
= defaultPersistenceType
;
152 factory
->mWindow
= aWindow
;
153 factory
->mContentParent
= aContentParent
;
155 if (!IndexedDatabaseManager::IsMainProcess()) {
156 TabChild
* tabChild
= TabChild::GetFrom(aWindow
);
157 IDB_ENSURE_TRUE(tabChild
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
159 IndexedDBChild
* actor
= new IndexedDBChild(tabChild
, origin
);
162 tabChild
->SendPIndexedDBConstructor(actor
, group
, origin
, &allowed
);
165 actor
->Send__delete__(actor
);
170 actor
->SetFactory(factory
);
173 factory
.forget(aFactory
);
179 IDBFactory::Create(JSContext
* aCx
,
180 JS::Handle
<JSObject
*> aOwningObject
,
181 nsIContentParent
* aContentParent
,
182 IDBFactory
** aFactory
)
184 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
185 NS_ASSERTION(aCx
, "Null context!");
186 NS_ASSERTION(aOwningObject
, "Null object!");
187 NS_ASSERTION(JS_GetGlobalForObject(aCx
, aOwningObject
) == aOwningObject
,
188 "Not a global object!");
189 NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
191 // Make sure that the manager is up before we do anything here since lots of
192 // decisions depend on which process we're running in.
193 IndexedDatabaseManager
* mgr
= IndexedDatabaseManager::GetOrCreate();
194 IDB_ENSURE_TRUE(mgr
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
198 StoragePrivilege privilege
;
199 PersistenceType defaultPersistenceType
;
200 QuotaManager::GetInfoForChrome(&group
, &origin
, &privilege
,
201 &defaultPersistenceType
);
203 nsRefPtr
<IDBFactory
> factory
= new IDBFactory();
204 factory
->mGroup
= group
;
205 factory
->mASCIIOrigin
= origin
;
206 factory
->mPrivilege
= privilege
;
207 factory
->mDefaultPersistenceType
= defaultPersistenceType
;
208 factory
->mOwningObject
= aOwningObject
;
209 factory
->mContentParent
= aContentParent
;
211 mozilla::HoldJSObjects(factory
.get());
212 factory
->mRootedOwningObject
= true;
214 if (!IndexedDatabaseManager::IsMainProcess()) {
215 ContentChild
* contentChild
= ContentChild::GetSingleton();
216 IDB_ENSURE_TRUE(contentChild
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
218 IndexedDBChild
* actor
= new IndexedDBChild(contentChild
, origin
);
220 contentChild
->SendPIndexedDBConstructor(actor
);
222 actor
->SetFactory(factory
);
225 factory
.forget(aFactory
);
231 IDBFactory::Create(nsIContentParent
* aContentParent
,
232 IDBFactory
** aFactory
)
234 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
235 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
236 NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
238 // We need to get this information before we push a null principal to avoid
239 // IsCallerChrome() assertion in quota manager.
242 StoragePrivilege privilege
;
243 PersistenceType defaultPersistenceType
;
244 QuotaManager::GetInfoForChrome(&group
, &origin
, &privilege
,
245 &defaultPersistenceType
);
247 nsCOMPtr
<nsIPrincipal
> principal
=
248 do_CreateInstance("@mozilla.org/nullprincipal;1");
249 NS_ENSURE_TRUE(principal
, NS_ERROR_FAILURE
);
251 AutoSafeJSContext cx
;
253 nsIXPConnect
* xpc
= nsContentUtils::XPConnect();
254 NS_ASSERTION(xpc
, "This should never be null!");
256 nsCOMPtr
<nsIXPConnectJSObjectHolder
> globalHolder
;
257 nsresult rv
= xpc
->CreateSandbox(cx
, principal
, getter_AddRefs(globalHolder
));
258 NS_ENSURE_SUCCESS(rv
, rv
);
260 JS::Rooted
<JSObject
*> global(cx
, globalHolder
->GetJSObject());
261 NS_ENSURE_STATE(global
);
263 // The CreateSandbox call returns a proxy to the actual sandbox object. We
264 // don't need a proxy here.
265 global
= js::UncheckedUnwrap(global
);
267 JSAutoCompartment
ac(cx
, global
);
269 nsRefPtr
<IDBFactory
> factory
= new IDBFactory();
270 factory
->mGroup
= group
;
271 factory
->mASCIIOrigin
= origin
;
272 factory
->mPrivilege
= privilege
;
273 factory
->mDefaultPersistenceType
= defaultPersistenceType
;
274 factory
->mOwningObject
= global
;
275 factory
->mContentParent
= aContentParent
;
277 mozilla::HoldJSObjects(factory
.get());
278 factory
->mRootedOwningObject
= true;
280 factory
.forget(aFactory
);
285 already_AddRefed
<nsIFileURL
>
286 IDBFactory::GetDatabaseFileURL(nsIFile
* aDatabaseFile
,
287 PersistenceType aPersistenceType
,
288 const nsACString
& aGroup
,
289 const nsACString
& aOrigin
)
291 nsCOMPtr
<nsIURI
> uri
;
292 nsresult rv
= NS_NewFileURI(getter_AddRefs(uri
), aDatabaseFile
);
293 NS_ENSURE_SUCCESS(rv
, nullptr);
295 nsCOMPtr
<nsIFileURL
> fileUrl
= do_QueryInterface(uri
);
296 NS_ASSERTION(fileUrl
, "This should always succeed!");
299 PersistenceTypeToText(aPersistenceType
, type
);
301 rv
= fileUrl
->SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type
+
302 NS_LITERAL_CSTRING("&group=") + aGroup
+
303 NS_LITERAL_CSTRING("&origin=") + aOrigin
);
304 NS_ENSURE_SUCCESS(rv
, nullptr);
306 return fileUrl
.forget();
310 already_AddRefed
<mozIStorageConnection
>
311 IDBFactory::GetConnection(const nsAString
& aDatabaseFilePath
,
312 PersistenceType aPersistenceType
,
313 const nsACString
& aGroup
,
314 const nsACString
& aOrigin
)
316 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
317 NS_ASSERTION(StringEndsWith(aDatabaseFilePath
, NS_LITERAL_STRING(".sqlite")),
320 nsCOMPtr
<nsIFile
> dbFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID
));
321 NS_ENSURE_TRUE(dbFile
, nullptr);
323 nsresult rv
= dbFile
->InitWithPath(aDatabaseFilePath
);
324 NS_ENSURE_SUCCESS(rv
, nullptr);
327 rv
= dbFile
->Exists(&exists
);
328 NS_ENSURE_SUCCESS(rv
, nullptr);
329 NS_ENSURE_TRUE(exists
, nullptr);
331 nsCOMPtr
<nsIFileURL
> dbFileUrl
=
332 GetDatabaseFileURL(dbFile
, aPersistenceType
, aGroup
, aOrigin
);
333 NS_ENSURE_TRUE(dbFileUrl
, nullptr);
335 nsCOMPtr
<mozIStorageService
> ss
=
336 do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID
);
337 NS_ENSURE_TRUE(ss
, nullptr);
339 nsCOMPtr
<mozIStorageConnection
> connection
;
340 rv
= ss
->OpenDatabaseWithFileURL(dbFileUrl
, getter_AddRefs(connection
));
341 NS_ENSURE_SUCCESS(rv
, nullptr);
343 rv
= SetDefaultPragmas(connection
);
344 NS_ENSURE_SUCCESS(rv
, nullptr);
346 return connection
.forget();
351 IDBFactory::SetDefaultPragmas(mozIStorageConnection
* aConnection
)
353 NS_ASSERTION(aConnection
, "Null connection!");
355 static const char query
[] =
356 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
357 // Switch the journaling mode to TRUNCATE to avoid changing the directory
358 // structure at the conclusion of every transaction for devices with slower
360 "PRAGMA journal_mode = TRUNCATE; "
362 // We use foreign keys in lots of places.
363 "PRAGMA foreign_keys = ON; "
364 // The "INSERT OR REPLACE" statement doesn't fire the update trigger,
365 // instead it fires only the insert trigger. This confuses the update
366 // refcount function. This behavior changes with enabled recursive triggers,
367 // so the statement fires the delete trigger first and then the insert
369 "PRAGMA recursive_triggers = ON;";
371 nsresult rv
= aConnection
->ExecuteSimpleSQL(NS_LITERAL_CSTRING(query
));
372 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
379 IgnoreWhitespace(char16_t c
)
386 IDBFactory::LoadDatabaseInformation(mozIStorageConnection
* aConnection
,
387 const nsACString
& aDatabaseId
,
389 ObjectStoreInfoArray
& aObjectStores
)
391 AssertIsOnIOThread();
392 NS_ASSERTION(aConnection
, "Null pointer!");
394 aObjectStores
.Clear();
396 // Load object store names and ids.
397 nsCOMPtr
<mozIStorageStatement
> stmt
;
398 nsresult rv
= aConnection
->CreateStatement(NS_LITERAL_CSTRING(
399 "SELECT name, id, key_path, auto_increment "
401 ), getter_AddRefs(stmt
));
402 NS_ENSURE_SUCCESS(rv
, rv
);
404 nsAutoTArray
<ObjectStoreInfoMap
, 20> infoMap
;
407 while (NS_SUCCEEDED((rv
= stmt
->ExecuteStep(&hasResult
))) && hasResult
) {
408 nsRefPtr
<ObjectStoreInfo
>* element
=
409 aObjectStores
.AppendElement(new ObjectStoreInfo());
411 ObjectStoreInfo
* info
= element
->get();
413 rv
= stmt
->GetString(0, info
->name
);
414 NS_ENSURE_SUCCESS(rv
, rv
);
416 info
->id
= stmt
->AsInt64(1);
419 nsresult rv
= stmt
->GetTypeOfIndex(2, &columnType
);
420 NS_ENSURE_SUCCESS(rv
, rv
);
422 // NB: We don't have to handle the NULL case, since that is the default
423 // for a new KeyPath.
424 if (columnType
!= mozIStorageStatement::VALUE_TYPE_NULL
) {
425 NS_ASSERTION(columnType
== mozIStorageStatement::VALUE_TYPE_TEXT
,
426 "Should be a string");
427 nsString keyPathSerialization
;
428 rv
= stmt
->GetString(2, keyPathSerialization
);
429 NS_ENSURE_SUCCESS(rv
, rv
);
431 info
->keyPath
= KeyPath::DeserializeFromString(keyPathSerialization
);
434 info
->nextAutoIncrementId
= stmt
->AsInt64(3);
435 info
->comittedAutoIncrementId
= info
->nextAutoIncrementId
;
437 info
->autoIncrement
= !!info
->nextAutoIncrementId
;
439 ObjectStoreInfoMap
* mapEntry
= infoMap
.AppendElement();
440 NS_ENSURE_TRUE(mapEntry
, NS_ERROR_OUT_OF_MEMORY
);
442 mapEntry
->id
= info
->id
;
443 mapEntry
->info
= info
;
445 NS_ENSURE_SUCCESS(rv
, rv
);
447 // Load index information
448 rv
= aConnection
->CreateStatement(NS_LITERAL_CSTRING(
449 "SELECT object_store_id, id, name, key_path, unique_index, multientry "
450 "FROM object_store_index"
451 ), getter_AddRefs(stmt
));
452 NS_ENSURE_SUCCESS(rv
, rv
);
454 while (NS_SUCCEEDED((rv
= stmt
->ExecuteStep(&hasResult
))) && hasResult
) {
455 int64_t objectStoreId
= stmt
->AsInt64(0);
457 ObjectStoreInfo
* objectStoreInfo
= nullptr;
458 for (uint32_t index
= 0; index
< infoMap
.Length(); index
++) {
459 if (infoMap
[index
].id
== objectStoreId
) {
460 objectStoreInfo
= infoMap
[index
].info
;
465 if (!objectStoreInfo
) {
466 NS_ERROR("Index for nonexistant object store!");
467 return NS_ERROR_UNEXPECTED
;
470 IndexInfo
* indexInfo
= objectStoreInfo
->indexes
.AppendElement();
471 NS_ENSURE_TRUE(indexInfo
, NS_ERROR_OUT_OF_MEMORY
);
473 indexInfo
->id
= stmt
->AsInt64(1);
475 rv
= stmt
->GetString(2, indexInfo
->name
);
476 NS_ENSURE_SUCCESS(rv
, rv
);
478 nsString keyPathSerialization
;
479 rv
= stmt
->GetString(3, keyPathSerialization
);
480 NS_ENSURE_SUCCESS(rv
, rv
);
482 // XXX bent wants to assert here
483 indexInfo
->keyPath
= KeyPath::DeserializeFromString(keyPathSerialization
);
484 indexInfo
->unique
= !!stmt
->AsInt32(4);
485 indexInfo
->multiEntry
= !!stmt
->AsInt32(5);
487 NS_ENSURE_SUCCESS(rv
, rv
);
489 // Load version information.
490 rv
= aConnection
->CreateStatement(NS_LITERAL_CSTRING(
493 ), getter_AddRefs(stmt
));
494 NS_ENSURE_SUCCESS(rv
, rv
);
496 rv
= stmt
->ExecuteStep(&hasResult
);
497 NS_ENSURE_SUCCESS(rv
, rv
);
500 NS_ERROR("Database has no version!");
501 return NS_ERROR_UNEXPECTED
;
505 rv
= stmt
->GetInt64(0, &version
);
507 *aVersion
= std::max
<int64_t>(version
, 0);
514 IDBFactory::SetDatabaseMetadata(DatabaseInfo
* aDatabaseInfo
,
516 ObjectStoreInfoArray
& aObjectStores
)
518 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
519 NS_ASSERTION(aDatabaseInfo
, "Null pointer!");
521 ObjectStoreInfoArray objectStores
;
522 objectStores
.SwapElements(aObjectStores
);
526 nsTArray
<nsString
> existingNames
;
527 aDatabaseInfo
->GetObjectStoreNames(existingNames
);
528 NS_ASSERTION(existingNames
.IsEmpty(), "Should be an empty DatabaseInfo");
532 aDatabaseInfo
->version
= aVersion
;
534 for (uint32_t index
= 0; index
< objectStores
.Length(); index
++) {
535 nsRefPtr
<ObjectStoreInfo
>& info
= objectStores
[index
];
537 if (!aDatabaseInfo
->PutObjectStore(info
)) {
538 NS_WARNING("Out of memory!");
539 return NS_ERROR_OUT_OF_MEMORY
;
546 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBFactory
)
547 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBFactory
)
549 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBFactory
)
550 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
551 NS_INTERFACE_MAP_ENTRY(nsISupports
)
554 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFactory
)
556 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBFactory
)
557 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
558 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow
)
559 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
561 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBFactory
)
562 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
563 if (tmp
->mOwningObject
) {
564 tmp
->mOwningObject
= nullptr;
566 if (tmp
->mRootedOwningObject
) {
567 mozilla::DropJSObjects(tmp
);
568 tmp
->mRootedOwningObject
= false;
570 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow
)
571 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
573 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBFactory
)
574 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
575 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOwningObject
)
576 NS_IMPL_CYCLE_COLLECTION_TRACE_END
579 IDBFactory::OpenInternal(const nsAString
& aName
,
581 PersistenceType aPersistenceType
,
582 const nsACString
& aGroup
,
583 const nsACString
& aASCIIOrigin
,
584 StoragePrivilege aPrivilege
,
586 IDBOpenDBRequest
** _retval
)
588 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
589 NS_ASSERTION(mWindow
|| mOwningObject
, "Must have one of these!");
592 nsCOMPtr
<nsPIDOMWindow
> window
;
593 JS::Rooted
<JSObject
*> scriptOwner(cx
);
598 static_cast<nsGlobalWindow
*>(window
.get())->FastGetGlobalJSObject();
601 scriptOwner
= mOwningObject
;
604 if (aPrivilege
== Chrome
) {
605 // Chrome privilege, ignore the persistence type parameter.
606 aPersistenceType
= PERSISTENCE_TYPE_PERSISTENT
;
609 nsRefPtr
<IDBOpenDBRequest
> request
=
610 IDBOpenDBRequest::Create(this, window
, scriptOwner
);
611 IDB_ENSURE_TRUE(request
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
615 if (IndexedDatabaseManager::IsMainProcess()) {
616 nsRefPtr
<OpenDatabaseHelper
> openHelper
=
617 new OpenDatabaseHelper(request
, aName
, aGroup
, aASCIIOrigin
, aVersion
,
618 aPersistenceType
, aDeleting
, mContentParent
,
621 rv
= openHelper
->Init();
622 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
624 if (!Preferences::GetBool(PREF_INDEXEDDB_ENABLED
)) {
625 openHelper
->SetError(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR
);
626 rv
= openHelper
->WaitForOpenAllowed();
629 if (mPrivilege
!= Chrome
&&
630 aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
) {
631 nsRefPtr
<CheckPermissionsHelper
> permissionHelper
=
632 new CheckPermissionsHelper(openHelper
, window
);
634 QuotaManager
* quotaManager
= QuotaManager::Get();
635 NS_ASSERTION(quotaManager
, "This should never be null!");
638 WaitForOpenAllowed(OriginOrPatternString::FromOrigin(aASCIIOrigin
),
639 Nullable
<PersistenceType
>(aPersistenceType
),
640 openHelper
->Id(), permissionHelper
);
643 // Chrome and temporary storage doesn't need to check the permission.
644 rv
= openHelper
->WaitForOpenAllowed();
647 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
649 else if (aDeleting
) {
650 nsCString databaseId
;
651 QuotaManager::GetStorageId(aPersistenceType
, aASCIIOrigin
, Client::IDB
,
653 MOZ_ASSERT(!databaseId
.IsEmpty());
655 IndexedDBDeleteDatabaseRequestChild
* actor
=
656 new IndexedDBDeleteDatabaseRequestChild(this, request
, databaseId
);
658 mActorChild
->SendPIndexedDBDeleteDatabaseRequestConstructor(
664 IndexedDBDatabaseChild
* dbActor
=
665 static_cast<IndexedDBDatabaseChild
*>(
666 mActorChild
->SendPIndexedDBDatabaseConstructor(nsString(aName
),
670 dbActor
->SetRequest(request
);
673 #ifdef IDB_PROFILER_USE_MARKS
675 NS_ConvertUTF16toUTF8
profilerName(aName
);
677 IDB_PROFILER_MARK("IndexedDB Request %llu: deleteDatabase(\"%s\")",
678 "MT IDBFactory.deleteDatabase()",
679 request
->GetSerialNumber(), profilerName
.get());
682 IDB_PROFILER_MARK("IndexedDB Request %llu: open(\"%s\", %lld)",
683 "MT IDBFactory.open()",
684 request
->GetSerialNumber(), profilerName
.get(),
690 request
.forget(_retval
);
695 IDBFactory::WrapObject(JSContext
* aCx
)
697 return IDBFactoryBinding::Wrap(aCx
, this);
700 already_AddRefed
<IDBOpenDBRequest
>
701 IDBFactory::Open(const nsAString
& aName
, const IDBOpenDBOptions
& aOptions
,
704 return Open(nullptr, aName
, aOptions
.mVersion
, aOptions
.mStorage
, false, aRv
);
707 already_AddRefed
<IDBOpenDBRequest
>
708 IDBFactory::DeleteDatabase(const nsAString
& aName
,
709 const IDBOpenDBOptions
& aOptions
,
712 return Open(nullptr, aName
, Optional
<uint64_t>(), aOptions
.mStorage
, true,
717 IDBFactory::Cmp(JSContext
* aCx
, JS::Handle
<JS::Value
> aFirst
,
718 JS::Handle
<JS::Value
> aSecond
, ErrorResult
& aRv
)
721 nsresult rv
= first
.SetFromJSVal(aCx
, aFirst
);
727 rv
= second
.SetFromJSVal(aCx
, aSecond
);
733 if (first
.IsUnset() || second
.IsUnset()) {
734 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR
);
738 return Key::CompareKeys(first
, second
);
741 already_AddRefed
<IDBOpenDBRequest
>
742 IDBFactory::OpenForPrincipal(nsIPrincipal
* aPrincipal
, const nsAString
& aName
,
743 uint64_t aVersion
, ErrorResult
& aRv
)
745 // Just to be on the extra-safe side
746 if (!nsContentUtils::IsCallerChrome()) {
750 return Open(aPrincipal
, aName
, Optional
<uint64_t>(aVersion
),
751 Optional
<mozilla::dom::StorageType
>(), false, aRv
);
754 already_AddRefed
<IDBOpenDBRequest
>
755 IDBFactory::OpenForPrincipal(nsIPrincipal
* aPrincipal
, const nsAString
& aName
,
756 const IDBOpenDBOptions
& aOptions
, ErrorResult
& aRv
)
758 // Just to be on the extra-safe side
759 if (!nsContentUtils::IsCallerChrome()) {
763 return Open(aPrincipal
, aName
, aOptions
.mVersion
, aOptions
.mStorage
, false,
767 already_AddRefed
<IDBOpenDBRequest
>
768 IDBFactory::DeleteForPrincipal(nsIPrincipal
* aPrincipal
, const nsAString
& aName
,
769 const IDBOpenDBOptions
& aOptions
,
772 // Just to be on the extra-safe side
773 if (!nsContentUtils::IsCallerChrome()) {
777 return Open(aPrincipal
, aName
, Optional
<uint64_t>(), aOptions
.mStorage
, true,
781 already_AddRefed
<IDBOpenDBRequest
>
782 IDBFactory::Open(nsIPrincipal
* aPrincipal
, const nsAString
& aName
,
783 const Optional
<uint64_t>& aVersion
,
784 const Optional
<mozilla::dom::StorageType
>& aStorageType
,
785 bool aDelete
, ErrorResult
& aRv
)
791 StoragePrivilege privilege
;
792 PersistenceType defaultPersistenceType
;
794 rv
= QuotaManager::GetInfoFromPrincipal(aPrincipal
, &group
, &origin
,
796 &defaultPersistenceType
);
798 IDB_REPORT_INTERNAL_ERR();
799 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
805 origin
= mASCIIOrigin
;
806 privilege
= mPrivilege
;
807 defaultPersistenceType
= mDefaultPersistenceType
;
810 uint64_t version
= 0;
811 if (!aDelete
&& aVersion
.WasPassed()) {
812 if (aVersion
.Value() < 1) {
813 aRv
.ThrowTypeError(MSG_INVALID_VERSION
);
816 version
= aVersion
.Value();
819 PersistenceType persistenceType
=
820 PersistenceTypeFromStorage(aStorageType
, defaultPersistenceType
);
822 nsRefPtr
<IDBOpenDBRequest
> request
;
823 rv
= OpenInternal(aName
, version
, persistenceType
, group
, origin
, privilege
,
824 aDelete
, getter_AddRefs(request
));
830 return request
.forget();