/src/mozilla-central/dom/simpledb/SDBConnection.cpp
Line | Count | Source (jump to first uncovered line) |
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 file, |
5 | | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "SDBConnection.h" |
8 | | |
9 | | #include "ActorsChild.h" |
10 | | #include "jsfriendapi.h" |
11 | | #include "mozilla/ipc/BackgroundChild.h" |
12 | | #include "mozilla/ipc/BackgroundParent.h" |
13 | | #include "mozilla/ipc/BackgroundUtils.h" |
14 | | #include "mozilla/ipc/PBackgroundChild.h" |
15 | | #include "nsISDBCallbacks.h" |
16 | | #include "SDBRequest.h" |
17 | | #include "SimpleDBCommon.h" |
18 | | |
19 | | namespace mozilla { |
20 | | namespace dom { |
21 | | |
22 | | using namespace mozilla::ipc; |
23 | | |
24 | | namespace { |
25 | | |
26 | | nsresult |
27 | | GetWriteData(JSContext* aCx, |
28 | | JS::Handle<JS::Value> aValue, |
29 | | nsCString& aData) |
30 | 0 | { |
31 | 0 | if (aValue.isObject()) { |
32 | 0 | JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); |
33 | 0 |
|
34 | 0 | bool isView = false; |
35 | 0 | if (JS_IsArrayBufferObject(obj) || |
36 | 0 | (isView = JS_IsArrayBufferViewObject(obj))) { |
37 | 0 | uint8_t* data; |
38 | 0 | uint32_t length; |
39 | 0 | bool unused; |
40 | 0 | if (isView) { |
41 | 0 | JS_GetObjectAsArrayBufferView(obj, &length, &unused, &data); |
42 | 0 | } else { |
43 | 0 | JS_GetObjectAsArrayBuffer(obj, &length, &data); |
44 | 0 | } |
45 | 0 |
|
46 | 0 | if (NS_WARN_IF(!aData.Assign(reinterpret_cast<char*>(data), |
47 | 0 | length, |
48 | 0 | fallible_t()))) { |
49 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
50 | 0 | } |
51 | 0 | |
52 | 0 | return NS_OK; |
53 | 0 | } |
54 | 0 | } |
55 | 0 |
|
56 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
57 | 0 | } |
58 | | |
59 | | } // namespace |
60 | | |
61 | | SDBConnection::SDBConnection() |
62 | | : mBackgroundActor(nullptr) |
63 | | , mRunningRequest(false) |
64 | | , mOpen(false) |
65 | | , mAllowedToClose(false) |
66 | 0 | { |
67 | 0 | AssertIsOnOwningThread(); |
68 | 0 | } |
69 | | |
70 | | SDBConnection::~SDBConnection() |
71 | 0 | { |
72 | 0 | AssertIsOnOwningThread(); |
73 | 0 |
|
74 | 0 | if (mBackgroundActor) { |
75 | 0 | mBackgroundActor->SendDeleteMeInternal(); |
76 | 0 | MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!"); |
77 | 0 | } |
78 | 0 | } |
79 | | |
80 | | // static |
81 | | nsresult |
82 | | SDBConnection::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) |
83 | 0 | { |
84 | 0 | MOZ_ASSERT(aResult); |
85 | 0 |
|
86 | 0 | if (NS_WARN_IF(!Preferences::GetBool(kPrefSimpleDBEnabled, false))) { |
87 | 0 | return NS_ERROR_NOT_AVAILABLE; |
88 | 0 | } |
89 | 0 | |
90 | 0 | if (aOuter) { |
91 | 0 | return NS_ERROR_NO_AGGREGATION; |
92 | 0 | } |
93 | 0 | |
94 | 0 | RefPtr<SDBConnection> connection = new SDBConnection(); |
95 | 0 |
|
96 | 0 | nsresult rv = connection->QueryInterface(aIID, aResult); |
97 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
98 | 0 | return rv; |
99 | 0 | } |
100 | 0 | |
101 | 0 | return NS_OK; |
102 | 0 | } |
103 | | |
104 | | void |
105 | | SDBConnection::ClearBackgroundActor() |
106 | 0 | { |
107 | 0 | AssertIsOnOwningThread(); |
108 | 0 |
|
109 | 0 | mBackgroundActor = nullptr; |
110 | 0 | } |
111 | | |
112 | | void |
113 | | SDBConnection::OnNewRequest() |
114 | 0 | { |
115 | 0 | AssertIsOnOwningThread(); |
116 | 0 | MOZ_ASSERT(!mRunningRequest); |
117 | 0 |
|
118 | 0 | mRunningRequest = true; |
119 | 0 | } |
120 | | |
121 | | void |
122 | | SDBConnection::OnRequestFinished() |
123 | 0 | { |
124 | 0 | AssertIsOnOwningThread(); |
125 | 0 | MOZ_ASSERT(mRunningRequest); |
126 | 0 |
|
127 | 0 | mRunningRequest = false; |
128 | 0 | } |
129 | | |
130 | | void |
131 | | SDBConnection::OnOpen() |
132 | 0 | { |
133 | 0 | AssertIsOnOwningThread(); |
134 | 0 | MOZ_ASSERT(!mOpen); |
135 | 0 |
|
136 | 0 | mOpen = true; |
137 | 0 | } |
138 | | |
139 | | void |
140 | | SDBConnection::OnClose(bool aAbnormal) |
141 | 0 | { |
142 | 0 | AssertIsOnOwningThread(); |
143 | 0 | MOZ_ASSERT(mOpen); |
144 | 0 |
|
145 | 0 | mOpen = false; |
146 | 0 |
|
147 | 0 | if (aAbnormal) { |
148 | 0 | MOZ_ASSERT(mAllowedToClose); |
149 | 0 |
|
150 | 0 | if (mCloseCallback) { |
151 | 0 | mCloseCallback->OnClose(this); |
152 | 0 | } |
153 | 0 | } |
154 | 0 | } |
155 | | |
156 | | void |
157 | | SDBConnection::AllowToClose() |
158 | 0 | { |
159 | 0 | AssertIsOnOwningThread(); |
160 | 0 |
|
161 | 0 | mAllowedToClose = true; |
162 | 0 | } |
163 | | |
164 | | nsresult |
165 | | SDBConnection::CheckState() |
166 | 0 | { |
167 | 0 | AssertIsOnOwningThread(); |
168 | 0 |
|
169 | 0 | if (mAllowedToClose) { |
170 | 0 | return NS_ERROR_ABORT; |
171 | 0 | } |
172 | 0 | |
173 | 0 | if (mRunningRequest) { |
174 | 0 | return NS_ERROR_NOT_AVAILABLE; |
175 | 0 | } |
176 | 0 | |
177 | 0 | return NS_OK; |
178 | 0 | } |
179 | | |
180 | | nsresult |
181 | | SDBConnection::EnsureBackgroundActor() |
182 | 0 | { |
183 | 0 | AssertIsOnOwningThread(); |
184 | 0 |
|
185 | 0 | if (mBackgroundActor) { |
186 | 0 | return NS_OK; |
187 | 0 | } |
188 | 0 | |
189 | 0 | PBackgroundChild* backgroundActor = |
190 | 0 | BackgroundChild::GetOrCreateForCurrentThread(); |
191 | 0 | if (NS_WARN_IF(!backgroundActor)) { |
192 | 0 | return NS_ERROR_FAILURE; |
193 | 0 | } |
194 | 0 | |
195 | 0 | SDBConnectionChild* actor = new SDBConnectionChild(this); |
196 | 0 |
|
197 | 0 | mBackgroundActor = |
198 | 0 | static_cast<SDBConnectionChild*>( |
199 | 0 | backgroundActor->SendPBackgroundSDBConnectionConstructor( |
200 | 0 | actor, |
201 | 0 | *mPrincipalInfo)); |
202 | 0 | if (NS_WARN_IF(!mBackgroundActor)) { |
203 | 0 | return NS_ERROR_FAILURE; |
204 | 0 | } |
205 | 0 | |
206 | 0 | return NS_OK; |
207 | 0 | } |
208 | | |
209 | | nsresult |
210 | | SDBConnection::InitiateRequest(SDBRequest* aRequest, |
211 | | const SDBRequestParams& aParams) |
212 | 0 | { |
213 | 0 | AssertIsOnOwningThread(); |
214 | 0 | MOZ_ASSERT(aRequest); |
215 | 0 | MOZ_ASSERT(mBackgroundActor); |
216 | 0 |
|
217 | 0 | auto actor = new SDBRequestChild(aRequest); |
218 | 0 |
|
219 | 0 | if (!mBackgroundActor->SendPBackgroundSDBRequestConstructor(actor, aParams)) { |
220 | 0 | return NS_ERROR_FAILURE; |
221 | 0 | } |
222 | 0 | |
223 | 0 | // Balanced in SDBRequestChild::Recv__delete__(). |
224 | 0 | OnNewRequest(); |
225 | 0 |
|
226 | 0 | return NS_OK; |
227 | 0 | } |
228 | | |
229 | | NS_IMPL_ISUPPORTS(SDBConnection, nsISDBConnection) |
230 | | |
231 | | NS_IMETHODIMP |
232 | | SDBConnection::Init(nsIPrincipal *aPrincipal) |
233 | 0 | { |
234 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
235 | 0 | MOZ_ASSERT(aPrincipal); |
236 | 0 |
|
237 | 0 | nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo()); |
238 | 0 | nsresult rv = PrincipalToPrincipalInfo(aPrincipal, principalInfo); |
239 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
240 | 0 | return rv; |
241 | 0 | } |
242 | 0 | |
243 | 0 | if (principalInfo->type() != PrincipalInfo::TContentPrincipalInfo && |
244 | 0 | principalInfo->type() != PrincipalInfo::TSystemPrincipalInfo) { |
245 | 0 | NS_WARNING("Simpledb not allowed for this principal!"); |
246 | 0 | return NS_ERROR_INVALID_ARG; |
247 | 0 | } |
248 | 0 |
|
249 | 0 | mPrincipalInfo = std::move(principalInfo); |
250 | 0 |
|
251 | 0 | return NS_OK; |
252 | 0 | } |
253 | | |
254 | | NS_IMETHODIMP |
255 | | SDBConnection::Open(const nsAString& aName, nsISDBRequest** _retval) |
256 | 0 | { |
257 | 0 | AssertIsOnOwningThread(); |
258 | 0 |
|
259 | 0 | nsresult rv = CheckState(); |
260 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
261 | 0 | return rv; |
262 | 0 | } |
263 | 0 | |
264 | 0 | if (mOpen) { |
265 | 0 | return NS_ERROR_ALREADY_INITIALIZED; |
266 | 0 | } |
267 | 0 | |
268 | 0 | SDBRequestOpenParams params; |
269 | 0 | params.name() = aName; |
270 | 0 |
|
271 | 0 | RefPtr<SDBRequest> request = new SDBRequest(this); |
272 | 0 |
|
273 | 0 | rv = EnsureBackgroundActor(); |
274 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
275 | 0 | return rv; |
276 | 0 | } |
277 | 0 | |
278 | 0 | rv = InitiateRequest(request, params); |
279 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
280 | 0 | return rv; |
281 | 0 | } |
282 | 0 | |
283 | 0 | request.forget(_retval); |
284 | 0 | return NS_OK; |
285 | 0 | } |
286 | | |
287 | | NS_IMETHODIMP |
288 | | SDBConnection::Seek(uint64_t aOffset, nsISDBRequest** _retval) |
289 | 0 | { |
290 | 0 | AssertIsOnOwningThread(); |
291 | 0 |
|
292 | 0 | nsresult rv = CheckState(); |
293 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
294 | 0 | return rv; |
295 | 0 | } |
296 | 0 | |
297 | 0 | if (!mOpen) { |
298 | 0 | return NS_BASE_STREAM_CLOSED; |
299 | 0 | } |
300 | 0 | |
301 | 0 | SDBRequestSeekParams params; |
302 | 0 | params.offset() = aOffset; |
303 | 0 |
|
304 | 0 | RefPtr<SDBRequest> request = new SDBRequest(this); |
305 | 0 |
|
306 | 0 | rv = InitiateRequest(request, params); |
307 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
308 | 0 | return rv; |
309 | 0 | } |
310 | 0 | |
311 | 0 | request.forget(_retval); |
312 | 0 | return NS_OK; |
313 | 0 | } |
314 | | |
315 | | NS_IMETHODIMP |
316 | | SDBConnection::Read(uint64_t aSize, nsISDBRequest** _retval) |
317 | 0 | { |
318 | 0 | AssertIsOnOwningThread(); |
319 | 0 |
|
320 | 0 | nsresult rv = CheckState(); |
321 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
322 | 0 | return rv; |
323 | 0 | } |
324 | 0 | |
325 | 0 | if (!mOpen) { |
326 | 0 | return NS_BASE_STREAM_CLOSED; |
327 | 0 | } |
328 | 0 | |
329 | 0 | SDBRequestReadParams params; |
330 | 0 | params.size() = aSize; |
331 | 0 |
|
332 | 0 | RefPtr<SDBRequest> request = new SDBRequest(this); |
333 | 0 |
|
334 | 0 | rv = InitiateRequest(request, params); |
335 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
336 | 0 | return rv; |
337 | 0 | } |
338 | 0 | |
339 | 0 | request.forget(_retval); |
340 | 0 | return NS_OK; |
341 | 0 | } |
342 | | |
343 | | NS_IMETHODIMP |
344 | | SDBConnection::Write(JS::HandleValue aValue, |
345 | | JSContext* aCx, |
346 | | nsISDBRequest** _retval) |
347 | 0 | { |
348 | 0 | AssertIsOnOwningThread(); |
349 | 0 |
|
350 | 0 | nsresult rv = CheckState(); |
351 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
352 | 0 | return rv; |
353 | 0 | } |
354 | 0 | |
355 | 0 | if (!mOpen) { |
356 | 0 | return NS_BASE_STREAM_CLOSED; |
357 | 0 | } |
358 | 0 | |
359 | 0 | JS::Rooted<JS::Value> value(aCx, aValue); |
360 | 0 |
|
361 | 0 | nsCString data; |
362 | 0 | rv = GetWriteData(aCx, value, data); |
363 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
364 | 0 | return rv; |
365 | 0 | } |
366 | 0 | |
367 | 0 | SDBRequestWriteParams params; |
368 | 0 | params.data() = data; |
369 | 0 |
|
370 | 0 | RefPtr<SDBRequest> request = new SDBRequest(this); |
371 | 0 |
|
372 | 0 | rv = InitiateRequest(request, params); |
373 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
374 | 0 | return rv; |
375 | 0 | } |
376 | 0 | |
377 | 0 | request.forget(_retval); |
378 | 0 | return NS_OK; |
379 | 0 | } |
380 | | |
381 | | NS_IMETHODIMP |
382 | | SDBConnection::Close(nsISDBRequest** _retval) |
383 | 0 | { |
384 | 0 | AssertIsOnOwningThread(); |
385 | 0 |
|
386 | 0 | nsresult rv = CheckState(); |
387 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
388 | 0 | return rv; |
389 | 0 | } |
390 | 0 | |
391 | 0 | if (!mOpen) { |
392 | 0 | return NS_BASE_STREAM_CLOSED; |
393 | 0 | } |
394 | 0 | |
395 | 0 | SDBRequestCloseParams params; |
396 | 0 |
|
397 | 0 | RefPtr<SDBRequest> request = new SDBRequest(this); |
398 | 0 |
|
399 | 0 | rv = InitiateRequest(request, params); |
400 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
401 | 0 | return rv; |
402 | 0 | } |
403 | 0 | |
404 | 0 | request.forget(_retval); |
405 | 0 | return NS_OK; |
406 | 0 | } |
407 | | |
408 | | NS_IMETHODIMP |
409 | | SDBConnection::GetCloseCallback(nsISDBCloseCallback** aCloseCallback) |
410 | 0 | { |
411 | 0 | AssertIsOnOwningThread(); |
412 | 0 | MOZ_ASSERT(aCloseCallback); |
413 | 0 |
|
414 | 0 | NS_IF_ADDREF(*aCloseCallback = mCloseCallback); |
415 | 0 | return NS_OK; |
416 | 0 | } |
417 | | |
418 | | NS_IMETHODIMP |
419 | | SDBConnection::SetCloseCallback(nsISDBCloseCallback* aCloseCallback) |
420 | 0 | { |
421 | 0 | AssertIsOnOwningThread(); |
422 | 0 |
|
423 | 0 | mCloseCallback = aCloseCallback; |
424 | 0 | return NS_OK; |
425 | 0 | } |
426 | | |
427 | | } // namespace dom |
428 | | } // namespace mozilla |