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