Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/quota/QuotaManagerService.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=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 "QuotaManagerService.h"
8
9
#include "ActorsChild.h"
10
#include "mozilla/BasePrincipal.h"
11
#include "mozilla/ClearOnShutdown.h"
12
#include "mozilla/Hal.h"
13
#include "mozilla/Preferences.h"
14
#include "mozilla/Unused.h"
15
#include "mozilla/ipc/BackgroundChild.h"
16
#include "mozilla/ipc/BackgroundParent.h"
17
#include "mozilla/ipc/BackgroundUtils.h"
18
#include "mozilla/ipc/PBackgroundChild.h"
19
#include "nsIIdleService.h"
20
#include "nsIObserverService.h"
21
#include "nsIScriptSecurityManager.h"
22
#include "nsXULAppAPI.h"
23
#include "QuotaManager.h"
24
#include "QuotaRequests.h"
25
26
0
#define PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID "profile-before-change-qm"
27
28
namespace mozilla {
29
namespace dom {
30
namespace quota {
31
32
using namespace mozilla::ipc;
33
34
namespace {
35
36
// Preference that is used to enable testing features.
37
const char kTestingPref[] = "dom.quotaManager.testing";
38
39
const char kIdleServiceContractId[] = "@mozilla.org/widget/idleservice;1";
40
41
// The number of seconds we will wait after receiving the idle-daily
42
// notification before beginning maintenance.
43
const uint32_t kIdleObserverTimeSec = 1;
44
45
mozilla::StaticRefPtr<QuotaManagerService> gQuotaManagerService;
46
47
mozilla::Atomic<bool> gInitialized(false);
48
mozilla::Atomic<bool> gClosed(false);
49
mozilla::Atomic<bool> gTestingMode(false);
50
51
void
52
TestingPrefChangedCallback(const char* aPrefName,
53
                           void* aClosure)
54
0
{
55
0
  MOZ_ASSERT(NS_IsMainThread());
56
0
  MOZ_ASSERT(!strcmp(aPrefName, kTestingPref));
57
0
  MOZ_ASSERT(!aClosure);
58
0
59
0
  gTestingMode = Preferences::GetBool(aPrefName);
60
0
}
61
62
nsresult
63
CheckedPrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
64
                                PrincipalInfo& aPrincipalInfo)
65
0
{
66
0
  MOZ_ASSERT(aPrincipal);
67
0
68
0
  nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &aPrincipalInfo);
69
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
70
0
    return rv;
71
0
  }
72
0
73
0
  if (aPrincipalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
74
0
      aPrincipalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
75
0
    return NS_ERROR_UNEXPECTED;
76
0
  }
77
0
78
0
  return NS_OK;
79
0
}
80
81
class AbortOperationsRunnable final
82
  : public Runnable
83
{
84
  ContentParentId mContentParentId;
85
86
public:
87
  explicit AbortOperationsRunnable(ContentParentId aContentParentId)
88
    : Runnable("dom::quota::AbortOperationsRunnable")
89
    , mContentParentId(aContentParentId)
90
0
  { }
91
92
private:
93
  NS_DECL_NSIRUNNABLE
94
};
95
96
} // namespace
97
98
class QuotaManagerService::PendingRequestInfo
99
{
100
protected:
101
  RefPtr<RequestBase> mRequest;
102
103
public:
104
  explicit PendingRequestInfo(RequestBase* aRequest)
105
    : mRequest(aRequest)
106
0
  { }
107
108
  virtual ~PendingRequestInfo()
109
0
  { }
110
111
  RequestBase*
112
  GetRequest() const
113
0
  {
114
0
    return mRequest;
115
0
  }
116
117
  virtual nsresult
118
  InitiateRequest(QuotaChild* aActor) = 0;
119
};
120
121
class QuotaManagerService::UsageRequestInfo
122
  : public PendingRequestInfo
123
{
124
  UsageRequestParams mParams;
125
126
public:
127
  UsageRequestInfo(UsageRequest* aRequest,
128
                   const UsageRequestParams& aParams)
129
    : PendingRequestInfo(aRequest)
130
    , mParams(aParams)
131
0
  {
132
0
    MOZ_ASSERT(aRequest);
133
0
    MOZ_ASSERT(aParams.type() != UsageRequestParams::T__None);
134
0
  }
135
136
  virtual nsresult
137
  InitiateRequest(QuotaChild* aActor) override;
138
};
139
140
class QuotaManagerService::RequestInfo
141
  : public PendingRequestInfo
142
{
143
  RequestParams mParams;
144
145
public:
146
  RequestInfo(Request* aRequest,
147
              const RequestParams& aParams)
148
    : PendingRequestInfo(aRequest)
149
    , mParams(aParams)
150
0
  {
151
0
    MOZ_ASSERT(aRequest);
152
0
    MOZ_ASSERT(aParams.type() != RequestParams::T__None);
153
0
  }
154
155
  virtual nsresult
156
  InitiateRequest(QuotaChild* aActor) override;
157
};
158
159
class QuotaManagerService::IdleMaintenanceInfo
160
  : public PendingRequestInfo
161
{
162
  const bool mStart;
163
164
public:
165
  explicit IdleMaintenanceInfo(bool aStart)
166
    : PendingRequestInfo(nullptr)
167
    , mStart(aStart)
168
0
  { }
169
170
  virtual nsresult
171
  InitiateRequest(QuotaChild* aActor) override;
172
};
173
174
QuotaManagerService::QuotaManagerService()
175
  : mBackgroundActor(nullptr)
176
  , mBackgroundActorFailed(false)
177
  , mIdleObserverRegistered(false)
178
0
{
179
0
  MOZ_ASSERT(NS_IsMainThread());
180
0
}
181
182
QuotaManagerService::~QuotaManagerService()
183
0
{
184
0
  MOZ_ASSERT(NS_IsMainThread());
185
0
  MOZ_ASSERT(!mIdleObserverRegistered);
186
0
}
187
188
// static
189
QuotaManagerService*
190
QuotaManagerService::GetOrCreate()
191
0
{
192
0
  MOZ_ASSERT(NS_IsMainThread());
193
0
194
0
  if (gClosed) {
195
0
    MOZ_ASSERT(false, "Calling GetOrCreate() after shutdown!");
196
0
    return nullptr;
197
0
  }
198
0
199
0
  if (!gQuotaManagerService) {
200
0
    RefPtr<QuotaManagerService> instance(new QuotaManagerService());
201
0
202
0
    nsresult rv = instance->Init();
203
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
204
0
      return nullptr;
205
0
    }
206
0
207
0
    if (gInitialized.exchange(true)) {
208
0
      MOZ_ASSERT(false, "Initialized more than once?!");
209
0
    }
210
0
211
0
    gQuotaManagerService = instance;
212
0
213
0
    ClearOnShutdown(&gQuotaManagerService);
214
0
  }
215
0
216
0
  return gQuotaManagerService;
217
0
}
218
219
// static
220
QuotaManagerService*
221
QuotaManagerService::Get()
222
0
{
223
0
  // Does not return an owning reference.
224
0
  return gQuotaManagerService;
225
0
}
226
227
// static
228
already_AddRefed<QuotaManagerService>
229
QuotaManagerService::FactoryCreate()
230
0
{
231
0
  RefPtr<QuotaManagerService> quotaManagerService = GetOrCreate();
232
0
  return quotaManagerService.forget();
233
0
}
234
235
void
236
QuotaManagerService::ClearBackgroundActor()
237
0
{
238
0
  MOZ_ASSERT(NS_IsMainThread());
239
0
240
0
  mBackgroundActor = nullptr;
241
0
}
242
243
void
244
QuotaManagerService::NoteLiveManager(QuotaManager* aManager)
245
0
{
246
0
  MOZ_ASSERT(XRE_IsParentProcess());
247
0
  MOZ_ASSERT(NS_IsMainThread());
248
0
  MOZ_ASSERT(aManager);
249
0
250
0
  mBackgroundThread = aManager->OwningThread();
251
0
}
252
253
void
254
QuotaManagerService::NoteShuttingDownManager()
255
0
{
256
0
  MOZ_ASSERT(XRE_IsParentProcess());
257
0
  MOZ_ASSERT(NS_IsMainThread());
258
0
259
0
  mBackgroundThread = nullptr;
260
0
}
261
262
void
263
QuotaManagerService::AbortOperationsForProcess(ContentParentId aContentParentId)
264
0
{
265
0
  MOZ_ASSERT(XRE_IsParentProcess());
266
0
  MOZ_ASSERT(NS_IsMainThread());
267
0
268
0
  if (!mBackgroundThread) {
269
0
    return;
270
0
  }
271
0
272
0
  RefPtr<AbortOperationsRunnable> runnable =
273
0
    new AbortOperationsRunnable(aContentParentId);
274
0
275
0
  MOZ_ALWAYS_SUCCEEDS(
276
0
    mBackgroundThread->Dispatch(runnable, NS_DISPATCH_NORMAL));
277
0
}
278
279
nsresult
280
QuotaManagerService::Init()
281
0
{
282
0
  MOZ_ASSERT(NS_IsMainThread());
283
0
284
0
  if (XRE_IsParentProcess()) {
285
0
    nsCOMPtr<nsIObserverService> observerService =
286
0
      mozilla::services::GetObserverService();
287
0
    if (NS_WARN_IF(!observerService)) {
288
0
      return NS_ERROR_FAILURE;
289
0
    }
290
0
291
0
    nsresult rv =
292
0
      observerService->AddObserver(this,
293
0
                                   PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID,
294
0
                                   false);
295
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
296
0
      return rv;
297
0
    }
298
0
  }
299
0
300
0
  Preferences::RegisterCallbackAndCall(TestingPrefChangedCallback,
301
0
                                       kTestingPref);
302
0
303
0
  return NS_OK;
304
0
}
305
306
void
307
QuotaManagerService::Destroy()
308
0
{
309
0
  // Setting the closed flag prevents the service from being recreated.
310
0
  // Don't set it though if there's no real instance created.
311
0
  if (gInitialized && gClosed.exchange(true)) {
312
0
    MOZ_ASSERT(false, "Shutdown more than once?!");
313
0
  }
314
0
315
0
  Preferences::UnregisterCallback(TestingPrefChangedCallback, kTestingPref);
316
0
317
0
  delete this;
318
0
}
319
320
nsresult
321
QuotaManagerService::InitiateRequest(nsAutoPtr<PendingRequestInfo>& aInfo)
322
0
{
323
0
  // Nothing can be done here if we have previously failed to create a
324
0
  // background actor.
325
0
  if (mBackgroundActorFailed) {
326
0
    return NS_ERROR_FAILURE;
327
0
  }
328
0
329
0
  if (!mBackgroundActor) {
330
0
    PBackgroundChild* backgroundActor =
331
0
      BackgroundChild::GetOrCreateForCurrentThread();
332
0
    if (NS_WARN_IF(!backgroundActor)) {
333
0
      mBackgroundActorFailed = true;
334
0
      return NS_ERROR_FAILURE;
335
0
    }
336
0
337
0
    {
338
0
      QuotaChild* actor = new QuotaChild(this);
339
0
340
0
      mBackgroundActor =
341
0
        static_cast<QuotaChild*>(backgroundActor->SendPQuotaConstructor(actor));
342
0
    }
343
0
  }
344
0
345
0
  if (!mBackgroundActor) {
346
0
    mBackgroundActorFailed = true;
347
0
    return NS_ERROR_FAILURE;
348
0
  }
349
0
350
0
  // If we already have a background actor then we can start this request now.
351
0
  nsresult rv = aInfo->InitiateRequest(mBackgroundActor);
352
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
353
0
    return rv;
354
0
  }
355
0
356
0
  return NS_OK;
357
0
}
358
359
void
360
QuotaManagerService::PerformIdleMaintenance()
361
0
{
362
0
  using namespace mozilla::hal;
363
0
364
0
  MOZ_ASSERT(XRE_IsParentProcess());
365
0
  MOZ_ASSERT(NS_IsMainThread());
366
0
367
0
  // If we're running on battery power then skip all idle maintenance since we
368
0
  // would otherwise be doing lots of disk I/O.
369
0
  BatteryInformation batteryInfo;
370
0
371
#ifdef MOZ_WIDGET_ANDROID
372
  // Android XPCShell doesn't load the AndroidBridge that is needed to make
373
  // GetCurrentBatteryInformation work...
374
  if (!QuotaManager::IsRunningXPCShellTests())
375
#endif
376
  {
377
0
    // In order to give the correct battery level, hal must have registered
378
0
    // battery observers.
379
0
    RegisterBatteryObserver(this);
380
0
    GetCurrentBatteryInformation(&batteryInfo);
381
0
    UnregisterBatteryObserver(this);
382
0
  }
383
0
384
0
  // If we're running XPCShell because we always want to be able to test this
385
0
  // code so pretend that we're always charging.
386
0
  if (QuotaManager::IsRunningXPCShellTests()) {
387
0
    batteryInfo.level() = 100;
388
0
    batteryInfo.charging() = true;
389
0
  }
390
0
391
0
  if (NS_WARN_IF(!batteryInfo.charging())) {
392
0
    return;
393
0
  }
394
0
395
0
  if (QuotaManager::IsRunningXPCShellTests()) {
396
0
    // We don't want user activity to impact this code if we're running tests.
397
0
    Unused << Observe(nullptr, OBSERVER_TOPIC_IDLE, nullptr);
398
0
  } else if (!mIdleObserverRegistered) {
399
0
    nsCOMPtr<nsIIdleService> idleService =
400
0
      do_GetService(kIdleServiceContractId);
401
0
    MOZ_ASSERT(idleService);
402
0
403
0
    MOZ_ALWAYS_SUCCEEDS(
404
0
      idleService->AddIdleObserver(this, kIdleObserverTimeSec));
405
0
406
0
    mIdleObserverRegistered = true;
407
0
  }
408
0
}
409
410
void
411
QuotaManagerService::RemoveIdleObserver()
412
0
{
413
0
  MOZ_ASSERT(XRE_IsParentProcess());
414
0
  MOZ_ASSERT(NS_IsMainThread());
415
0
416
0
  if (mIdleObserverRegistered) {
417
0
    nsCOMPtr<nsIIdleService> idleService =
418
0
      do_GetService(kIdleServiceContractId);
419
0
    MOZ_ASSERT(idleService);
420
0
421
0
    // Ignore the return value of RemoveIdleObserver, it may fail if the
422
0
    // observer has already been unregistered during shutdown.
423
0
    Unused <<
424
0
      idleService->RemoveIdleObserver(this, kIdleObserverTimeSec);
425
0
426
0
    mIdleObserverRegistered = false;
427
0
  }
428
0
}
429
430
NS_IMPL_ADDREF(QuotaManagerService)
431
NS_IMPL_RELEASE_WITH_DESTROY(QuotaManagerService, Destroy())
432
NS_IMPL_QUERY_INTERFACE(QuotaManagerService,
433
                        nsIQuotaManagerService,
434
                        nsIObserver)
435
436
NS_IMETHODIMP
437
QuotaManagerService::Init(nsIQuotaRequest** _retval)
438
0
{
439
0
  MOZ_ASSERT(NS_IsMainThread());
440
0
  MOZ_ASSERT(nsContentUtils::IsCallerChrome());
441
0
442
0
  if (NS_WARN_IF(!gTestingMode)) {
443
0
    return NS_ERROR_UNEXPECTED;
444
0
  }
445
0
446
0
  RefPtr<Request> request = new Request();
447
0
448
0
  InitParams params;
449
0
450
0
  nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
451
0
452
0
  nsresult rv = InitiateRequest(info);
453
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
454
0
    return rv;
455
0
  }
456
0
457
0
  request.forget(_retval);
458
0
  return NS_OK;
459
0
}
460
461
NS_IMETHODIMP
462
QuotaManagerService::InitStoragesForPrincipal(
463
                                             nsIPrincipal* aPrincipal,
464
                                             const nsACString& aPersistenceType,
465
                                             nsIQuotaRequest** _retval)
466
0
{
467
0
  MOZ_ASSERT(NS_IsMainThread());
468
0
  MOZ_ASSERT(nsContentUtils::IsCallerChrome());
469
0
470
0
  if (NS_WARN_IF(!gTestingMode)) {
471
0
    return NS_ERROR_UNEXPECTED;
472
0
  }
473
0
474
0
  RefPtr<Request> request = new Request();
475
0
476
0
  InitOriginParams params;
477
0
478
0
  nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
479
0
                                                params.principalInfo());
480
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
481
0
    return rv;
482
0
  }
483
0
484
0
  Nullable<PersistenceType> persistenceType;
485
0
  rv = NullablePersistenceTypeFromText(aPersistenceType, &persistenceType);
486
0
  if (NS_WARN_IF(NS_FAILED(rv)) || persistenceType.IsNull()) {
487
0
    return NS_ERROR_INVALID_ARG;
488
0
  }
489
0
490
0
  params.persistenceType() = persistenceType.Value();
491
0
492
0
  nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
493
0
494
0
  rv = InitiateRequest(info);
495
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
496
0
    return rv;
497
0
  }
498
0
499
0
  request.forget(_retval);
500
0
  return NS_OK;
501
0
}
502
503
NS_IMETHODIMP
504
QuotaManagerService::GetUsage(nsIQuotaUsageCallback* aCallback,
505
                              bool aGetAll,
506
                              nsIQuotaUsageRequest** _retval)
507
0
{
508
0
  MOZ_ASSERT(NS_IsMainThread());
509
0
  MOZ_ASSERT(aCallback);
510
0
511
0
  RefPtr<UsageRequest> request = new UsageRequest(aCallback);
512
0
513
0
  AllUsageParams params;
514
0
515
0
  params.getAll() = aGetAll;
516
0
517
0
  nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
518
0
519
0
  nsresult rv = InitiateRequest(info);
520
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
521
0
    return rv;
522
0
  }
523
0
524
0
  request.forget(_retval);
525
0
  return NS_OK;
526
0
}
527
528
NS_IMETHODIMP
529
QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
530
                                          nsIQuotaUsageCallback* aCallback,
531
                                          bool aGetGroupUsage,
532
                                          nsIQuotaUsageRequest** _retval)
533
0
{
534
0
  MOZ_ASSERT(NS_IsMainThread());
535
0
  MOZ_ASSERT(aPrincipal);
536
0
  MOZ_ASSERT(aCallback);
537
0
538
0
  RefPtr<UsageRequest> request = new UsageRequest(aPrincipal, aCallback);
539
0
540
0
  OriginUsageParams params;
541
0
542
0
  nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
543
0
                                                params.principalInfo());
544
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
545
0
    return rv;
546
0
  }
547
0
548
0
  params.getGroupUsage() = aGetGroupUsage;
549
0
550
0
  nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
551
0
552
0
  rv = InitiateRequest(info);
553
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
554
0
    return rv;
555
0
  }
556
0
557
0
  request.forget(_retval);
558
0
  return NS_OK;
559
0
}
560
561
NS_IMETHODIMP
562
QuotaManagerService::Clear(nsIQuotaRequest** _retval)
563
0
{
564
0
  MOZ_ASSERT(NS_IsMainThread());
565
0
566
0
  if (NS_WARN_IF(!gTestingMode)) {
567
0
    return NS_ERROR_UNEXPECTED;
568
0
  }
569
0
570
0
  RefPtr<Request> request = new Request();
571
0
572
0
  ClearAllParams params;
573
0
574
0
  nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
575
0
576
0
  nsresult rv = InitiateRequest(info);
577
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
578
0
    return rv;
579
0
  }
580
0
581
0
  request.forget(_retval);
582
0
  return NS_OK;
583
0
}
584
585
NS_IMETHODIMP
586
QuotaManagerService::ClearStoragesForPrincipal(nsIPrincipal* aPrincipal,
587
                                               const nsACString& aPersistenceType,
588
                                               bool aClearAll,
589
                                               nsIQuotaRequest** _retval)
590
0
{
591
0
  MOZ_ASSERT(NS_IsMainThread());
592
0
  MOZ_ASSERT(aPrincipal);
593
0
594
0
  nsCString suffix;
595
0
  aPrincipal->OriginAttributesRef().CreateSuffix(suffix);
596
0
597
0
  if (NS_WARN_IF(aClearAll && !suffix.IsEmpty())) {
598
0
    // The originAttributes should be default originAttributes when the
599
0
    // aClearAll flag is set.
600
0
    return NS_ERROR_INVALID_ARG;
601
0
  }
602
0
603
0
  RefPtr<Request> request = new Request(aPrincipal);
604
0
605
0
  ClearOriginParams params;
606
0
607
0
  nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
608
0
                                                params.principalInfo());
609
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
610
0
    return rv;
611
0
  }
612
0
613
0
  Nullable<PersistenceType> persistenceType;
614
0
  rv = NullablePersistenceTypeFromText(aPersistenceType, &persistenceType);
615
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
616
0
    return NS_ERROR_INVALID_ARG;
617
0
  }
618
0
619
0
  if (persistenceType.IsNull()) {
620
0
    params.persistenceTypeIsExplicit() = false;
621
0
  } else {
622
0
    params.persistenceType() = persistenceType.Value();
623
0
    params.persistenceTypeIsExplicit() = true;
624
0
  }
625
0
626
0
  params.clearAll() = aClearAll;
627
0
628
0
  nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
629
0
630
0
  rv = InitiateRequest(info);
631
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
632
0
    return rv;
633
0
  }
634
0
635
0
  request.forget(_retval);
636
0
  return NS_OK;
637
0
}
638
639
NS_IMETHODIMP
640
QuotaManagerService::Reset(nsIQuotaRequest** _retval)
641
0
{
642
0
  MOZ_ASSERT(NS_IsMainThread());
643
0
644
0
  if (NS_WARN_IF(!gTestingMode)) {
645
0
    return NS_ERROR_UNEXPECTED;
646
0
  }
647
0
648
0
  RefPtr<Request> request = new Request();
649
0
650
0
  ResetAllParams params;
651
0
652
0
  nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
653
0
654
0
  nsresult rv = InitiateRequest(info);
655
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
656
0
    return rv;
657
0
  }
658
0
659
0
  request.forget(_retval);
660
0
  return NS_OK;
661
0
}
662
663
NS_IMETHODIMP
664
QuotaManagerService::Persisted(nsIPrincipal* aPrincipal,
665
                               nsIQuotaRequest** _retval)
666
0
{
667
0
  MOZ_ASSERT(NS_IsMainThread());
668
0
  MOZ_ASSERT(aPrincipal);
669
0
  MOZ_ASSERT(_retval);
670
0
671
0
  RefPtr<Request> request = new Request(aPrincipal);
672
0
673
0
  PersistedParams params;
674
0
675
0
  nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
676
0
                                                params.principalInfo());
677
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
678
0
    return rv;
679
0
  }
680
0
681
0
  nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
682
0
683
0
  rv = InitiateRequest(info);
684
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
685
0
    return rv;
686
0
  }
687
0
688
0
  request.forget(_retval);
689
0
  return NS_OK;
690
0
}
691
692
NS_IMETHODIMP
693
QuotaManagerService::Persist(nsIPrincipal* aPrincipal,
694
                             nsIQuotaRequest** _retval)
695
0
{
696
0
  MOZ_ASSERT(NS_IsMainThread());
697
0
  MOZ_ASSERT(aPrincipal);
698
0
  MOZ_ASSERT(_retval);
699
0
700
0
  RefPtr<Request> request = new Request(aPrincipal);
701
0
702
0
  PersistParams params;
703
0
704
0
  nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
705
0
                                                params.principalInfo());
706
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
707
0
    return rv;
708
0
  }
709
0
710
0
  nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
711
0
712
0
  rv = InitiateRequest(info);
713
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
714
0
    return rv;
715
0
  }
716
0
717
0
  request.forget(_retval);
718
0
  return NS_OK;
719
0
}
720
721
NS_IMETHODIMP
722
QuotaManagerService::Observe(nsISupports* aSubject,
723
                             const char* aTopic,
724
                             const char16_t* aData)
725
0
{
726
0
  MOZ_ASSERT(XRE_IsParentProcess());
727
0
  MOZ_ASSERT(NS_IsMainThread());
728
0
729
0
  if (!strcmp(aTopic, PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID)) {
730
0
    RemoveIdleObserver();
731
0
    return NS_OK;
732
0
  }
733
0
734
0
  if (!strcmp(aTopic, "clear-origin-attributes-data")) {
735
0
    RefPtr<Request> request = new Request();
736
0
737
0
    ClearDataParams params;
738
0
    params.pattern() = nsDependentString(aData);
739
0
740
0
    nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
741
0
742
0
    nsresult rv = InitiateRequest(info);
743
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
744
0
      return rv;
745
0
    }
746
0
747
0
    return NS_OK;
748
0
  }
749
0
750
0
  if (!strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY)) {
751
0
    PerformIdleMaintenance();
752
0
    return NS_OK;
753
0
  }
754
0
755
0
  if (!strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
756
0
    nsAutoPtr<PendingRequestInfo> info(
757
0
      new IdleMaintenanceInfo(/* aStart */ true));
758
0
759
0
    nsresult rv = InitiateRequest(info);
760
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
761
0
      return rv;
762
0
    }
763
0
764
0
    return NS_OK;
765
0
  }
766
0
767
0
  if (!strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
768
0
    RemoveIdleObserver();
769
0
770
0
    nsAutoPtr<PendingRequestInfo> info(
771
0
      new IdleMaintenanceInfo(/* aStart */ false));
772
0
773
0
    nsresult rv = InitiateRequest(info);
774
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
775
0
      return rv;
776
0
    }
777
0
778
0
    return NS_OK;
779
0
  }
780
0
781
0
  MOZ_ASSERT_UNREACHABLE("Should never get here!");
782
0
  return NS_OK;
783
0
}
784
785
void
786
QuotaManagerService::Notify(const hal::BatteryInformation& aBatteryInfo)
787
0
{
788
0
  // This notification is received when battery data changes. We don't need to
789
0
  // deal with this notification.
790
0
}
791
792
NS_IMETHODIMP
793
AbortOperationsRunnable::Run()
794
0
{
795
0
  AssertIsOnBackgroundThread();
796
0
797
0
  if (QuotaManager::IsShuttingDown()) {
798
0
    return NS_OK;
799
0
  }
800
0
801
0
  QuotaManager* quotaManager = QuotaManager::Get();
802
0
  if (!quotaManager) {
803
0
    return NS_OK;
804
0
  }
805
0
806
0
  quotaManager->AbortOperationsForProcess(mContentParentId);
807
0
808
0
  return NS_OK;
809
0
}
810
811
nsresult
812
QuotaManagerService::
813
UsageRequestInfo::InitiateRequest(QuotaChild* aActor)
814
0
{
815
0
  MOZ_ASSERT(aActor);
816
0
817
0
  auto request = static_cast<UsageRequest*>(mRequest.get());
818
0
819
0
  auto actor = new QuotaUsageRequestChild(request);
820
0
821
0
  if (!aActor->SendPQuotaUsageRequestConstructor(actor, mParams)) {
822
0
    request->SetError(NS_ERROR_FAILURE);
823
0
    return NS_ERROR_FAILURE;
824
0
  }
825
0
826
0
  request->SetBackgroundActor(actor);
827
0
828
0
  return NS_OK;
829
0
}
830
831
nsresult
832
QuotaManagerService::
833
RequestInfo::InitiateRequest(QuotaChild* aActor)
834
0
{
835
0
  MOZ_ASSERT(aActor);
836
0
837
0
  auto request = static_cast<Request*>(mRequest.get());
838
0
839
0
  auto actor = new QuotaRequestChild(request);
840
0
841
0
  if (!aActor->SendPQuotaRequestConstructor(actor, mParams)) {
842
0
    request->SetError(NS_ERROR_FAILURE);
843
0
    return NS_ERROR_FAILURE;
844
0
  }
845
0
846
0
  return NS_OK;
847
0
}
848
849
nsresult
850
QuotaManagerService::
851
IdleMaintenanceInfo::InitiateRequest(QuotaChild* aActor)
852
0
{
853
0
  MOZ_ASSERT(aActor);
854
0
855
0
  bool result;
856
0
857
0
  if (mStart) {
858
0
    result = aActor->SendStartIdleMaintenance();
859
0
  } else {
860
0
    result = aActor->SendStopIdleMaintenance();
861
0
  }
862
0
863
0
  if (!result) {
864
0
    return NS_ERROR_FAILURE;
865
0
  }
866
0
867
0
  return NS_OK;
868
0
}
869
870
} // namespace quota
871
} // namespace dom
872
} // namespace mozilla