Coverage Report

Created: 2018-09-25 14:53

/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