IDBFactory.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "IDBFactory.h"
  6. #include "BackgroundChildImpl.h"
  7. #include "IDBRequest.h"
  8. #include "IndexedDatabaseManager.h"
  9. #include "mozilla/ErrorResult.h"
  10. #include "mozilla/Preferences.h"
  11. #include "mozilla/dom/BindingDeclarations.h"
  12. #include "mozilla/dom/IDBFactoryBinding.h"
  13. #include "mozilla/dom/TabChild.h"
  14. #include "mozilla/ipc/BackgroundChild.h"
  15. #include "mozilla/ipc/BackgroundUtils.h"
  16. #include "mozilla/ipc/PBackground.h"
  17. #include "mozilla/ipc/PBackgroundChild.h"
  18. #include "mozIThirdPartyUtil.h"
  19. #include "nsAboutProtocolUtils.h"
  20. #include "nsContentUtils.h"
  21. #include "nsGlobalWindow.h"
  22. #include "nsIAboutModule.h"
  23. #include "nsIIPCBackgroundChildCreateCallback.h"
  24. #include "nsILoadContext.h"
  25. #include "nsIPrincipal.h"
  26. #include "nsIURI.h"
  27. #include "nsIUUIDGenerator.h"
  28. #include "nsIWebNavigation.h"
  29. #include "nsSandboxFlags.h"
  30. #include "nsServiceManagerUtils.h"
  31. #include "ProfilerHelpers.h"
  32. #include "ReportInternalError.h"
  33. // Include this last to avoid path problems on Windows.
  34. #include "ActorsChild.h"
  35. #ifdef DEBUG
  36. #include "nsContentUtils.h" // For assertions.
  37. #endif
  38. using namespace mozilla::dom::indexedDB;
  39. namespace mozilla {
  40. namespace dom {
  41. using namespace mozilla::dom::quota;
  42. using namespace mozilla::ipc;
  43. class IDBFactory::BackgroundCreateCallback final
  44. : public nsIIPCBackgroundChildCreateCallback
  45. {
  46. RefPtr<IDBFactory> mFactory;
  47. LoggingInfo mLoggingInfo;
  48. public:
  49. explicit
  50. BackgroundCreateCallback(IDBFactory* aFactory,
  51. const LoggingInfo& aLoggingInfo)
  52. : mFactory(aFactory)
  53. , mLoggingInfo(aLoggingInfo)
  54. {
  55. MOZ_ASSERT(aFactory);
  56. }
  57. NS_DECL_ISUPPORTS
  58. private:
  59. ~BackgroundCreateCallback()
  60. { }
  61. NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
  62. };
  63. struct IDBFactory::PendingRequestInfo
  64. {
  65. RefPtr<IDBOpenDBRequest> mRequest;
  66. FactoryRequestParams mParams;
  67. PendingRequestInfo(IDBOpenDBRequest* aRequest,
  68. const FactoryRequestParams& aParams)
  69. : mRequest(aRequest), mParams(aParams)
  70. {
  71. MOZ_ASSERT(aRequest);
  72. MOZ_ASSERT(aParams.type() != FactoryRequestParams::T__None);
  73. }
  74. };
  75. IDBFactory::IDBFactory()
  76. : mOwningObject(nullptr)
  77. , mBackgroundActor(nullptr)
  78. , mInnerWindowID(0)
  79. , mBackgroundActorFailed(false)
  80. , mPrivateBrowsingMode(false)
  81. {
  82. #ifdef DEBUG
  83. mOwningThread = PR_GetCurrentThread();
  84. #endif
  85. AssertIsOnOwningThread();
  86. }
  87. IDBFactory::~IDBFactory()
  88. {
  89. MOZ_ASSERT_IF(mBackgroundActorFailed, !mBackgroundActor);
  90. mOwningObject = nullptr;
  91. mozilla::DropJSObjects(this);
  92. if (mBackgroundActor) {
  93. mBackgroundActor->SendDeleteMeInternal();
  94. MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
  95. }
  96. }
  97. // static
  98. nsresult
  99. IDBFactory::CreateForWindow(nsPIDOMWindowInner* aWindow,
  100. IDBFactory** aFactory)
  101. {
  102. MOZ_ASSERT(NS_IsMainThread());
  103. MOZ_ASSERT(aWindow);
  104. MOZ_ASSERT(aFactory);
  105. nsCOMPtr<nsIPrincipal> principal;
  106. nsresult rv = AllowedForWindowInternal(aWindow, getter_AddRefs(principal));
  107. if (rv == NS_ERROR_DOM_NOT_SUPPORTED_ERR) {
  108. NS_WARNING("IndexedDB is not permitted in a third-party window.");
  109. *aFactory = nullptr;
  110. return NS_OK;
  111. }
  112. if (NS_WARN_IF(NS_FAILED(rv))) {
  113. if (rv == NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR) {
  114. IDB_REPORT_INTERNAL_ERR();
  115. }
  116. return rv;
  117. }
  118. MOZ_ASSERT(principal);
  119. nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo());
  120. rv = PrincipalToPrincipalInfo(principal, principalInfo);
  121. if (NS_WARN_IF(NS_FAILED(rv))) {
  122. IDB_REPORT_INTERNAL_ERR();
  123. return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  124. }
  125. MOZ_ASSERT(principalInfo->type() == PrincipalInfo::TContentPrincipalInfo ||
  126. principalInfo->type() == PrincipalInfo::TSystemPrincipalInfo);
  127. nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
  128. nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
  129. RefPtr<IDBFactory> factory = new IDBFactory();
  130. factory->mPrincipalInfo = Move(principalInfo);
  131. factory->mWindow = aWindow;
  132. factory->mTabChild = TabChild::GetFrom(aWindow);
  133. factory->mInnerWindowID = aWindow->WindowID();
  134. factory->mPrivateBrowsingMode =
  135. loadContext && loadContext->UsePrivateBrowsing();
  136. factory.forget(aFactory);
  137. return NS_OK;
  138. }
  139. // static
  140. nsresult
  141. IDBFactory::CreateForMainThreadJS(JSContext* aCx,
  142. JS::Handle<JSObject*> aOwningObject,
  143. IDBFactory** aFactory)
  144. {
  145. MOZ_ASSERT(NS_IsMainThread());
  146. nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo());
  147. nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aOwningObject);
  148. MOZ_ASSERT(principal);
  149. bool isSystem;
  150. if (!AllowedForPrincipal(principal, &isSystem)) {
  151. return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  152. }
  153. nsresult rv = PrincipalToPrincipalInfo(principal, principalInfo);
  154. if (NS_WARN_IF(NS_FAILED(rv))) {
  155. return rv;
  156. }
  157. rv = CreateForMainThreadJSInternal(aCx, aOwningObject, principalInfo, aFactory);
  158. if (NS_WARN_IF(NS_FAILED(rv))) {
  159. return rv;
  160. }
  161. MOZ_ASSERT(!principalInfo);
  162. return NS_OK;
  163. }
  164. // static
  165. nsresult
  166. IDBFactory::CreateForWorker(JSContext* aCx,
  167. JS::Handle<JSObject*> aOwningObject,
  168. const PrincipalInfo& aPrincipalInfo,
  169. uint64_t aInnerWindowID,
  170. IDBFactory** aFactory)
  171. {
  172. MOZ_ASSERT(!NS_IsMainThread());
  173. MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::T__None);
  174. nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo(aPrincipalInfo));
  175. nsresult rv =
  176. CreateForJSInternal(aCx,
  177. aOwningObject,
  178. principalInfo,
  179. aInnerWindowID,
  180. aFactory);
  181. if (NS_WARN_IF(NS_FAILED(rv))) {
  182. return rv;
  183. }
  184. MOZ_ASSERT(!principalInfo);
  185. return NS_OK;
  186. }
  187. // static
  188. nsresult
  189. IDBFactory::CreateForMainThreadJSInternal(
  190. JSContext* aCx,
  191. JS::Handle<JSObject*> aOwningObject,
  192. nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
  193. IDBFactory** aFactory)
  194. {
  195. MOZ_ASSERT(NS_IsMainThread());
  196. MOZ_ASSERT(aPrincipalInfo);
  197. IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate();
  198. if (NS_WARN_IF(!mgr)) {
  199. IDB_REPORT_INTERNAL_ERR();
  200. return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  201. }
  202. nsresult rv =
  203. CreateForJSInternal(aCx,
  204. aOwningObject,
  205. aPrincipalInfo,
  206. /* aInnerWindowID */ 0,
  207. aFactory);
  208. if (NS_WARN_IF(NS_FAILED(rv))) {
  209. return rv;
  210. }
  211. return NS_OK;
  212. }
  213. // static
  214. nsresult
  215. IDBFactory::CreateForJSInternal(JSContext* aCx,
  216. JS::Handle<JSObject*> aOwningObject,
  217. nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
  218. uint64_t aInnerWindowID,
  219. IDBFactory** aFactory)
  220. {
  221. MOZ_ASSERT(aCx);
  222. MOZ_ASSERT(aOwningObject);
  223. MOZ_ASSERT(aPrincipalInfo);
  224. MOZ_ASSERT(aPrincipalInfo->type() != PrincipalInfo::T__None);
  225. MOZ_ASSERT(aFactory);
  226. MOZ_ASSERT(JS_GetGlobalForObject(aCx, aOwningObject) == aOwningObject,
  227. "Not a global object!");
  228. if (aPrincipalInfo->type() != PrincipalInfo::TContentPrincipalInfo &&
  229. aPrincipalInfo->type() != PrincipalInfo::TSystemPrincipalInfo) {
  230. NS_WARNING("IndexedDB not allowed for this principal!");
  231. aPrincipalInfo = nullptr;
  232. *aFactory = nullptr;
  233. return NS_OK;
  234. }
  235. RefPtr<IDBFactory> factory = new IDBFactory();
  236. factory->mPrincipalInfo = aPrincipalInfo.forget();
  237. factory->mOwningObject = aOwningObject;
  238. mozilla::HoldJSObjects(factory.get());
  239. factory->mInnerWindowID = aInnerWindowID;
  240. factory.forget(aFactory);
  241. return NS_OK;
  242. }
  243. // static
  244. bool
  245. IDBFactory::AllowedForWindow(nsPIDOMWindowInner* aWindow)
  246. {
  247. MOZ_ASSERT(NS_IsMainThread());
  248. MOZ_ASSERT(aWindow);
  249. nsCOMPtr<nsIPrincipal> principal;
  250. nsresult rv = AllowedForWindowInternal(aWindow, getter_AddRefs(principal));
  251. if (NS_WARN_IF(NS_FAILED(rv))) {
  252. return false;
  253. }
  254. return true;
  255. }
  256. // static
  257. nsresult
  258. IDBFactory::AllowedForWindowInternal(nsPIDOMWindowInner* aWindow,
  259. nsIPrincipal** aPrincipal)
  260. {
  261. MOZ_ASSERT(NS_IsMainThread());
  262. MOZ_ASSERT(aWindow);
  263. if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) {
  264. return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  265. }
  266. nsContentUtils::StorageAccess access =
  267. nsContentUtils::StorageAllowedForWindow(aWindow);
  268. // the factory callsite records whether the browser is in private browsing.
  269. // and thus we don't have to respect that setting here. IndexedDB has no
  270. // concept of session-local storage, and thus ignores it.
  271. if (access == nsContentUtils::StorageAccess::eDeny) {
  272. return NS_ERROR_DOM_SECURITY_ERR;
  273. }
  274. nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
  275. MOZ_ASSERT(sop);
  276. nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
  277. if (NS_WARN_IF(!principal)) {
  278. return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  279. }
  280. if (nsContentUtils::IsSystemPrincipal(principal)) {
  281. principal.forget(aPrincipal);
  282. return NS_OK;
  283. }
  284. // About URIs shouldn't be able to access IndexedDB unless they have the
  285. // nsIAboutModule::ENABLE_INDEXED_DB flag set on them.
  286. nsCOMPtr<nsIURI> uri;
  287. MOZ_ALWAYS_SUCCEEDS(principal->GetURI(getter_AddRefs(uri)));
  288. MOZ_ASSERT(uri);
  289. bool isAbout = false;
  290. MOZ_ALWAYS_SUCCEEDS(uri->SchemeIs("about", &isAbout));
  291. if (isAbout) {
  292. nsCOMPtr<nsIAboutModule> module;
  293. if (NS_SUCCEEDED(NS_GetAboutModule(uri, getter_AddRefs(module)))) {
  294. uint32_t flags;
  295. if (NS_SUCCEEDED(module->GetURIFlags(uri, &flags))) {
  296. if (!(flags & nsIAboutModule::ENABLE_INDEXED_DB)) {
  297. return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
  298. }
  299. } else {
  300. return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
  301. }
  302. } else {
  303. return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
  304. }
  305. }
  306. principal.forget(aPrincipal);
  307. return NS_OK;
  308. }
  309. // static
  310. bool
  311. IDBFactory::AllowedForPrincipal(nsIPrincipal* aPrincipal,
  312. bool* aIsSystemPrincipal)
  313. {
  314. MOZ_ASSERT(NS_IsMainThread());
  315. MOZ_ASSERT(aPrincipal);
  316. if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) {
  317. return false;
  318. }
  319. if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
  320. if (aIsSystemPrincipal) {
  321. *aIsSystemPrincipal = true;
  322. }
  323. return true;
  324. } else if (aIsSystemPrincipal) {
  325. *aIsSystemPrincipal = false;
  326. }
  327. if (aPrincipal->GetIsNullPrincipal()) {
  328. return false;
  329. }
  330. return true;
  331. }
  332. #ifdef DEBUG
  333. void
  334. IDBFactory::AssertIsOnOwningThread() const
  335. {
  336. MOZ_ASSERT(mOwningThread);
  337. MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
  338. }
  339. PRThread*
  340. IDBFactory::OwningThread() const
  341. {
  342. MOZ_ASSERT(mOwningThread);
  343. return mOwningThread;
  344. }
  345. #endif // DEBUG
  346. bool
  347. IDBFactory::IsChrome() const
  348. {
  349. AssertIsOnOwningThread();
  350. MOZ_ASSERT(mPrincipalInfo);
  351. return mPrincipalInfo->type() == PrincipalInfo::TSystemPrincipalInfo;
  352. }
  353. void
  354. IDBFactory::IncrementParentLoggingRequestSerialNumber()
  355. {
  356. AssertIsOnOwningThread();
  357. MOZ_ASSERT(mBackgroundActor);
  358. mBackgroundActor->SendIncrementLoggingRequestSerialNumber();
  359. }
  360. already_AddRefed<IDBOpenDBRequest>
  361. IDBFactory::Open(JSContext* aCx,
  362. const nsAString& aName,
  363. uint64_t aVersion,
  364. ErrorResult& aRv)
  365. {
  366. return OpenInternal(aCx,
  367. /* aPrincipal */ nullptr,
  368. aName,
  369. Optional<uint64_t>(aVersion),
  370. Optional<StorageType>(),
  371. /* aDeleting */ false,
  372. aRv);
  373. }
  374. already_AddRefed<IDBOpenDBRequest>
  375. IDBFactory::Open(JSContext* aCx,
  376. const nsAString& aName,
  377. const IDBOpenDBOptions& aOptions,
  378. ErrorResult& aRv)
  379. {
  380. return OpenInternal(aCx,
  381. /* aPrincipal */ nullptr,
  382. aName,
  383. aOptions.mVersion,
  384. aOptions.mStorage,
  385. /* aDeleting */ false,
  386. aRv);
  387. }
  388. already_AddRefed<IDBOpenDBRequest>
  389. IDBFactory::DeleteDatabase(JSContext* aCx,
  390. const nsAString& aName,
  391. const IDBOpenDBOptions& aOptions,
  392. ErrorResult& aRv)
  393. {
  394. return OpenInternal(aCx,
  395. /* aPrincipal */ nullptr,
  396. aName,
  397. Optional<uint64_t>(),
  398. aOptions.mStorage,
  399. /* aDeleting */ true,
  400. aRv);
  401. }
  402. int16_t
  403. IDBFactory::Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
  404. JS::Handle<JS::Value> aSecond, ErrorResult& aRv)
  405. {
  406. Key first, second;
  407. nsresult rv = first.SetFromJSVal(aCx, aFirst, /* aCallGetters */ true);
  408. if (NS_FAILED(rv)) {
  409. aRv.Throw(rv);
  410. return 0;
  411. }
  412. rv = second.SetFromJSVal(aCx, aSecond, /* aCallGetters */ true);
  413. if (NS_FAILED(rv)) {
  414. aRv.Throw(rv);
  415. return 0;
  416. }
  417. if (first.IsUnset() || second.IsUnset()) {
  418. aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
  419. return 0;
  420. }
  421. return Key::CompareKeys(first, second);
  422. }
  423. already_AddRefed<IDBOpenDBRequest>
  424. IDBFactory::OpenForPrincipal(JSContext* aCx,
  425. nsIPrincipal* aPrincipal,
  426. const nsAString& aName,
  427. uint64_t aVersion,
  428. ErrorResult& aRv)
  429. {
  430. MOZ_ASSERT(aPrincipal);
  431. if (!NS_IsMainThread()) {
  432. MOZ_CRASH("Figure out security checks for workers!");
  433. }
  434. MOZ_ASSERT(nsContentUtils::IsCallerChrome());
  435. return OpenInternal(aCx,
  436. aPrincipal,
  437. aName,
  438. Optional<uint64_t>(aVersion),
  439. Optional<StorageType>(),
  440. /* aDeleting */ false,
  441. aRv);
  442. }
  443. already_AddRefed<IDBOpenDBRequest>
  444. IDBFactory::OpenForPrincipal(JSContext* aCx,
  445. nsIPrincipal* aPrincipal,
  446. const nsAString& aName,
  447. const IDBOpenDBOptions& aOptions,
  448. ErrorResult& aRv)
  449. {
  450. MOZ_ASSERT(aPrincipal);
  451. if (!NS_IsMainThread()) {
  452. MOZ_CRASH("Figure out security checks for workers!");
  453. }
  454. MOZ_ASSERT(nsContentUtils::IsCallerChrome());
  455. return OpenInternal(aCx,
  456. aPrincipal,
  457. aName,
  458. aOptions.mVersion,
  459. aOptions.mStorage,
  460. /* aDeleting */ false,
  461. aRv);
  462. }
  463. already_AddRefed<IDBOpenDBRequest>
  464. IDBFactory::DeleteForPrincipal(JSContext* aCx,
  465. nsIPrincipal* aPrincipal,
  466. const nsAString& aName,
  467. const IDBOpenDBOptions& aOptions,
  468. ErrorResult& aRv)
  469. {
  470. MOZ_ASSERT(aPrincipal);
  471. if (!NS_IsMainThread()) {
  472. MOZ_CRASH("Figure out security checks for workers!");
  473. }
  474. MOZ_ASSERT(nsContentUtils::IsCallerChrome());
  475. return OpenInternal(aCx,
  476. aPrincipal,
  477. aName,
  478. Optional<uint64_t>(),
  479. aOptions.mStorage,
  480. /* aDeleting */ true,
  481. aRv);
  482. }
  483. already_AddRefed<IDBOpenDBRequest>
  484. IDBFactory::OpenInternal(JSContext* aCx,
  485. nsIPrincipal* aPrincipal,
  486. const nsAString& aName,
  487. const Optional<uint64_t>& aVersion,
  488. const Optional<StorageType>& aStorageType,
  489. bool aDeleting,
  490. ErrorResult& aRv)
  491. {
  492. MOZ_ASSERT(mWindow || mOwningObject);
  493. MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode);
  494. CommonFactoryRequestParams commonParams;
  495. PrincipalInfo& principalInfo = commonParams.principalInfo();
  496. if (aPrincipal) {
  497. if (!NS_IsMainThread()) {
  498. MOZ_CRASH("Figure out security checks for workers!");
  499. }
  500. MOZ_ASSERT(nsContentUtils::IsCallerChrome());
  501. if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(aPrincipal,
  502. &principalInfo)))) {
  503. IDB_REPORT_INTERNAL_ERR();
  504. aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  505. return nullptr;
  506. }
  507. if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
  508. principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
  509. IDB_REPORT_INTERNAL_ERR();
  510. aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  511. return nullptr;
  512. }
  513. } else {
  514. principalInfo = *mPrincipalInfo;
  515. }
  516. uint64_t version = 0;
  517. if (!aDeleting && aVersion.WasPassed()) {
  518. if (aVersion.Value() < 1) {
  519. aRv.ThrowTypeError<MSG_INVALID_VERSION>();
  520. return nullptr;
  521. }
  522. version = aVersion.Value();
  523. }
  524. // Nothing can be done here if we have previously failed to create a
  525. // background actor.
  526. if (mBackgroundActorFailed) {
  527. IDB_REPORT_INTERNAL_ERR();
  528. aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  529. return nullptr;
  530. }
  531. PersistenceType persistenceType;
  532. if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
  533. // Chrome privilege always gets persistent storage.
  534. persistenceType = PERSISTENCE_TYPE_PERSISTENT;
  535. } else {
  536. persistenceType = PersistenceTypeFromStorage(aStorageType);
  537. }
  538. DatabaseMetadata& metadata = commonParams.metadata();
  539. metadata.name() = aName;
  540. metadata.persistenceType() = persistenceType;
  541. FactoryRequestParams params;
  542. if (aDeleting) {
  543. metadata.version() = 0;
  544. params = DeleteDatabaseRequestParams(commonParams);
  545. } else {
  546. metadata.version() = version;
  547. params = OpenDatabaseRequestParams(commonParams);
  548. }
  549. if (!mBackgroundActor && mPendingRequests.IsEmpty()) {
  550. BackgroundChildImpl::ThreadLocal* threadLocal =
  551. BackgroundChildImpl::GetThreadLocalForCurrentThread();
  552. nsAutoPtr<ThreadLocal> newIDBThreadLocal;
  553. ThreadLocal* idbThreadLocal;
  554. if (threadLocal && threadLocal->mIndexedDBThreadLocal) {
  555. idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
  556. } else {
  557. nsCOMPtr<nsIUUIDGenerator> uuidGen =
  558. do_GetService("@mozilla.org/uuid-generator;1");
  559. MOZ_ASSERT(uuidGen);
  560. nsID id;
  561. MOZ_ALWAYS_SUCCEEDS(uuidGen->GenerateUUIDInPlace(&id));
  562. newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id);
  563. }
  564. if (PBackgroundChild* actor = BackgroundChild::GetForCurrentThread()) {
  565. BackgroundActorCreated(actor, idbThreadLocal->GetLoggingInfo());
  566. } else {
  567. // We need to start the sequence to create a background actor for this
  568. // thread.
  569. RefPtr<BackgroundCreateCallback> cb =
  570. new BackgroundCreateCallback(this, idbThreadLocal->GetLoggingInfo());
  571. if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) {
  572. IDB_REPORT_INTERNAL_ERR();
  573. aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  574. return nullptr;
  575. }
  576. }
  577. if (newIDBThreadLocal) {
  578. if (!threadLocal) {
  579. threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread();
  580. }
  581. MOZ_ASSERT(threadLocal);
  582. MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal);
  583. threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget();
  584. }
  585. }
  586. RefPtr<IDBOpenDBRequest> request;
  587. if (mWindow) {
  588. JS::Rooted<JSObject*> scriptOwner(aCx,
  589. nsGlobalWindow::Cast(mWindow.get())->FastGetGlobalJSObject());
  590. MOZ_ASSERT(scriptOwner);
  591. request = IDBOpenDBRequest::CreateForWindow(aCx, this, mWindow, scriptOwner);
  592. } else {
  593. JS::Rooted<JSObject*> scriptOwner(aCx, mOwningObject);
  594. request = IDBOpenDBRequest::CreateForJS(aCx, this, scriptOwner);
  595. if (!request) {
  596. MOZ_ASSERT(!NS_IsMainThread());
  597. aRv.ThrowUncatchableException();
  598. return nullptr;
  599. }
  600. }
  601. MOZ_ASSERT(request);
  602. if (aDeleting) {
  603. IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: "
  604. "indexedDB.deleteDatabase(\"%s\")",
  605. "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()",
  606. IDB_LOG_ID_STRING(),
  607. request->LoggingSerialNumber(),
  608. NS_ConvertUTF16toUTF8(aName).get());
  609. } else {
  610. IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: "
  611. "indexedDB.open(\"%s\", %s)",
  612. "IndexedDB %s: C R[%llu]: IDBFactory.open()",
  613. IDB_LOG_ID_STRING(),
  614. request->LoggingSerialNumber(),
  615. NS_ConvertUTF16toUTF8(aName).get(),
  616. IDB_LOG_STRINGIFY(aVersion));
  617. }
  618. // If we already have a background actor then we can start this request now.
  619. if (mBackgroundActor) {
  620. nsresult rv = InitiateRequest(request, params);
  621. if (NS_WARN_IF(NS_FAILED(rv))) {
  622. IDB_REPORT_INTERNAL_ERR();
  623. aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  624. return nullptr;
  625. }
  626. } else {
  627. mPendingRequests.AppendElement(new PendingRequestInfo(request, params));
  628. }
  629. return request.forget();
  630. }
  631. nsresult
  632. IDBFactory::BackgroundActorCreated(PBackgroundChild* aBackgroundActor,
  633. const LoggingInfo& aLoggingInfo)
  634. {
  635. MOZ_ASSERT(aBackgroundActor);
  636. MOZ_ASSERT(!mBackgroundActor);
  637. MOZ_ASSERT(!mBackgroundActorFailed);
  638. {
  639. BackgroundFactoryChild* actor = new BackgroundFactoryChild(this);
  640. mBackgroundActor =
  641. static_cast<BackgroundFactoryChild*>(
  642. aBackgroundActor->SendPBackgroundIDBFactoryConstructor(actor,
  643. aLoggingInfo));
  644. }
  645. if (NS_WARN_IF(!mBackgroundActor)) {
  646. BackgroundActorFailed();
  647. return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  648. }
  649. nsresult rv = NS_OK;
  650. for (uint32_t index = 0, count = mPendingRequests.Length();
  651. index < count;
  652. index++) {
  653. nsAutoPtr<PendingRequestInfo> info(mPendingRequests[index].forget());
  654. nsresult rv2 = InitiateRequest(info->mRequest, info->mParams);
  655. // Warn for every failure, but just return the first failure if there are
  656. // multiple failures.
  657. if (NS_WARN_IF(NS_FAILED(rv2)) && NS_SUCCEEDED(rv)) {
  658. rv = rv2;
  659. }
  660. }
  661. mPendingRequests.Clear();
  662. return rv;
  663. }
  664. void
  665. IDBFactory::BackgroundActorFailed()
  666. {
  667. MOZ_ASSERT(!mPendingRequests.IsEmpty());
  668. MOZ_ASSERT(!mBackgroundActor);
  669. MOZ_ASSERT(!mBackgroundActorFailed);
  670. mBackgroundActorFailed = true;
  671. for (uint32_t index = 0, count = mPendingRequests.Length();
  672. index < count;
  673. index++) {
  674. nsAutoPtr<PendingRequestInfo> info(mPendingRequests[index].forget());
  675. info->mRequest->
  676. DispatchNonTransactionError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  677. }
  678. mPendingRequests.Clear();
  679. }
  680. nsresult
  681. IDBFactory::InitiateRequest(IDBOpenDBRequest* aRequest,
  682. const FactoryRequestParams& aParams)
  683. {
  684. MOZ_ASSERT(aRequest);
  685. MOZ_ASSERT(mBackgroundActor);
  686. MOZ_ASSERT(!mBackgroundActorFailed);
  687. bool deleting;
  688. uint64_t requestedVersion;
  689. switch (aParams.type()) {
  690. case FactoryRequestParams::TDeleteDatabaseRequestParams: {
  691. const DatabaseMetadata& metadata =
  692. aParams.get_DeleteDatabaseRequestParams().commonParams().metadata();
  693. deleting = true;
  694. requestedVersion = metadata.version();
  695. break;
  696. }
  697. case FactoryRequestParams::TOpenDatabaseRequestParams: {
  698. const DatabaseMetadata& metadata =
  699. aParams.get_OpenDatabaseRequestParams().commonParams().metadata();
  700. deleting = false;
  701. requestedVersion = metadata.version();
  702. break;
  703. }
  704. default:
  705. MOZ_CRASH("Should never get here!");
  706. }
  707. auto actor =
  708. new BackgroundFactoryRequestChild(this,
  709. aRequest,
  710. deleting,
  711. requestedVersion);
  712. if (!mBackgroundActor->SendPBackgroundIDBFactoryRequestConstructor(actor,
  713. aParams)) {
  714. aRequest->DispatchNonTransactionError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  715. return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  716. }
  717. return NS_OK;
  718. }
  719. NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBFactory)
  720. NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBFactory)
  721. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBFactory)
  722. NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  723. NS_INTERFACE_MAP_ENTRY(nsISupports)
  724. NS_INTERFACE_MAP_END
  725. NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFactory)
  726. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBFactory)
  727. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
  728. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  729. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBFactory)
  730. NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
  731. tmp->mOwningObject = nullptr;
  732. NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
  733. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  734. NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBFactory)
  735. NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
  736. NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOwningObject)
  737. NS_IMPL_CYCLE_COLLECTION_TRACE_END
  738. JSObject*
  739. IDBFactory::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
  740. {
  741. return IDBFactoryBinding::Wrap(aCx, this, aGivenProto);
  742. }
  743. NS_IMPL_ISUPPORTS(IDBFactory::BackgroundCreateCallback,
  744. nsIIPCBackgroundChildCreateCallback)
  745. void
  746. IDBFactory::BackgroundCreateCallback::ActorCreated(PBackgroundChild* aActor)
  747. {
  748. MOZ_ASSERT(aActor);
  749. MOZ_ASSERT(mFactory);
  750. RefPtr<IDBFactory> factory;
  751. mFactory.swap(factory);
  752. factory->BackgroundActorCreated(aActor, mLoggingInfo);
  753. }
  754. void
  755. IDBFactory::BackgroundCreateCallback::ActorFailed()
  756. {
  757. MOZ_ASSERT(mFactory);
  758. RefPtr<IDBFactory> factory;
  759. mFactory.swap(factory);
  760. factory->BackgroundActorFailed();
  761. }
  762. } // namespace dom
  763. } // namespace mozilla