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 file,
5
* You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "IDBMutableFile.h"
8
9
#include "ActorsChild.h"
10
#include "FileInfo.h"
11
#include "IDBDatabase.h"
12
#include "IDBFactory.h"
13
#include "IDBFileHandle.h"
14
#include "IDBFileRequest.h"
15
#include "IndexedDatabaseManager.h"
16
#include "MainThreadUtils.h"
17
#include "mozilla/Assertions.h"
18
#include "mozilla/ErrorResult.h"
19
#include "mozilla/dom/File.h"
20
#include "mozilla/dom/IDBMutableFileBinding.h"
21
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
22
#include "mozilla/dom/quota/FileStreams.h"
23
#include "mozilla/dom/quota/QuotaManager.h"
24
#include "mozilla/ipc/BackgroundUtils.h"
25
#include "mozilla/ipc/PBackgroundSharedTypes.h"
26
#include "nsContentUtils.h"
27
#include "nsDebug.h"
28
#include "nsError.h"
29
#include "ReportInternalError.h"
30
31
namespace mozilla {
32
namespace dom {
33
34
using namespace mozilla::dom::indexedDB;
35
using namespace mozilla::dom::quota;
36
37
IDBMutableFile::IDBMutableFile(IDBDatabase* aDatabase,
38
BackgroundMutableFileChild* aActor,
39
const nsAString& aName, const nsAString& aType)
40
: DOMEventTargetHelper(aDatabase),
41
mDatabase(aDatabase),
42
mBackgroundActor(aActor),
43
mName(aName),
44
mType(aType),
45
mInvalidated(false) {
46
MOZ_ASSERT(aDatabase);
47
aDatabase->AssertIsOnOwningThread();
48
MOZ_ASSERT(aActor);
49
50
mDatabase->NoteLiveMutableFile(this);
51
}
52
53
IDBMutableFile::~IDBMutableFile() {
54
AssertIsOnOwningThread();
55
56
mDatabase->NoteFinishedMutableFile(this);
57
58
if (mBackgroundActor) {
59
mBackgroundActor->SendDeleteMeInternal();
60
MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
61
}
62
}
63
64
#ifdef DEBUG
65
66
void IDBMutableFile::AssertIsOnOwningThread() const {
67
MOZ_ASSERT(mDatabase);
68
mDatabase->AssertIsOnOwningThread();
69
}
70
71
#endif // DEBUG
72
73
int64_t IDBMutableFile::GetFileId() const {
74
AssertIsOnOwningThread();
75
76
int64_t fileId;
77
if (!mBackgroundActor ||
78
NS_WARN_IF(!mBackgroundActor->SendGetFileId(&fileId))) {
79
return -1;
80
}
81
82
return fileId;
83
}
84
85
void IDBMutableFile::Invalidate() {
86
AssertIsOnOwningThread();
87
MOZ_ASSERT(!mInvalidated);
88
89
mInvalidated = true;
90
91
AbortFileHandles();
92
}
93
94
void IDBMutableFile::RegisterFileHandle(IDBFileHandle* aFileHandle) {
95
AssertIsOnOwningThread();
96
MOZ_ASSERT(aFileHandle);
97
aFileHandle->AssertIsOnOwningThread();
98
MOZ_ASSERT(!mFileHandles.Contains(aFileHandle));
99
100
mFileHandles.PutEntry(aFileHandle);
101
}
102
103
void IDBMutableFile::UnregisterFileHandle(IDBFileHandle* aFileHandle) {
104
AssertIsOnOwningThread();
105
MOZ_ASSERT(aFileHandle);
106
aFileHandle->AssertIsOnOwningThread();
107
MOZ_ASSERT(mFileHandles.Contains(aFileHandle));
108
109
mFileHandles.RemoveEntry(aFileHandle);
110
}
111
112
void IDBMutableFile::AbortFileHandles() {
113
AssertIsOnOwningThread();
114
115
class MOZ_STACK_CLASS Helper final {
116
public:
117
static void AbortFileHandles(
118
nsTHashtable<nsPtrHashKey<IDBFileHandle>>& aTable) {
119
if (!aTable.Count()) {
120
return;
121
}
122
123
nsTArray<RefPtr<IDBFileHandle>> fileHandlesToAbort;
124
fileHandlesToAbort.SetCapacity(aTable.Count());
125
126
for (auto iter = aTable.Iter(); !iter.Done(); iter.Next()) {
127
IDBFileHandle* fileHandle = iter.Get()->GetKey();
128
MOZ_ASSERT(fileHandle);
129
130
fileHandle->AssertIsOnOwningThread();
131
132
if (!fileHandle->IsDone()) {
133
fileHandlesToAbort.AppendElement(iter.Get()->GetKey());
134
}
135
}
136
MOZ_ASSERT(fileHandlesToAbort.Length() <= aTable.Count());
137
138
if (fileHandlesToAbort.IsEmpty()) {
139
return;
140
}
141
142
for (RefPtr<IDBFileHandle>& fileHandle : fileHandlesToAbort) {
143
MOZ_ASSERT(fileHandle);
144
145
fileHandle->Abort();
146
}
147
}
148
};
149
150
Helper::AbortFileHandles(mFileHandles);
151
}
152
153
IDBDatabase* IDBMutableFile::Database() const {
154
AssertIsOnOwningThread();
155
156
return mDatabase;
157
}
158
159
already_AddRefed<IDBFileHandle> IDBMutableFile::Open(FileMode aMode,
160
ErrorResult& aError) {
161
AssertIsOnOwningThread();
162
163
if (QuotaManager::IsShuttingDown() || mDatabase->IsClosed() || !GetOwner()) {
164
aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
165
return nullptr;
166
}
167
168
RefPtr<IDBFileHandle> fileHandle = IDBFileHandle::Create(this, aMode);
169
if (NS_WARN_IF(!fileHandle)) {
170
aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
171
return nullptr;
172
}
173
174
BackgroundFileHandleChild* actor = new BackgroundFileHandleChild(fileHandle);
175
176
MOZ_ALWAYS_TRUE(
177
mBackgroundActor->SendPBackgroundFileHandleConstructor(actor, aMode));
178
179
fileHandle->SetBackgroundActor(actor);
180
181
return fileHandle.forget();
182
}
183
184
already_AddRefed<DOMRequest> IDBMutableFile::GetFile(ErrorResult& aError) {
185
RefPtr<IDBFileHandle> fileHandle = Open(FileMode::Readonly, aError);
186
if (NS_WARN_IF(aError.Failed())) {
187
return nullptr;
188
}
189
190
FileRequestGetFileParams params;
191
192
RefPtr<IDBFileRequest> request =
193
IDBFileRequest::Create(fileHandle, /* aWrapAsDOMRequest */ true);
194
195
fileHandle->StartRequest(request, params);
196
197
return request.forget();
198
}
199
200
NS_IMPL_ADDREF_INHERITED(IDBMutableFile, DOMEventTargetHelper)
201
NS_IMPL_RELEASE_INHERITED(IDBMutableFile, DOMEventTargetHelper)
202
203
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBMutableFile)
204
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
205
206
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBMutableFile)
207
208
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBMutableFile,
209
DOMEventTargetHelper)
210
tmp->AssertIsOnOwningThread();
211
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDatabase)
212
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
213
214
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBMutableFile,
215
DOMEventTargetHelper)
216
tmp->AssertIsOnOwningThread();
217
218
// Don't unlink mDatabase!
219
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
220
221
JSObject* IDBMutableFile::WrapObject(JSContext* aCx,
222
JS::Handle<JSObject*> aGivenProto) {
223
return IDBMutableFile_Binding::Wrap(aCx, this, aGivenProto);
224
}
225
226
} // namespace dom
227
} // namespace mozilla