Bug 1769952 - Fix running raptor on a Win10-64 VM r=sparky
[gecko.git] / dom / simpledb / SDBConnection.cpp
bloba035d1631ece33359cba4bd22d2af2b405b5c377
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/. */
7 #include "SDBConnection.h"
9 // Local includes
10 #include "ActorsChild.h"
11 #include "SDBRequest.h"
12 #include "SimpleDBCommon.h"
14 // Global includes
15 #include <stdint.h>
16 #include <utility>
17 #include "MainThreadUtils.h"
18 #include "js/ArrayBuffer.h"
19 #include "js/RootingAPI.h"
20 #include "js/TypeDecls.h"
21 #include "js/experimental/TypedData.h"
22 #include "mozilla/Assertions.h"
23 #include "mozilla/MacroForEach.h"
24 #include "mozilla/Maybe.h"
25 #include "mozilla/Preferences.h"
26 #include "mozilla/RefPtr.h"
27 #include "mozilla/Variant.h"
28 #include "mozilla/dom/PBackgroundSDBConnection.h"
29 #include "mozilla/dom/quota/QuotaManager.h"
30 #include "mozilla/fallible.h"
31 #include "mozilla/ipc/BackgroundChild.h"
32 #include "mozilla/ipc/BackgroundUtils.h"
33 #include "mozilla/ipc/PBackgroundChild.h"
34 #include "mozilla/ipc/PBackgroundSharedTypes.h"
35 #include "nsDebug.h"
36 #include "nsError.h"
37 #include "nsISDBCallbacks.h"
38 #include "nsISupportsUtils.h"
39 #include "nsStringFwd.h"
40 #include "nscore.h"
42 namespace mozilla::dom {
44 using namespace mozilla::ipc;
46 namespace {
48 nsresult GetWriteData(JSContext* aCx, JS::Handle<JS::Value> aValue,
49 nsCString& aData) {
50 if (aValue.isObject()) {
51 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
53 bool isView = false;
54 if (JS::IsArrayBufferObject(obj) ||
55 (isView = JS_IsArrayBufferViewObject(obj))) {
56 uint8_t* data;
57 size_t length;
58 bool unused;
59 if (isView) {
60 JS_GetObjectAsArrayBufferView(obj, &length, &unused, &data);
61 } else {
62 JS::GetObjectAsArrayBuffer(obj, &length, &data);
65 // Throw for large buffers to prevent truncation.
66 if (length > INT32_MAX) {
67 return NS_ERROR_ILLEGAL_VALUE;
70 if (NS_WARN_IF(!aData.Assign(reinterpret_cast<char*>(data), length,
71 fallible_t()))) {
72 return NS_ERROR_OUT_OF_MEMORY;
75 return NS_OK;
79 return NS_ERROR_NOT_IMPLEMENTED;
82 } // namespace
84 SDBConnection::SDBConnection()
85 : mBackgroundActor(nullptr),
86 mPersistenceType(quota::PERSISTENCE_TYPE_INVALID),
87 mRunningRequest(false),
88 mOpen(false),
89 mAllowedToClose(false) {
90 AssertIsOnOwningThread();
93 SDBConnection::~SDBConnection() {
94 AssertIsOnOwningThread();
96 if (mBackgroundActor) {
97 mBackgroundActor->SendDeleteMeInternal();
98 MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
102 // static
103 nsresult SDBConnection::Create(REFNSIID aIID, void** aResult) {
104 MOZ_ASSERT(aResult);
106 if (NS_WARN_IF(!Preferences::GetBool(kPrefSimpleDBEnabled, false))) {
107 return NS_ERROR_NOT_AVAILABLE;
110 RefPtr<SDBConnection> connection = new SDBConnection();
112 nsresult rv = connection->QueryInterface(aIID, aResult);
113 if (NS_WARN_IF(NS_FAILED(rv))) {
114 return rv;
117 return NS_OK;
120 void SDBConnection::ClearBackgroundActor() {
121 AssertIsOnOwningThread();
123 mBackgroundActor = nullptr;
126 void SDBConnection::OnNewRequest() {
127 AssertIsOnOwningThread();
128 MOZ_ASSERT(!mRunningRequest);
130 mRunningRequest = true;
133 void SDBConnection::OnRequestFinished() {
134 AssertIsOnOwningThread();
135 MOZ_ASSERT(mRunningRequest);
137 mRunningRequest = false;
140 void SDBConnection::OnOpen() {
141 AssertIsOnOwningThread();
142 MOZ_ASSERT(!mOpen);
144 mOpen = true;
147 void SDBConnection::OnClose(bool aAbnormal) {
148 AssertIsOnOwningThread();
149 MOZ_ASSERT(mOpen);
151 mOpen = false;
153 if (aAbnormal) {
154 MOZ_ASSERT(mAllowedToClose);
156 if (mCloseCallback) {
157 mCloseCallback->OnClose(this);
162 void SDBConnection::AllowToClose() {
163 AssertIsOnOwningThread();
165 mAllowedToClose = true;
168 nsresult SDBConnection::CheckState() {
169 AssertIsOnOwningThread();
171 if (mAllowedToClose) {
172 return NS_ERROR_ABORT;
175 if (mRunningRequest) {
176 return NS_ERROR_NOT_AVAILABLE;
179 return NS_OK;
182 nsresult SDBConnection::EnsureBackgroundActor() {
183 AssertIsOnOwningThread();
185 if (mBackgroundActor) {
186 return NS_OK;
189 PBackgroundChild* backgroundActor =
190 BackgroundChild::GetOrCreateForCurrentThread();
191 if (NS_WARN_IF(!backgroundActor)) {
192 return NS_ERROR_FAILURE;
195 SDBConnectionChild* actor = new SDBConnectionChild(this);
197 mBackgroundActor = static_cast<SDBConnectionChild*>(
198 backgroundActor->SendPBackgroundSDBConnectionConstructor(
199 actor, mPersistenceType, *mPrincipalInfo));
200 if (NS_WARN_IF(!mBackgroundActor)) {
201 return NS_ERROR_FAILURE;
204 return NS_OK;
207 nsresult SDBConnection::InitiateRequest(SDBRequest* aRequest,
208 const SDBRequestParams& aParams) {
209 AssertIsOnOwningThread();
210 MOZ_ASSERT(aRequest);
211 MOZ_ASSERT(mBackgroundActor);
213 auto actor = new SDBRequestChild(aRequest);
215 if (!mBackgroundActor->SendPBackgroundSDBRequestConstructor(actor, aParams)) {
216 return NS_ERROR_FAILURE;
219 // Balanced in SDBRequestChild::Recv__delete__().
220 OnNewRequest();
222 return NS_OK;
225 NS_IMPL_ISUPPORTS(SDBConnection, nsISDBConnection)
227 NS_IMETHODIMP
228 SDBConnection::Init(nsIPrincipal* aPrincipal,
229 const nsACString& aPersistenceType) {
230 MOZ_ASSERT(NS_IsMainThread());
231 MOZ_ASSERT(aPrincipal);
233 UniquePtr<PrincipalInfo> principalInfo(new PrincipalInfo());
234 nsresult rv = PrincipalToPrincipalInfo(aPrincipal, principalInfo.get());
235 if (NS_WARN_IF(NS_FAILED(rv))) {
236 return rv;
239 if (principalInfo->type() != PrincipalInfo::TContentPrincipalInfo &&
240 principalInfo->type() != PrincipalInfo::TSystemPrincipalInfo) {
241 NS_WARNING("Simpledb not allowed for this principal!");
242 return NS_ERROR_INVALID_ARG;
245 if (NS_WARN_IF(!quota::QuotaManager::IsPrincipalInfoValid(*principalInfo))) {
246 return NS_ERROR_INVALID_ARG;
249 PersistenceType persistenceType;
250 if (aPersistenceType.IsVoid()) {
251 persistenceType = quota::PERSISTENCE_TYPE_DEFAULT;
252 } else {
253 const auto maybePersistenceType =
254 quota::PersistenceTypeFromString(aPersistenceType, fallible);
255 if (NS_WARN_IF(maybePersistenceType.isNothing())) {
256 return NS_ERROR_INVALID_ARG;
259 persistenceType = maybePersistenceType.value();
262 mPrincipalInfo = std::move(principalInfo);
263 mPersistenceType = persistenceType;
265 return NS_OK;
268 NS_IMETHODIMP
269 SDBConnection::Open(const nsAString& aName, nsISDBRequest** _retval) {
270 AssertIsOnOwningThread();
272 nsresult rv = CheckState();
273 if (NS_WARN_IF(NS_FAILED(rv))) {
274 return rv;
277 if (mOpen) {
278 return NS_ERROR_ALREADY_INITIALIZED;
281 SDBRequestOpenParams params;
282 params.name() = aName;
284 RefPtr<SDBRequest> request = new SDBRequest(this);
286 rv = EnsureBackgroundActor();
287 if (NS_WARN_IF(NS_FAILED(rv))) {
288 return rv;
291 rv = InitiateRequest(request, params);
292 if (NS_WARN_IF(NS_FAILED(rv))) {
293 return rv;
296 request.forget(_retval);
297 return NS_OK;
300 NS_IMETHODIMP
301 SDBConnection::Seek(uint64_t aOffset, nsISDBRequest** _retval) {
302 AssertIsOnOwningThread();
304 nsresult rv = CheckState();
305 if (NS_WARN_IF(NS_FAILED(rv))) {
306 return rv;
309 if (!mOpen) {
310 return NS_BASE_STREAM_CLOSED;
313 SDBRequestSeekParams params;
314 params.offset() = aOffset;
316 RefPtr<SDBRequest> request = new SDBRequest(this);
318 rv = InitiateRequest(request, params);
319 if (NS_WARN_IF(NS_FAILED(rv))) {
320 return rv;
323 request.forget(_retval);
324 return NS_OK;
327 NS_IMETHODIMP
328 SDBConnection::Read(uint64_t aSize, nsISDBRequest** _retval) {
329 AssertIsOnOwningThread();
331 nsresult rv = CheckState();
332 if (NS_WARN_IF(NS_FAILED(rv))) {
333 return rv;
336 if (!mOpen) {
337 return NS_BASE_STREAM_CLOSED;
340 SDBRequestReadParams params;
341 params.size() = aSize;
343 RefPtr<SDBRequest> request = new SDBRequest(this);
345 rv = InitiateRequest(request, params);
346 if (NS_WARN_IF(NS_FAILED(rv))) {
347 return rv;
350 request.forget(_retval);
351 return NS_OK;
354 NS_IMETHODIMP
355 SDBConnection::Write(JS::HandleValue aValue, JSContext* aCx,
356 nsISDBRequest** _retval) {
357 AssertIsOnOwningThread();
359 nsresult rv = CheckState();
360 if (NS_WARN_IF(NS_FAILED(rv))) {
361 return rv;
364 if (!mOpen) {
365 return NS_BASE_STREAM_CLOSED;
368 JS::Rooted<JS::Value> value(aCx, aValue);
370 nsCString data;
371 rv = GetWriteData(aCx, value, data);
372 if (NS_WARN_IF(NS_FAILED(rv))) {
373 return rv;
376 SDBRequestWriteParams params;
377 params.data() = data;
379 RefPtr<SDBRequest> request = new SDBRequest(this);
381 rv = InitiateRequest(request, params);
382 if (NS_WARN_IF(NS_FAILED(rv))) {
383 return rv;
386 request.forget(_retval);
387 return NS_OK;
390 NS_IMETHODIMP
391 SDBConnection::Close(nsISDBRequest** _retval) {
392 AssertIsOnOwningThread();
394 nsresult rv = CheckState();
395 if (NS_WARN_IF(NS_FAILED(rv))) {
396 return rv;
399 if (!mOpen) {
400 return NS_BASE_STREAM_CLOSED;
403 SDBRequestCloseParams params;
405 RefPtr<SDBRequest> request = new SDBRequest(this);
407 rv = InitiateRequest(request, params);
408 if (NS_WARN_IF(NS_FAILED(rv))) {
409 return rv;
412 request.forget(_retval);
413 return NS_OK;
416 NS_IMETHODIMP
417 SDBConnection::GetCloseCallback(nsISDBCloseCallback** aCloseCallback) {
418 AssertIsOnOwningThread();
419 MOZ_ASSERT(aCloseCallback);
421 NS_IF_ADDREF(*aCloseCallback = mCloseCallback);
422 return NS_OK;
425 NS_IMETHODIMP
426 SDBConnection::SetCloseCallback(nsISDBCloseCallback* aCloseCallback) {
427 AssertIsOnOwningThread();
429 mCloseCallback = aCloseCallback;
430 return NS_OK;
433 } // namespace mozilla::dom