IDBTransaction.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  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 "IDBTransaction.h"
  6. #include "BackgroundChildImpl.h"
  7. #include "IDBDatabase.h"
  8. #include "IDBEvents.h"
  9. #include "IDBObjectStore.h"
  10. #include "IDBRequest.h"
  11. #include "mozilla/ErrorResult.h"
  12. #include "mozilla/EventDispatcher.h"
  13. #include "mozilla/dom/DOMError.h"
  14. #include "mozilla/dom/DOMStringList.h"
  15. #include "mozilla/ipc/BackgroundChild.h"
  16. #include "nsAutoPtr.h"
  17. #include "nsPIDOMWindow.h"
  18. #include "nsQueryObject.h"
  19. #include "nsServiceManagerUtils.h"
  20. #include "nsTHashtable.h"
  21. #include "ProfilerHelpers.h"
  22. #include "ReportInternalError.h"
  23. #include "WorkerHolder.h"
  24. #include "WorkerPrivate.h"
  25. // Include this last to avoid path problems on Windows.
  26. #include "ActorsChild.h"
  27. namespace mozilla {
  28. namespace dom {
  29. using namespace mozilla::dom::indexedDB;
  30. using namespace mozilla::dom::workers;
  31. using namespace mozilla::ipc;
  32. class IDBTransaction::WorkerHolder final
  33. : public mozilla::dom::workers::WorkerHolder
  34. {
  35. WorkerPrivate* mWorkerPrivate;
  36. // The IDBTransaction owns this object so we only need a weak reference back
  37. // to it.
  38. IDBTransaction* mTransaction;
  39. public:
  40. WorkerHolder(WorkerPrivate* aWorkerPrivate, IDBTransaction* aTransaction)
  41. : mWorkerPrivate(aWorkerPrivate)
  42. , mTransaction(aTransaction)
  43. {
  44. MOZ_ASSERT(aWorkerPrivate);
  45. MOZ_ASSERT(aTransaction);
  46. aWorkerPrivate->AssertIsOnWorkerThread();
  47. aTransaction->AssertIsOnOwningThread();
  48. MOZ_COUNT_CTOR(IDBTransaction::WorkerHolder);
  49. }
  50. ~WorkerHolder()
  51. {
  52. mWorkerPrivate->AssertIsOnWorkerThread();
  53. MOZ_COUNT_DTOR(IDBTransaction::WorkerHolder);
  54. }
  55. private:
  56. virtual bool
  57. Notify(Status aStatus) override;
  58. };
  59. IDBTransaction::IDBTransaction(IDBDatabase* aDatabase,
  60. const nsTArray<nsString>& aObjectStoreNames,
  61. Mode aMode)
  62. : IDBWrapperCache(aDatabase)
  63. , mDatabase(aDatabase)
  64. , mObjectStoreNames(aObjectStoreNames)
  65. , mLoggingSerialNumber(0)
  66. , mNextObjectStoreId(0)
  67. , mNextIndexId(0)
  68. , mAbortCode(NS_OK)
  69. , mPendingRequestCount(0)
  70. , mLineNo(0)
  71. , mColumn(0)
  72. , mReadyState(IDBTransaction::INITIAL)
  73. , mMode(aMode)
  74. , mCreating(false)
  75. , mRegistered(false)
  76. , mAbortedByScript(false)
  77. #ifdef DEBUG
  78. , mSentCommitOrAbort(false)
  79. , mFiredCompleteOrAbort(false)
  80. #endif
  81. {
  82. MOZ_ASSERT(aDatabase);
  83. aDatabase->AssertIsOnOwningThread();
  84. mBackgroundActor.mNormalBackgroundActor = nullptr;
  85. BackgroundChildImpl::ThreadLocal* threadLocal =
  86. BackgroundChildImpl::GetThreadLocalForCurrentThread();
  87. MOZ_ASSERT(threadLocal);
  88. ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
  89. MOZ_ASSERT(idbThreadLocal);
  90. const_cast<int64_t&>(mLoggingSerialNumber) =
  91. idbThreadLocal->NextTransactionSN(aMode);
  92. #ifdef DEBUG
  93. if (!aObjectStoreNames.IsEmpty()) {
  94. nsTArray<nsString> sortedNames(aObjectStoreNames);
  95. sortedNames.Sort();
  96. const uint32_t count = sortedNames.Length();
  97. MOZ_ASSERT(count == aObjectStoreNames.Length());
  98. // Make sure the array is properly sorted.
  99. for (uint32_t index = 0; index < count; index++) {
  100. MOZ_ASSERT(aObjectStoreNames[index] == sortedNames[index]);
  101. }
  102. // Make sure there are no duplicates in our objectStore names.
  103. for (uint32_t index = 0; index < count - 1; index++) {
  104. MOZ_ASSERT(sortedNames[index] != sortedNames[index + 1]);
  105. }
  106. }
  107. #endif
  108. }
  109. IDBTransaction::~IDBTransaction()
  110. {
  111. AssertIsOnOwningThread();
  112. MOZ_ASSERT(!mPendingRequestCount);
  113. MOZ_ASSERT(!mCreating);
  114. MOZ_ASSERT(mSentCommitOrAbort);
  115. MOZ_ASSERT_IF(mMode == VERSION_CHANGE &&
  116. mBackgroundActor.mVersionChangeBackgroundActor,
  117. mFiredCompleteOrAbort);
  118. MOZ_ASSERT_IF(mMode != VERSION_CHANGE &&
  119. mBackgroundActor.mNormalBackgroundActor,
  120. mFiredCompleteOrAbort);
  121. if (mRegistered) {
  122. mDatabase->UnregisterTransaction(this);
  123. #ifdef DEBUG
  124. mRegistered = false;
  125. #endif
  126. }
  127. if (mMode == VERSION_CHANGE) {
  128. if (auto* actor = mBackgroundActor.mVersionChangeBackgroundActor) {
  129. actor->SendDeleteMeInternal(/* aFailedConstructor */ false);
  130. MOZ_ASSERT(!mBackgroundActor.mVersionChangeBackgroundActor,
  131. "SendDeleteMeInternal should have cleared!");
  132. }
  133. } else if (auto* actor = mBackgroundActor.mNormalBackgroundActor) {
  134. actor->SendDeleteMeInternal();
  135. MOZ_ASSERT(!mBackgroundActor.mNormalBackgroundActor,
  136. "SendDeleteMeInternal should have cleared!");
  137. }
  138. }
  139. // static
  140. already_AddRefed<IDBTransaction>
  141. IDBTransaction::CreateVersionChange(
  142. IDBDatabase* aDatabase,
  143. BackgroundVersionChangeTransactionChild* aActor,
  144. IDBOpenDBRequest* aOpenRequest,
  145. int64_t aNextObjectStoreId,
  146. int64_t aNextIndexId)
  147. {
  148. MOZ_ASSERT(aDatabase);
  149. aDatabase->AssertIsOnOwningThread();
  150. MOZ_ASSERT(aActor);
  151. MOZ_ASSERT(aOpenRequest);
  152. MOZ_ASSERT(aNextObjectStoreId > 0);
  153. MOZ_ASSERT(aNextIndexId > 0);
  154. nsTArray<nsString> emptyObjectStoreNames;
  155. RefPtr<IDBTransaction> transaction =
  156. new IDBTransaction(aDatabase,
  157. emptyObjectStoreNames,
  158. VERSION_CHANGE);
  159. aOpenRequest->GetCallerLocation(transaction->mFilename,
  160. &transaction->mLineNo, &transaction->mColumn);
  161. transaction->SetScriptOwner(aDatabase->GetScriptOwner());
  162. nsCOMPtr<nsIRunnable> runnable = do_QueryObject(transaction);
  163. nsContentUtils::RunInMetastableState(runnable.forget());
  164. transaction->mBackgroundActor.mVersionChangeBackgroundActor = aActor;
  165. transaction->mNextObjectStoreId = aNextObjectStoreId;
  166. transaction->mNextIndexId = aNextIndexId;
  167. transaction->mCreating = true;
  168. aDatabase->RegisterTransaction(transaction);
  169. transaction->mRegistered = true;
  170. return transaction.forget();
  171. }
  172. // static
  173. already_AddRefed<IDBTransaction>
  174. IDBTransaction::Create(JSContext* aCx, IDBDatabase* aDatabase,
  175. const nsTArray<nsString>& aObjectStoreNames,
  176. Mode aMode)
  177. {
  178. MOZ_ASSERT(aDatabase);
  179. aDatabase->AssertIsOnOwningThread();
  180. MOZ_ASSERT(!aObjectStoreNames.IsEmpty());
  181. MOZ_ASSERT(aMode == READ_ONLY ||
  182. aMode == READ_WRITE ||
  183. aMode == READ_WRITE_FLUSH ||
  184. aMode == CLEANUP);
  185. RefPtr<IDBTransaction> transaction =
  186. new IDBTransaction(aDatabase, aObjectStoreNames, aMode);
  187. IDBRequest::CaptureCaller(aCx, transaction->mFilename, &transaction->mLineNo,
  188. &transaction->mColumn);
  189. transaction->SetScriptOwner(aDatabase->GetScriptOwner());
  190. nsCOMPtr<nsIRunnable> runnable = do_QueryObject(transaction);
  191. nsContentUtils::RunInMetastableState(runnable.forget());
  192. transaction->mCreating = true;
  193. aDatabase->RegisterTransaction(transaction);
  194. transaction->mRegistered = true;
  195. if (!NS_IsMainThread()) {
  196. WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
  197. MOZ_ASSERT(workerPrivate);
  198. workerPrivate->AssertIsOnWorkerThread();
  199. transaction->mWorkerHolder = new WorkerHolder(workerPrivate, transaction);
  200. MOZ_ALWAYS_TRUE(transaction->mWorkerHolder->HoldWorker(workerPrivate, Canceling));
  201. }
  202. return transaction.forget();
  203. }
  204. // static
  205. IDBTransaction*
  206. IDBTransaction::GetCurrent()
  207. {
  208. using namespace mozilla::ipc;
  209. MOZ_ASSERT(BackgroundChild::GetForCurrentThread());
  210. BackgroundChildImpl::ThreadLocal* threadLocal =
  211. BackgroundChildImpl::GetThreadLocalForCurrentThread();
  212. MOZ_ASSERT(threadLocal);
  213. ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
  214. MOZ_ASSERT(idbThreadLocal);
  215. return idbThreadLocal->GetCurrentTransaction();
  216. }
  217. #ifdef DEBUG
  218. void
  219. IDBTransaction::AssertIsOnOwningThread() const
  220. {
  221. MOZ_ASSERT(mDatabase);
  222. mDatabase->AssertIsOnOwningThread();
  223. }
  224. #endif // DEBUG
  225. void
  226. IDBTransaction::SetBackgroundActor(indexedDB::BackgroundTransactionChild* aBackgroundActor)
  227. {
  228. AssertIsOnOwningThread();
  229. MOZ_ASSERT(aBackgroundActor);
  230. MOZ_ASSERT(!mBackgroundActor.mNormalBackgroundActor);
  231. MOZ_ASSERT(mMode != VERSION_CHANGE);
  232. mBackgroundActor.mNormalBackgroundActor = aBackgroundActor;
  233. }
  234. BackgroundRequestChild*
  235. IDBTransaction::StartRequest(IDBRequest* aRequest, const RequestParams& aParams)
  236. {
  237. AssertIsOnOwningThread();
  238. MOZ_ASSERT(aRequest);
  239. MOZ_ASSERT(aParams.type() != RequestParams::T__None);
  240. BackgroundRequestChild* actor = new BackgroundRequestChild(aRequest);
  241. if (mMode == VERSION_CHANGE) {
  242. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  243. mBackgroundActor.mVersionChangeBackgroundActor->
  244. SendPBackgroundIDBRequestConstructor(actor, aParams);
  245. } else {
  246. MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
  247. mBackgroundActor.mNormalBackgroundActor->
  248. SendPBackgroundIDBRequestConstructor(actor, aParams);
  249. }
  250. // Balanced in BackgroundRequestChild::Recv__delete__().
  251. OnNewRequest();
  252. return actor;
  253. }
  254. void
  255. IDBTransaction::OpenCursor(BackgroundCursorChild* aBackgroundActor,
  256. const OpenCursorParams& aParams)
  257. {
  258. AssertIsOnOwningThread();
  259. MOZ_ASSERT(aBackgroundActor);
  260. MOZ_ASSERT(aParams.type() != OpenCursorParams::T__None);
  261. if (mMode == VERSION_CHANGE) {
  262. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  263. mBackgroundActor.mVersionChangeBackgroundActor->
  264. SendPBackgroundIDBCursorConstructor(aBackgroundActor, aParams);
  265. } else {
  266. MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
  267. mBackgroundActor.mNormalBackgroundActor->
  268. SendPBackgroundIDBCursorConstructor(aBackgroundActor, aParams);
  269. }
  270. // Balanced in BackgroundCursorChild::RecvResponse().
  271. OnNewRequest();
  272. }
  273. void
  274. IDBTransaction::RefreshSpec(bool aMayDelete)
  275. {
  276. AssertIsOnOwningThread();
  277. for (uint32_t count = mObjectStores.Length(), index = 0;
  278. index < count;
  279. index++) {
  280. mObjectStores[index]->RefreshSpec(aMayDelete);
  281. }
  282. for (uint32_t count = mDeletedObjectStores.Length(), index = 0;
  283. index < count;
  284. index++) {
  285. mDeletedObjectStores[index]->RefreshSpec(false);
  286. }
  287. }
  288. void
  289. IDBTransaction::OnNewRequest()
  290. {
  291. AssertIsOnOwningThread();
  292. if (!mPendingRequestCount) {
  293. MOZ_ASSERT(INITIAL == mReadyState);
  294. mReadyState = LOADING;
  295. }
  296. ++mPendingRequestCount;
  297. }
  298. void
  299. IDBTransaction::OnRequestFinished(bool aActorDestroyedNormally)
  300. {
  301. AssertIsOnOwningThread();
  302. MOZ_ASSERT(mPendingRequestCount);
  303. --mPendingRequestCount;
  304. if (!mPendingRequestCount) {
  305. mReadyState = COMMITTING;
  306. if (aActorDestroyedNormally) {
  307. if (NS_SUCCEEDED(mAbortCode)) {
  308. SendCommit();
  309. } else {
  310. SendAbort(mAbortCode);
  311. }
  312. } else {
  313. // Don't try to send any more messages to the parent if the request actor
  314. // was killed.
  315. #ifdef DEBUG
  316. MOZ_ASSERT(!mSentCommitOrAbort);
  317. mSentCommitOrAbort = true;
  318. #endif
  319. IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: "
  320. "Request actor was killed, transaction will be aborted",
  321. "IndexedDB %s: C T[%lld]: IDBTransaction abort",
  322. IDB_LOG_ID_STRING(),
  323. LoggingSerialNumber());
  324. }
  325. }
  326. }
  327. void
  328. IDBTransaction::SendCommit()
  329. {
  330. AssertIsOnOwningThread();
  331. MOZ_ASSERT(NS_SUCCEEDED(mAbortCode));
  332. MOZ_ASSERT(IsCommittingOrDone());
  333. MOZ_ASSERT(!mSentCommitOrAbort);
  334. MOZ_ASSERT(!mPendingRequestCount);
  335. // Don't do this in the macro because we always need to increment the serial
  336. // number to keep in sync with the parent.
  337. const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
  338. IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
  339. "All requests complete, committing transaction",
  340. "IndexedDB %s: C T[%lld] R[%llu]: IDBTransaction commit",
  341. IDB_LOG_ID_STRING(),
  342. LoggingSerialNumber(),
  343. requestSerialNumber);
  344. if (mMode == VERSION_CHANGE) {
  345. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  346. mBackgroundActor.mVersionChangeBackgroundActor->SendCommit();
  347. } else {
  348. MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
  349. mBackgroundActor.mNormalBackgroundActor->SendCommit();
  350. }
  351. #ifdef DEBUG
  352. mSentCommitOrAbort = true;
  353. #endif
  354. }
  355. void
  356. IDBTransaction::SendAbort(nsresult aResultCode)
  357. {
  358. AssertIsOnOwningThread();
  359. MOZ_ASSERT(NS_FAILED(aResultCode));
  360. MOZ_ASSERT(IsCommittingOrDone());
  361. MOZ_ASSERT(!mSentCommitOrAbort);
  362. // Don't do this in the macro because we always need to increment the serial
  363. // number to keep in sync with the parent.
  364. const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
  365. IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
  366. "Aborting transaction with result 0x%x",
  367. "IndexedDB %s: C T[%lld] R[%llu]: IDBTransaction abort (0x%x)",
  368. IDB_LOG_ID_STRING(),
  369. LoggingSerialNumber(),
  370. requestSerialNumber,
  371. aResultCode);
  372. if (mMode == VERSION_CHANGE) {
  373. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  374. mBackgroundActor.mVersionChangeBackgroundActor->SendAbort(aResultCode);
  375. } else {
  376. MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
  377. mBackgroundActor.mNormalBackgroundActor->SendAbort(aResultCode);
  378. }
  379. #ifdef DEBUG
  380. mSentCommitOrAbort = true;
  381. #endif
  382. }
  383. bool
  384. IDBTransaction::IsOpen() const
  385. {
  386. AssertIsOnOwningThread();
  387. // If we haven't started anything then we're open.
  388. if (mReadyState == IDBTransaction::INITIAL) {
  389. return true;
  390. }
  391. // If we've already started then we need to check to see if we still have the
  392. // mCreating flag set. If we do (i.e. we haven't returned to the event loop
  393. // from the time we were created) then we are open. Otherwise check the
  394. // currently running transaction to see if it's the same. We only allow other
  395. // requests to be made if this transaction is currently running.
  396. if (mReadyState == IDBTransaction::LOADING &&
  397. (mCreating || GetCurrent() == this)) {
  398. return true;
  399. }
  400. return false;
  401. }
  402. void
  403. IDBTransaction::GetCallerLocation(nsAString& aFilename, uint32_t* aLineNo,
  404. uint32_t* aColumn) const
  405. {
  406. AssertIsOnOwningThread();
  407. MOZ_ASSERT(aLineNo);
  408. MOZ_ASSERT(aColumn);
  409. aFilename = mFilename;
  410. *aLineNo = mLineNo;
  411. *aColumn = mColumn;
  412. }
  413. already_AddRefed<IDBObjectStore>
  414. IDBTransaction::CreateObjectStore(const ObjectStoreSpec& aSpec)
  415. {
  416. AssertIsOnOwningThread();
  417. MOZ_ASSERT(aSpec.metadata().id());
  418. MOZ_ASSERT(VERSION_CHANGE == mMode);
  419. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  420. MOZ_ASSERT(IsOpen());
  421. #ifdef DEBUG
  422. {
  423. const nsString& name = aSpec.metadata().name();
  424. for (uint32_t count = mObjectStores.Length(), index = 0;
  425. index < count;
  426. index++) {
  427. MOZ_ASSERT(mObjectStores[index]->Name() != name);
  428. }
  429. }
  430. #endif
  431. MOZ_ALWAYS_TRUE(mBackgroundActor.mVersionChangeBackgroundActor->
  432. SendCreateObjectStore(aSpec.metadata()));
  433. RefPtr<IDBObjectStore> objectStore = IDBObjectStore::Create(this, aSpec);
  434. MOZ_ASSERT(objectStore);
  435. mObjectStores.AppendElement(objectStore);
  436. return objectStore.forget();
  437. }
  438. void
  439. IDBTransaction::DeleteObjectStore(int64_t aObjectStoreId)
  440. {
  441. AssertIsOnOwningThread();
  442. MOZ_ASSERT(aObjectStoreId);
  443. MOZ_ASSERT(VERSION_CHANGE == mMode);
  444. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  445. MOZ_ASSERT(IsOpen());
  446. MOZ_ALWAYS_TRUE(mBackgroundActor.mVersionChangeBackgroundActor->
  447. SendDeleteObjectStore(aObjectStoreId));
  448. for (uint32_t count = mObjectStores.Length(), index = 0;
  449. index < count;
  450. index++) {
  451. RefPtr<IDBObjectStore>& objectStore = mObjectStores[index];
  452. if (objectStore->Id() == aObjectStoreId) {
  453. objectStore->NoteDeletion();
  454. RefPtr<IDBObjectStore>* deletedObjectStore =
  455. mDeletedObjectStores.AppendElement();
  456. deletedObjectStore->swap(mObjectStores[index]);
  457. mObjectStores.RemoveElementAt(index);
  458. break;
  459. }
  460. }
  461. }
  462. void
  463. IDBTransaction::RenameObjectStore(int64_t aObjectStoreId,
  464. const nsAString& aName)
  465. {
  466. AssertIsOnOwningThread();
  467. MOZ_ASSERT(aObjectStoreId);
  468. MOZ_ASSERT(VERSION_CHANGE == mMode);
  469. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  470. MOZ_ASSERT(IsOpen());
  471. MOZ_ALWAYS_TRUE(mBackgroundActor.mVersionChangeBackgroundActor->
  472. SendRenameObjectStore(aObjectStoreId, nsString(aName)));
  473. }
  474. void
  475. IDBTransaction::CreateIndex(IDBObjectStore* aObjectStore,
  476. const indexedDB::IndexMetadata& aMetadata)
  477. {
  478. AssertIsOnOwningThread();
  479. MOZ_ASSERT(aObjectStore);
  480. MOZ_ASSERT(aMetadata.id());
  481. MOZ_ASSERT(VERSION_CHANGE == mMode);
  482. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  483. MOZ_ASSERT(IsOpen());
  484. MOZ_ALWAYS_TRUE(mBackgroundActor.mVersionChangeBackgroundActor->
  485. SendCreateIndex(aObjectStore->Id(), aMetadata));
  486. }
  487. void
  488. IDBTransaction::DeleteIndex(IDBObjectStore* aObjectStore,
  489. int64_t aIndexId)
  490. {
  491. AssertIsOnOwningThread();
  492. MOZ_ASSERT(aObjectStore);
  493. MOZ_ASSERT(aIndexId);
  494. MOZ_ASSERT(VERSION_CHANGE == mMode);
  495. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  496. MOZ_ASSERT(IsOpen());
  497. MOZ_ALWAYS_TRUE(mBackgroundActor.mVersionChangeBackgroundActor->
  498. SendDeleteIndex(aObjectStore->Id(), aIndexId));
  499. }
  500. void
  501. IDBTransaction::RenameIndex(IDBObjectStore* aObjectStore,
  502. int64_t aIndexId,
  503. const nsAString& aName)
  504. {
  505. AssertIsOnOwningThread();
  506. MOZ_ASSERT(aObjectStore);
  507. MOZ_ASSERT(aIndexId);
  508. MOZ_ASSERT(VERSION_CHANGE == mMode);
  509. MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
  510. MOZ_ASSERT(IsOpen());
  511. MOZ_ALWAYS_TRUE(mBackgroundActor.mVersionChangeBackgroundActor->
  512. SendRenameIndex(aObjectStore->Id(),
  513. aIndexId,
  514. nsString(aName)));
  515. }
  516. void
  517. IDBTransaction::AbortInternal(nsresult aAbortCode,
  518. already_AddRefed<DOMError> aError)
  519. {
  520. AssertIsOnOwningThread();
  521. MOZ_ASSERT(NS_FAILED(aAbortCode));
  522. MOZ_ASSERT(!IsCommittingOrDone());
  523. RefPtr<DOMError> error = aError;
  524. const bool isVersionChange = mMode == VERSION_CHANGE;
  525. const bool isInvalidated = mDatabase->IsInvalidated();
  526. bool needToSendAbort = mReadyState == INITIAL;
  527. mAbortCode = aAbortCode;
  528. mReadyState = DONE;
  529. mError = error.forget();
  530. if (isVersionChange) {
  531. // If a version change transaction is aborted, we must revert the world
  532. // back to its previous state unless we're being invalidated after the
  533. // transaction already completed.
  534. if (!isInvalidated) {
  535. mDatabase->RevertToPreviousState();
  536. }
  537. // We do the reversion only for the mObjectStores/mDeletedObjectStores but
  538. // not for the mIndexes/mDeletedIndexes of each IDBObjectStore because it's
  539. // time-consuming(O(m*n)) and mIndexes/mDeletedIndexes won't be used anymore
  540. // in IDBObjectStore::(Create|Delete)Index() and IDBObjectStore::Index() in
  541. // which all the executions are returned earlier by !transaction->IsOpen().
  542. const nsTArray<ObjectStoreSpec>& specArray =
  543. mDatabase->Spec()->objectStores();
  544. if (specArray.IsEmpty()) {
  545. mObjectStores.Clear();
  546. mDeletedObjectStores.Clear();
  547. } else {
  548. nsTHashtable<nsUint64HashKey> validIds(specArray.Length());
  549. for (uint32_t specCount = specArray.Length(), specIndex = 0;
  550. specIndex < specCount;
  551. specIndex++) {
  552. const int64_t objectStoreId = specArray[specIndex].metadata().id();
  553. MOZ_ASSERT(objectStoreId);
  554. validIds.PutEntry(uint64_t(objectStoreId));
  555. }
  556. for (uint32_t objCount = mObjectStores.Length(), objIndex = 0;
  557. objIndex < objCount;
  558. /* incremented conditionally */) {
  559. const int64_t objectStoreId = mObjectStores[objIndex]->Id();
  560. MOZ_ASSERT(objectStoreId);
  561. if (validIds.Contains(uint64_t(objectStoreId))) {
  562. objIndex++;
  563. } else {
  564. mObjectStores.RemoveElementAt(objIndex);
  565. objCount--;
  566. }
  567. }
  568. if (!mDeletedObjectStores.IsEmpty()) {
  569. for (uint32_t objCount = mDeletedObjectStores.Length(), objIndex = 0;
  570. objIndex < objCount;
  571. objIndex++) {
  572. const int64_t objectStoreId = mDeletedObjectStores[objIndex]->Id();
  573. MOZ_ASSERT(objectStoreId);
  574. if (validIds.Contains(uint64_t(objectStoreId))) {
  575. RefPtr<IDBObjectStore>* objectStore =
  576. mObjectStores.AppendElement();
  577. objectStore->swap(mDeletedObjectStores[objIndex]);
  578. }
  579. }
  580. mDeletedObjectStores.Clear();
  581. }
  582. }
  583. }
  584. // Fire the abort event if there are no outstanding requests. Otherwise the
  585. // abort event will be fired when all outstanding requests finish.
  586. if (needToSendAbort) {
  587. SendAbort(aAbortCode);
  588. }
  589. if (isVersionChange) {
  590. mDatabase->Close();
  591. }
  592. }
  593. void
  594. IDBTransaction::Abort(IDBRequest* aRequest)
  595. {
  596. AssertIsOnOwningThread();
  597. MOZ_ASSERT(aRequest);
  598. if (IsCommittingOrDone()) {
  599. // Already started (and maybe finished) the commit or abort so there is
  600. // nothing to do here.
  601. return;
  602. }
  603. ErrorResult rv;
  604. RefPtr<DOMError> error = aRequest->GetError(rv);
  605. AbortInternal(aRequest->GetErrorCode(), error.forget());
  606. }
  607. void
  608. IDBTransaction::Abort(nsresult aErrorCode)
  609. {
  610. AssertIsOnOwningThread();
  611. if (IsCommittingOrDone()) {
  612. // Already started (and maybe finished) the commit or abort so there is
  613. // nothing to do here.
  614. return;
  615. }
  616. RefPtr<DOMError> error = new DOMError(GetOwner(), aErrorCode);
  617. AbortInternal(aErrorCode, error.forget());
  618. }
  619. void
  620. IDBTransaction::Abort(ErrorResult& aRv)
  621. {
  622. AssertIsOnOwningThread();
  623. if (IsCommittingOrDone()) {
  624. aRv = NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
  625. return;
  626. }
  627. AbortInternal(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR, nullptr);
  628. MOZ_ASSERT(!mAbortedByScript);
  629. mAbortedByScript = true;
  630. }
  631. void
  632. IDBTransaction::FireCompleteOrAbortEvents(nsresult aResult)
  633. {
  634. AssertIsOnOwningThread();
  635. MOZ_ASSERT(!mFiredCompleteOrAbort);
  636. mReadyState = DONE;
  637. #ifdef DEBUG
  638. mFiredCompleteOrAbort = true;
  639. #endif
  640. // Make sure we drop the WorkerHolder when this function completes.
  641. nsAutoPtr<WorkerHolder> workerHolder = Move(mWorkerHolder);
  642. nsCOMPtr<nsIDOMEvent> event;
  643. if (NS_SUCCEEDED(aResult)) {
  644. event = CreateGenericEvent(this,
  645. nsDependentString(kCompleteEventType),
  646. eDoesNotBubble,
  647. eNotCancelable);
  648. MOZ_ASSERT(event);
  649. } else {
  650. if (aResult == NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR) {
  651. mDatabase->SetQuotaExceeded();
  652. }
  653. if (!mError && !mAbortedByScript) {
  654. mError = new DOMError(GetOwner(), aResult);
  655. }
  656. event = CreateGenericEvent(this,
  657. nsDependentString(kAbortEventType),
  658. eDoesBubble,
  659. eNotCancelable);
  660. MOZ_ASSERT(event);
  661. }
  662. if (NS_SUCCEEDED(mAbortCode)) {
  663. IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: "
  664. "Firing 'complete' event",
  665. "IndexedDB %s: C T[%lld]: IDBTransaction 'complete' event",
  666. IDB_LOG_ID_STRING(),
  667. mLoggingSerialNumber);
  668. } else {
  669. IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: "
  670. "Firing 'abort' event with error 0x%x",
  671. "IndexedDB %s: C T[%lld]: IDBTransaction 'abort' event (0x%x)",
  672. IDB_LOG_ID_STRING(),
  673. mLoggingSerialNumber,
  674. mAbortCode);
  675. }
  676. bool dummy;
  677. if (NS_FAILED(DispatchEvent(event, &dummy))) {
  678. NS_WARNING("DispatchEvent failed!");
  679. }
  680. mDatabase->DelayedMaybeExpireFileActors();
  681. }
  682. int64_t
  683. IDBTransaction::NextObjectStoreId()
  684. {
  685. AssertIsOnOwningThread();
  686. MOZ_ASSERT(VERSION_CHANGE == mMode);
  687. return mNextObjectStoreId++;
  688. }
  689. int64_t
  690. IDBTransaction::NextIndexId()
  691. {
  692. AssertIsOnOwningThread();
  693. MOZ_ASSERT(VERSION_CHANGE == mMode);
  694. return mNextIndexId++;
  695. }
  696. nsPIDOMWindowInner*
  697. IDBTransaction::GetParentObject() const
  698. {
  699. AssertIsOnOwningThread();
  700. return mDatabase->GetParentObject();
  701. }
  702. IDBTransactionMode
  703. IDBTransaction::GetMode(ErrorResult& aRv) const
  704. {
  705. AssertIsOnOwningThread();
  706. switch (mMode) {
  707. case READ_ONLY:
  708. return IDBTransactionMode::Readonly;
  709. case READ_WRITE:
  710. return IDBTransactionMode::Readwrite;
  711. case READ_WRITE_FLUSH:
  712. return IDBTransactionMode::Readwriteflush;
  713. case CLEANUP:
  714. return IDBTransactionMode::Cleanup;
  715. case VERSION_CHANGE:
  716. return IDBTransactionMode::Versionchange;
  717. case MODE_INVALID:
  718. default:
  719. MOZ_CRASH("Bad mode!");
  720. }
  721. }
  722. DOMError*
  723. IDBTransaction::GetError() const
  724. {
  725. AssertIsOnOwningThread();
  726. return mError;
  727. }
  728. already_AddRefed<DOMStringList>
  729. IDBTransaction::ObjectStoreNames() const
  730. {
  731. AssertIsOnOwningThread();
  732. if (mMode == IDBTransaction::VERSION_CHANGE) {
  733. return mDatabase->ObjectStoreNames();
  734. }
  735. RefPtr<DOMStringList> list = new DOMStringList();
  736. list->StringArray() = mObjectStoreNames;
  737. return list.forget();
  738. }
  739. already_AddRefed<IDBObjectStore>
  740. IDBTransaction::ObjectStore(const nsAString& aName, ErrorResult& aRv)
  741. {
  742. AssertIsOnOwningThread();
  743. if (IsCommittingOrDone()) {
  744. aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
  745. return nullptr;
  746. }
  747. const ObjectStoreSpec* spec = nullptr;
  748. if (IDBTransaction::VERSION_CHANGE == mMode ||
  749. mObjectStoreNames.Contains(aName)) {
  750. const nsTArray<ObjectStoreSpec>& objectStores =
  751. mDatabase->Spec()->objectStores();
  752. for (uint32_t count = objectStores.Length(), index = 0;
  753. index < count;
  754. index++) {
  755. const ObjectStoreSpec& objectStore = objectStores[index];
  756. if (objectStore.metadata().name() == aName) {
  757. spec = &objectStore;
  758. break;
  759. }
  760. }
  761. }
  762. if (!spec) {
  763. aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR);
  764. return nullptr;
  765. }
  766. const int64_t desiredId = spec->metadata().id();
  767. RefPtr<IDBObjectStore> objectStore;
  768. for (uint32_t count = mObjectStores.Length(), index = 0;
  769. index < count;
  770. index++) {
  771. RefPtr<IDBObjectStore>& existingObjectStore = mObjectStores[index];
  772. if (existingObjectStore->Id() == desiredId) {
  773. objectStore = existingObjectStore;
  774. break;
  775. }
  776. }
  777. if (!objectStore) {
  778. objectStore = IDBObjectStore::Create(this, *spec);
  779. MOZ_ASSERT(objectStore);
  780. mObjectStores.AppendElement(objectStore);
  781. }
  782. return objectStore.forget();
  783. }
  784. NS_IMPL_ADDREF_INHERITED(IDBTransaction, IDBWrapperCache)
  785. NS_IMPL_RELEASE_INHERITED(IDBTransaction, IDBWrapperCache)
  786. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBTransaction)
  787. NS_INTERFACE_MAP_ENTRY(nsIRunnable)
  788. NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache)
  789. NS_IMPL_CYCLE_COLLECTION_CLASS(IDBTransaction)
  790. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBTransaction,
  791. IDBWrapperCache)
  792. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDatabase)
  793. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
  794. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStores)
  795. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeletedObjectStores)
  796. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  797. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBTransaction, IDBWrapperCache)
  798. // Don't unlink mDatabase!
  799. NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
  800. NS_IMPL_CYCLE_COLLECTION_UNLINK(mObjectStores)
  801. NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeletedObjectStores)
  802. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  803. JSObject*
  804. IDBTransaction::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
  805. {
  806. AssertIsOnOwningThread();
  807. return IDBTransactionBinding::Wrap(aCx, this, aGivenProto);
  808. }
  809. nsresult
  810. IDBTransaction::GetEventTargetParent(EventChainPreVisitor& aVisitor)
  811. {
  812. AssertIsOnOwningThread();
  813. aVisitor.mCanHandle = true;
  814. aVisitor.SetParentTarget(mDatabase, false);
  815. return NS_OK;
  816. }
  817. NS_IMETHODIMP
  818. IDBTransaction::Run()
  819. {
  820. AssertIsOnOwningThread();
  821. // We're back at the event loop, no longer newborn.
  822. mCreating = false;
  823. // Maybe commit if there were no requests generated.
  824. if (mReadyState == IDBTransaction::INITIAL) {
  825. mReadyState = DONE;
  826. SendCommit();
  827. }
  828. return NS_OK;
  829. }
  830. bool
  831. IDBTransaction::
  832. WorkerHolder::Notify(Status aStatus)
  833. {
  834. MOZ_ASSERT(mWorkerPrivate);
  835. mWorkerPrivate->AssertIsOnWorkerThread();
  836. MOZ_ASSERT(aStatus > Running);
  837. if (mTransaction && aStatus > Terminating) {
  838. mTransaction->AssertIsOnOwningThread();
  839. RefPtr<IDBTransaction> transaction = Move(mTransaction);
  840. if (!transaction->IsCommittingOrDone()) {
  841. IDB_REPORT_INTERNAL_ERR();
  842. transaction->AbortInternal(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR, nullptr);
  843. }
  844. }
  845. return true;
  846. }
  847. } // namespace dom
  848. } // namespace mozilla