Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=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/. */
6
7
#ifndef mozilla_dom_idbtransaction_h__
8
#define mozilla_dom_idbtransaction_h__
9
10
#include "FlippedOnce.h"
11
#include "mozilla/Attributes.h"
12
#include "mozilla/dom/IDBTransactionBinding.h"
13
#include "mozilla/DOMEventTargetHelper.h"
14
#include "nsAutoPtr.h"
15
#include "nsCycleCollectionParticipant.h"
16
#include "nsIRunnable.h"
17
#include "nsString.h"
18
#include "nsTArray.h"
19
20
namespace mozilla {
21
22
class ErrorResult;
23
class EventChainPreVisitor;
24
25
namespace dom {
26
27
class DOMException;
28
class DOMStringList;
29
class IDBCursor;
30
class IDBDatabase;
31
class IDBObjectStore;
32
class IDBOpenDBRequest;
33
class IDBRequest;
34
class StrongWorkerRef;
35
36
namespace indexedDB {
37
class BackgroundCursorChild;
38
class BackgroundRequestChild;
39
class BackgroundTransactionChild;
40
class BackgroundVersionChangeTransactionChild;
41
class IndexMetadata;
42
class ObjectStoreSpec;
43
class OpenCursorParams;
44
class RequestParams;
45
} // namespace indexedDB
46
47
class IDBTransaction final : public DOMEventTargetHelper, public nsIRunnable {
48
friend class indexedDB::BackgroundCursorChild;
49
friend class indexedDB::BackgroundRequestChild;
50
51
public:
52
enum struct Mode {
53
ReadOnly = 0,
54
ReadWrite,
55
ReadWriteFlush,
56
Cleanup,
57
VersionChange,
58
59
// Only needed for IPC serialization helper, should never be used in code.
60
Invalid
61
};
62
63
enum struct ReadyState { Active, Inactive, Committing, Finished };
64
65
private:
66
// TODO: Only non-const because of Bug 1575173.
67
RefPtr<IDBDatabase> mDatabase;
68
RefPtr<DOMException> mError;
69
const nsTArray<nsString> mObjectStoreNames;
70
nsTArray<RefPtr<IDBObjectStore>> mObjectStores;
71
nsTArray<RefPtr<IDBObjectStore>> mDeletedObjectStores;
72
RefPtr<StrongWorkerRef> mWorkerRef;
73
nsTArray<IDBCursor*> mCursors;
74
75
// Tagged with mMode. If mMode is Mode::VersionChange then mBackgroundActor
76
// will be a BackgroundVersionChangeTransactionChild. Otherwise it will be a
77
// BackgroundTransactionChild.
78
union {
79
indexedDB::BackgroundTransactionChild* mNormalBackgroundActor;
80
indexedDB::BackgroundVersionChangeTransactionChild*
81
mVersionChangeBackgroundActor;
82
} mBackgroundActor;
83
84
const int64_t mLoggingSerialNumber;
85
86
// Only used for Mode::VersionChange transactions.
87
int64_t mNextObjectStoreId;
88
int64_t mNextIndexId;
89
90
nsresult mAbortCode; ///< The result that caused the transaction to be
91
///< aborted, or NS_OK if not aborted.
92
///< NS_ERROR_DOM_INDEXEDDB_ABORT_ERR indicates that the
93
///< user explicitly requested aborting. Should be
94
///< renamed to mResult or so, because it is actually
95
///< used to check if the transaction has been aborted.
96
uint32_t mPendingRequestCount; ///< Counted via OnNewRequest and
97
///< OnRequestFinished, so that the
98
///< transaction can auto-commit when the last
99
///< pending request finished.
100
101
const nsString mFilename;
102
const uint32_t mLineNo;
103
const uint32_t mColumn;
104
105
ReadyState mReadyState = ReadyState::Active;
106
FlippedOnce<false> mStarted;
107
const Mode mMode;
108
109
bool mCreating; ///< Set between successful creation until the transaction
110
///< has run on the event-loop.
111
bool mRegistered; ///< Whether mDatabase->RegisterTransaction() has been
112
///< called (which may not be the case if construction was
113
///< incomplete).
114
FlippedOnce<false> mAbortedByScript;
115
bool mNotedActiveTransaction;
116
117
#ifdef DEBUG
118
FlippedOnce<false> mSentCommitOrAbort;
119
FlippedOnce<false> mFiredCompleteOrAbort;
120
#endif
121
122
public:
123
static MOZ_MUST_USE RefPtr<IDBTransaction> CreateVersionChange(
124
IDBDatabase* aDatabase,
125
indexedDB::BackgroundVersionChangeTransactionChild* aActor,
126
IDBOpenDBRequest* aOpenRequest, int64_t aNextObjectStoreId,
127
int64_t aNextIndexId);
128
129
static MOZ_MUST_USE RefPtr<IDBTransaction> Create(
130
JSContext* aCx, IDBDatabase* aDatabase,
131
const nsTArray<nsString>& aObjectStoreNames, Mode aMode);
132
133
static IDBTransaction* GetCurrent();
134
135
void AssertIsOnOwningThread() const
136
#ifdef DEBUG
137
;
138
#else
139
{
140
}
141
#endif
142
143
void SetBackgroundActor(
144
indexedDB::BackgroundTransactionChild* aBackgroundActor);
145
146
void ClearBackgroundActor() {
147
AssertIsOnOwningThread();
148
149
if (mMode == Mode::VersionChange) {
150
mBackgroundActor.mVersionChangeBackgroundActor = nullptr;
151
} else {
152
mBackgroundActor.mNormalBackgroundActor = nullptr;
153
}
154
155
// Note inactive transaction here if we didn't receive the Complete message
156
// from the parent.
157
MaybeNoteInactiveTransaction();
158
}
159
160
indexedDB::BackgroundRequestChild* StartRequest(
161
IDBRequest* aRequest, const indexedDB::RequestParams& aParams);
162
163
void OpenCursor(indexedDB::BackgroundCursorChild* aBackgroundActor,
164
const indexedDB::OpenCursorParams& aParams);
165
166
void RefreshSpec(bool aMayDelete);
167
168
bool CanAcceptRequests() const;
169
170
bool IsCommittingOrFinished() const {
171
AssertIsOnOwningThread();
172
173
return mReadyState == ReadyState::Committing ||
174
mReadyState == ReadyState::Finished;
175
}
176
177
bool IsActive() const {
178
AssertIsOnOwningThread();
179
180
return mReadyState == ReadyState::Active;
181
}
182
183
bool IsInactive() const {
184
AssertIsOnOwningThread();
185
186
return mReadyState == ReadyState::Inactive;
187
}
188
189
bool IsFinished() const {
190
AssertIsOnOwningThread();
191
192
return mReadyState == ReadyState::Finished;
193
}
194
195
bool IsWriteAllowed() const {
196
AssertIsOnOwningThread();
197
return mMode == Mode::ReadWrite || mMode == Mode::ReadWriteFlush ||
198
mMode == Mode::Cleanup || mMode == Mode::VersionChange;
199
}
200
201
bool IsAborted() const {
202
AssertIsOnOwningThread();
203
return NS_FAILED(mAbortCode);
204
}
205
206
template <ReadyState OriginalState, ReadyState TemporaryState>
207
class AutoRestoreState {
208
public:
209
explicit AutoRestoreState(IDBTransaction& aOwner) : mOwner { aOwner }
210
#ifdef DEBUG
211
, mSavedPendingRequestCount { mOwner.mPendingRequestCount }
212
#endif
213
{
214
mOwner.AssertIsOnOwningThread();
215
MOZ_ASSERT(mOwner.mReadyState == OriginalState);
216
mOwner.mReadyState = TemporaryState;
217
}
218
219
~AutoRestoreState() {
220
mOwner.AssertIsOnOwningThread();
221
MOZ_ASSERT(mOwner.mReadyState == TemporaryState);
222
MOZ_ASSERT(mOwner.mPendingRequestCount == mSavedPendingRequestCount);
223
224
mOwner.mReadyState = OriginalState;
225
}
226
227
private:
228
IDBTransaction& mOwner;
229
#ifdef DEBUG
230
const uint32_t mSavedPendingRequestCount;
231
#endif
232
};
233
234
AutoRestoreState<ReadyState::Inactive, ReadyState::Active>
235
TemporarilyTransitionToActive();
236
AutoRestoreState<ReadyState::Active, ReadyState::Inactive>
237
TemporarilyTransitionToInactive();
238
239
void TransitionToActive() {
240
MOZ_ASSERT(mReadyState == ReadyState::Inactive);
241
mReadyState = ReadyState::Active;
242
}
243
244
void TransitionToInactive() {
245
MOZ_ASSERT(mReadyState == ReadyState::Active);
246
mReadyState = ReadyState::Inactive;
247
}
248
249
nsresult AbortCode() const {
250
AssertIsOnOwningThread();
251
return mAbortCode;
252
}
253
254
void GetCallerLocation(nsAString& aFilename, uint32_t* aLineNo,
255
uint32_t* aColumn) const;
256
257
// 'Get' prefix is to avoid name collisions with the enum
258
Mode GetMode() const {
259
AssertIsOnOwningThread();
260
return mMode;
261
}
262
263
IDBDatabase* Database() const {
264
AssertIsOnOwningThread();
265
return mDatabase;
266
}
267
268
// Only for use by ProfilerHelpers.h
269
const nsTArray<nsString>& ObjectStoreNamesInternal() const {
270
AssertIsOnOwningThread();
271
return mObjectStoreNames;
272
}
273
274
MOZ_MUST_USE RefPtr<IDBObjectStore> CreateObjectStore(
275
const indexedDB::ObjectStoreSpec& aSpec);
276
277
void DeleteObjectStore(int64_t aObjectStoreId);
278
279
void RenameObjectStore(int64_t aObjectStoreId, const nsAString& aName);
280
281
void CreateIndex(IDBObjectStore* aObjectStore,
282
const indexedDB::IndexMetadata& aMetadata);
283
284
void DeleteIndex(IDBObjectStore* aObjectStore, int64_t aIndexId);
285
286
void RenameIndex(IDBObjectStore* aObjectStore, int64_t aIndexId,
287
const nsAString& aName);
288
289
void Abort(IDBRequest* aRequest);
290
291
void Abort(nsresult aErrorCode);
292
293
int64_t LoggingSerialNumber() const {
294
AssertIsOnOwningThread();
295
296
return mLoggingSerialNumber;
297
}
298
299
nsIGlobalObject* GetParentObject() const;
300
301
void FireCompleteOrAbortEvents(nsresult aResult);
302
303
// Only for Mode::VersionChange transactions.
304
int64_t NextObjectStoreId();
305
306
// Only for Mode::VersionChange transactions.
307
int64_t NextIndexId();
308
309
void InvalidateCursorCaches();
310
void RegisterCursor(IDBCursor* aCursor);
311
void UnregisterCursor(IDBCursor* aCursor);
312
313
NS_DECL_ISUPPORTS_INHERITED
314
NS_DECL_NSIRUNNABLE
315
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, DOMEventTargetHelper)
316
317
// nsWrapperCache
318
JSObject* WrapObject(JSContext* aCx,
319
JS::Handle<JSObject*> aGivenProto) override;
320
321
// Methods bound via WebIDL.
322
IDBDatabase* Db() const { return Database(); }
323
324
IDBTransactionMode GetMode(ErrorResult& aRv) const;
325
326
DOMException* GetError() const;
327
328
MOZ_MUST_USE RefPtr<IDBObjectStore> ObjectStore(const nsAString& aName,
329
ErrorResult& aRv);
330
331
void Abort(ErrorResult& aRv);
332
333
IMPL_EVENT_HANDLER(abort)
334
IMPL_EVENT_HANDLER(complete)
335
IMPL_EVENT_HANDLER(error)
336
337
MOZ_MUST_USE RefPtr<DOMStringList> ObjectStoreNames() const;
338
339
// EventTarget
340
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
341
342
private:
343
struct CreatedFromFactoryFunction {};
344
345
public:
346
IDBTransaction(IDBDatabase* aDatabase,
347
const nsTArray<nsString>& aObjectStoreNames, Mode aMode,
348
nsString aFilename, uint32_t aLineNo, uint32_t aColumn,
349
CreatedFromFactoryFunction aDummy);
350
351
private:
352
~IDBTransaction();
353
354
void AbortInternal(nsresult aAbortCode, RefPtr<DOMException> aError);
355
356
void SendCommit();
357
358
void SendAbort(nsresult aResultCode);
359
360
void NoteActiveTransaction();
361
362
void MaybeNoteInactiveTransaction();
363
364
void OnNewRequest();
365
366
void OnRequestFinished(bool aRequestCompletedSuccessfully);
367
368
template <typename Func>
369
auto DoWithTransactionChild(const Func& aFunc) const;
370
371
bool HasTransactionChild() const;
372
};
373
374
} // namespace dom
375
} // namespace mozilla
376
377
#endif // mozilla_dom_idbtransaction_h__