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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_StorageIPC_h
8 #define mozilla_dom_StorageIPC_h
10 #include "LocalStorageCache.h"
11 #include "StorageDBThread.h"
12 #include "StorageObserver.h"
14 #include "mozilla/Mutex.h"
15 #include "mozilla/UniquePtr.h"
16 #include "mozilla/dom/FlippedOnce.h"
17 #include "mozilla/dom/PBackgroundLocalStorageCacheChild.h"
18 #include "mozilla/dom/PBackgroundLocalStorageCacheParent.h"
19 #include "mozilla/dom/PBackgroundSessionStorageCacheChild.h"
20 #include "mozilla/dom/PBackgroundSessionStorageCacheParent.h"
21 #include "mozilla/dom/PBackgroundSessionStorageManagerChild.h"
22 #include "mozilla/dom/PBackgroundSessionStorageManagerParent.h"
23 #include "mozilla/dom/PBackgroundStorageChild.h"
24 #include "mozilla/dom/PBackgroundStorageParent.h"
25 #include "mozilla/dom/PSessionStorageObserverChild.h"
26 #include "mozilla/dom/PSessionStorageObserverParent.h"
27 #include "nsTHashSet.h"
31 class OriginAttributesPattern
;
35 class BackgroundChildImpl
;
42 class LocalStorageManager
;
43 class PBackgroundStorageParent
;
44 class PSessionStorageObserverParent
;
45 class SessionStorageCache
;
46 class SessionStorageCacheParent
;
47 class SessionStorageManager
;
48 class SessionStorageManagerParent
;
49 class BackgroundSessionStorageManager
;
50 class SessionStorageObserver
;
52 class LocalStorageCacheChild final
: public PBackgroundLocalStorageCacheChild
{
53 friend class mozilla::ipc::BackgroundChildImpl
;
54 friend class LocalStorageCache
;
55 friend class LocalStorageManager
;
57 // LocalStorageCache effectively owns this instance, although IPC handles its
58 // allocation/deallocation. When the LocalStorageCache destructor runs, it
59 // will invoke SendDeleteMeInternal() which will trigger both instances to
60 // drop their mutual references and cause IPC to destroy the actor after the
61 // DeleteMe round-trip.
62 LocalStorageCache
* MOZ_NON_OWNING_REF mCache
;
67 void AssertIsOnOwningThread() const {
68 NS_ASSERT_OWNINGTHREAD(LocalStorageCacheChild
);
72 // Only created by LocalStorageManager.
73 explicit LocalStorageCacheChild(LocalStorageCache
* aCache
);
75 // Only destroyed by mozilla::ipc::BackgroundChildImpl.
76 ~LocalStorageCacheChild();
78 // Only called by LocalStorageCache.
79 void SendDeleteMeInternal();
81 // IPDL methods are only called by IPDL.
82 void ActorDestroy(ActorDestroyReason aWhy
) override
;
84 mozilla::ipc::IPCResult
RecvObserve(const PrincipalInfo
& aPrincipalInfo
,
85 const PrincipalInfo
& aCachePrincipalInfo
,
86 const uint32_t& aPrivateBrowsingId
,
87 const nsAString
& aDocumentURI
,
88 const nsAString
& aKey
,
89 const nsAString
& aOldValue
,
90 const nsAString
& aNewValue
) override
;
93 // Child side of the IPC protocol, exposes as DB interface but
94 // is responsible to send all requests to the parent process
95 // and expects asynchronous answers. Those are then transparently
96 // forwarded back to consumers on the child process.
97 class StorageDBChild final
: public PBackgroundStorageChild
{
98 class ShutdownObserver
;
100 virtual ~StorageDBChild();
103 StorageDBChild(LocalStorageManager
* aManager
, uint32_t aPrivateBrowsingId
);
105 static StorageDBChild
* Get(uint32_t aPrivateBrowsingId
);
107 static StorageDBChild
* GetOrCreate(uint32_t aPrivateBrowsingId
);
109 NS_INLINE_DECL_REFCOUNTING(StorageDBChild
);
111 void AddIPDLReference();
112 void ReleaseIPDLReference();
114 virtual nsresult
Init();
115 virtual nsresult
Shutdown();
117 virtual void AsyncPreload(LocalStorageCacheBridge
* aCache
,
118 bool aPriority
= false);
119 virtual void AsyncGetUsage(StorageUsageBridge
* aUsage
);
121 virtual void SyncPreload(LocalStorageCacheBridge
* aCache
,
122 bool aForceSync
= false);
124 virtual nsresult
AsyncAddItem(LocalStorageCacheBridge
* aCache
,
125 const nsAString
& aKey
, const nsAString
& aValue
);
126 virtual nsresult
AsyncUpdateItem(LocalStorageCacheBridge
* aCache
,
127 const nsAString
& aKey
,
128 const nsAString
& aValue
);
129 virtual nsresult
AsyncRemoveItem(LocalStorageCacheBridge
* aCache
,
130 const nsAString
& aKey
);
131 virtual nsresult
AsyncClear(LocalStorageCacheBridge
* aCache
);
133 virtual void AsyncClearAll() {
134 if (mOriginsHavingData
) {
135 mOriginsHavingData
->Clear(); /* NO-OP on the child process otherwise */
139 virtual void AsyncClearMatchingOrigin(const nsACString
& aOriginNoSuffix
) {
140 MOZ_CRASH("Shouldn't be called!");
143 virtual void AsyncClearMatchingOriginAttributes(
144 const OriginAttributesPattern
& aPattern
) {
145 MOZ_CRASH("Shouldn't be called!");
148 virtual void AsyncFlush() { MOZ_CRASH("Shouldn't be called!"); }
150 virtual bool ShouldPreloadOrigin(const nsACString
& aOriginNoSuffix
);
153 mozilla::ipc::IPCResult
RecvObserve(const nsACString
& aTopic
,
154 const nsAString
& aOriginAttributesPattern
,
155 const nsACString
& aOriginScope
) override
;
156 mozilla::ipc::IPCResult
RecvLoadItem(const nsACString
& aOriginSuffix
,
157 const nsACString
& aOriginNoSuffix
,
158 const nsAString
& aKey
,
159 const nsAString
& aValue
) override
;
160 mozilla::ipc::IPCResult
RecvLoadDone(const nsACString
& aOriginSuffix
,
161 const nsACString
& aOriginNoSuffix
,
162 const nsresult
& aRv
) override
;
163 mozilla::ipc::IPCResult
RecvOriginsHavingData(
164 nsTArray
<nsCString
>&& aOrigins
) override
;
165 mozilla::ipc::IPCResult
RecvLoadUsage(const nsACString
& aOriginNoSuffix
,
166 const int64_t& aUsage
) override
;
167 mozilla::ipc::IPCResult
RecvError(const nsresult
& aRv
) override
;
169 nsTHashSet
<nsCString
>& OriginsHavingData();
171 // Held to get caches to forward answers to.
172 RefPtr
<LocalStorageManager
> mManager
;
174 // Origins having data hash, for optimization purposes only
175 UniquePtr
<nsTHashSet
<nsCString
>> mOriginsHavingData
;
177 // List of caches waiting for preload. This ensures the contract that
178 // AsyncPreload call references the cache for time of the preload.
179 nsTHashSet
<RefPtr
<LocalStorageCacheBridge
>> mLoadingCaches
;
181 // Expected to be only 0 or 1.
182 const uint32_t mPrivateBrowsingId
;
184 // Status of the remote database
190 class SessionStorageObserverChild final
: public PSessionStorageObserverChild
{
191 friend class SessionStorageManager
;
192 friend class SessionStorageObserver
;
194 // SessionStorageObserver effectively owns this instance, although IPC handles
195 // its allocation/deallocation. When the SessionStorageObserver destructor
196 // runs, it will invoke SendDeleteMeInternal() which will trigger both
197 // instances to drop their mutual references and cause IPC to destroy the
198 // actor after the DeleteMe round-trip.
199 SessionStorageObserver
* MOZ_NON_OWNING_REF mObserver
;
204 void AssertIsOnOwningThread() const {
205 NS_ASSERT_OWNINGTHREAD(LocalStorageCacheChild
);
209 // Only created by SessionStorageManager.
210 explicit SessionStorageObserverChild(SessionStorageObserver
* aObserver
);
212 ~SessionStorageObserverChild();
214 // Only called by SessionStorageObserver.
215 void SendDeleteMeInternal();
217 // IPDL methods are only called by IPDL.
218 void ActorDestroy(ActorDestroyReason aWhy
) override
;
220 mozilla::ipc::IPCResult
RecvObserve(const nsACString
& aTopic
,
221 const nsAString
& aOriginAttributesPattern
,
222 const nsACString
& aOriginScope
) override
;
225 class SessionStorageCacheChild final
226 : public PBackgroundSessionStorageCacheChild
{
227 friend class PBackgroundSessionStorageCacheChild
;
228 friend class SessionStorageCache
;
229 friend class SessionStorageManager
;
230 friend class mozilla::ipc::BackgroundChildImpl
;
232 // SessionStorageManagerChild effectively owns this instance, although IPC
233 // handles its allocation/deallocation. When the SessionStorageManager
234 // destructor runs, it will invoke SendDeleteMeInternal() which will trigger
235 // both instances to drop their mutual references and cause IPC to destroy the
236 // actor after the DeleteMe round-trip.
237 SessionStorageCache
* MOZ_NON_OWNING_REF mCache
;
239 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::SessionStorageCacheChild
, override
)
242 void AssertIsOnOwningThread() const {
243 NS_ASSERT_OWNINGTHREAD(SesionStoragManagerChild
);
247 // Only created by SessionStorageManager.
248 explicit SessionStorageCacheChild(SessionStorageCache
* aCache
);
250 // Only destroyed by mozilla::ipc::BackgroundChildImpl.
251 ~SessionStorageCacheChild();
253 // Only called by SessionStorageCache.
254 void SendDeleteMeInternal();
256 // IPDL methods are only called by IPDL.
257 void ActorDestroy(ActorDestroyReason aWhy
) override
;
260 class SessionStorageManagerChild final
261 : public PBackgroundSessionStorageManagerChild
{
262 friend class PBackgroundSessionStorageManagerChild
;
263 friend class SessionStorage
;
264 friend class SessionStorageManager
;
265 friend class mozilla::ipc::BackgroundChildImpl
;
267 // SessionStorageManager effectively owns this instance, although IPC handles
268 // its allocation/deallocation. When the SessionStorageManager destructor
269 // runs, it will invoke SendDeleteMeInternal() which will trigger both
270 // instances to drop their mutual references and cause IPC to destroy the
271 // actor after the DeleteMe round-trip.
272 SessionStorageManager
* MOZ_NON_OWNING_REF mSSManager
;
274 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::SessionStorageManagerChild
, override
)
277 void AssertIsOnOwningThread() const {
278 NS_ASSERT_OWNINGTHREAD(SesionStoragManagerChild
);
282 // Only created by SessionStorage.
283 explicit SessionStorageManagerChild(SessionStorageManager
* aSSManager
);
285 // Only destroyed by mozilla::ipc::BackgroundChildImpl.
286 ~SessionStorageManagerChild();
288 // Only called by SessionStorageManager.
289 void SendDeleteMeInternal();
291 // IPDL methods are only called by IPDL.
292 void ActorDestroy(ActorDestroyReason aWhy
) override
;
294 mozilla::ipc::IPCResult
RecvClearStoragesForOrigin(
295 const nsACString
& aOriginAttrs
, const nsACString
& aOriginKey
) override
;
298 class LocalStorageCacheParent final
299 : public PBackgroundLocalStorageCacheParent
{
300 const PrincipalInfo mPrincipalInfo
;
301 const nsCString mOriginKey
;
302 uint32_t mPrivateBrowsingId
;
303 bool mActorDestroyed
;
306 // Created in AllocPBackgroundLocalStorageCacheParent.
307 LocalStorageCacheParent(const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
,
308 const nsACString
& aOriginKey
,
309 uint32_t aPrivateBrowsingId
);
311 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::LocalStorageCacheParent
)
313 const PrincipalInfo
& PrincipalInfo() const { return mPrincipalInfo
; }
316 // Reference counted.
317 ~LocalStorageCacheParent();
319 // IPDL methods are only called by IPDL.
320 void ActorDestroy(ActorDestroyReason aWhy
) override
;
322 mozilla::ipc::IPCResult
RecvDeleteMe() override
;
324 mozilla::ipc::IPCResult
RecvNotify(const nsAString
& aDocumentURI
,
325 const nsAString
& aKey
,
326 const nsAString
& aOldValue
,
327 const nsAString
& aNewValue
) override
;
330 // Receives async requests from child processes and is responsible
331 // to send back responses from the DB thread. Exposes as a fake
332 // LocalStorageCache consumer.
333 // Also responsible for forwardning all chrome operation notifications
334 // such as cookie cleaning etc to the child process.
335 class StorageDBParent final
: public PBackgroundStorageParent
{
338 virtual ~StorageDBParent();
341 StorageDBParent(const nsAString
& aProfilePath
, uint32_t aPrivateBrowsingId
);
345 NS_IMETHOD_(MozExternalRefCountType
) AddRef(void);
346 NS_IMETHOD_(MozExternalRefCountType
) Release(void);
348 void AddIPDLReference();
349 void ReleaseIPDLReference();
351 bool IPCOpen() { return mIPCOpen
; }
354 // Fake cache class receiving async callbacks from DB thread, sending
355 // them back to appropriate cache object on the child process.
356 class CacheParentBridge
: public LocalStorageCacheBridge
{
358 CacheParentBridge(StorageDBParent
* aParentDB
,
359 const nsACString
& aOriginSuffix
,
360 const nsACString
& aOriginNoSuffix
)
361 : mOwningEventTarget(GetCurrentSerialEventTarget()),
363 mOriginSuffix(aOriginSuffix
),
364 mOriginNoSuffix(aOriginNoSuffix
),
367 virtual ~CacheParentBridge() = default;
369 // LocalStorageCacheBridge
370 virtual const nsCString
Origin() const override
;
371 virtual const nsCString
& OriginNoSuffix() const override
{
372 return mOriginNoSuffix
;
374 virtual const nsCString
& OriginSuffix() const override
{
375 return mOriginSuffix
;
377 virtual bool Loaded() override
{ return mLoaded
; }
378 virtual uint32_t LoadedCount() override
{ return mLoadedCount
; }
380 virtual bool LoadItem(const nsAString
& aKey
,
381 const nsAString
& aValue
) override
;
382 virtual void LoadDone(nsresult aRv
) override
;
383 virtual void LoadWait() override
;
386 Release(void) override
;
391 nsCOMPtr
<nsISerialEventTarget
> mOwningEventTarget
;
392 RefPtr
<StorageDBParent
> mParent
;
393 nsCString mOriginSuffix
, mOriginNoSuffix
;
395 uint32_t mLoadedCount
;
398 // Fake usage class receiving async callbacks from DB thread
399 class UsageParentBridge
: public StorageUsageBridge
{
401 UsageParentBridge(StorageDBParent
* aParentDB
,
402 const nsACString
& aOriginScope
)
403 : mOwningEventTarget(GetCurrentSerialEventTarget()),
405 mOriginScope(aOriginScope
) {}
406 virtual ~UsageParentBridge() = default;
408 // StorageUsageBridge
409 virtual const nsCString
& OriginScope() override
{ return mOriginScope
; }
410 virtual void LoadUsage(const int64_t usage
) override
;
412 NS_IMETHOD_(MozExternalRefCountType
)
413 Release(void) override
;
418 nsCOMPtr
<nsISerialEventTarget
> mOwningEventTarget
;
419 RefPtr
<StorageDBParent
> mParent
;
420 nsCString mOriginScope
;
425 virtual void ActorDestroy(ActorDestroyReason aWhy
) override
;
426 mozilla::ipc::IPCResult
RecvDeleteMe() override
;
428 mozilla::ipc::IPCResult
RecvAsyncPreload(const nsACString
& aOriginSuffix
,
429 const nsACString
& aOriginNoSuffix
,
430 const bool& aPriority
) override
;
431 mozilla::ipc::IPCResult
RecvPreload(const nsACString
& aOriginSuffix
,
432 const nsACString
& aOriginNoSuffix
,
433 const uint32_t& aAlreadyLoadedCount
,
434 nsTArray
<nsString
>* aKeys
,
435 nsTArray
<nsString
>* aValues
,
436 nsresult
* aRv
) override
;
437 mozilla::ipc::IPCResult
RecvAsyncGetUsage(
438 const nsACString
& aOriginNoSuffix
) override
;
439 mozilla::ipc::IPCResult
RecvAsyncAddItem(const nsACString
& aOriginSuffix
,
440 const nsACString
& aOriginNoSuffix
,
441 const nsAString
& aKey
,
442 const nsAString
& aValue
) override
;
443 mozilla::ipc::IPCResult
RecvAsyncUpdateItem(const nsACString
& aOriginSuffix
,
444 const nsACString
& aOriginNoSuffix
,
445 const nsAString
& aKey
,
446 const nsAString
& aValue
) override
;
447 mozilla::ipc::IPCResult
RecvAsyncRemoveItem(const nsACString
& aOriginSuffix
,
448 const nsACString
& aOriginNoSuffix
,
449 const nsAString
& aKey
) override
;
450 mozilla::ipc::IPCResult
RecvAsyncClear(
451 const nsACString
& aOriginSuffix
,
452 const nsACString
& aOriginNoSuffix
) override
;
453 mozilla::ipc::IPCResult
RecvAsyncFlush() override
;
455 mozilla::ipc::IPCResult
RecvStartup() override
;
456 mozilla::ipc::IPCResult
RecvClearAll() override
;
457 mozilla::ipc::IPCResult
RecvClearMatchingOrigin(
458 const nsACString
& aOriginNoSuffix
) override
;
459 mozilla::ipc::IPCResult
RecvClearMatchingOriginAttributes(
460 const OriginAttributesPattern
& aPattern
) override
;
462 void Observe(const nsACString
& aTopic
, const nsAString
& aOriginAttrPattern
,
463 const nsACString
& aOriginScope
);
466 CacheParentBridge
* NewCache(const nsACString
& aOriginSuffix
,
467 const nsACString
& aOriginNoSuffix
);
469 RefPtr
<ObserverSink
> mObserverSink
;
471 // A hack to deal with deadlock between the parent process main thread and
472 // background thread when invoking StorageDBThread::GetOrCreate because it
473 // cannot safely perform a synchronous dispatch back to the main thread
474 // (because we are already synchronously doing things on the stack).
475 // Populated for the same process actors, empty for other process actors.
476 nsString mProfilePath
;
478 // Expected to be only 0 or 1.
479 const uint32_t mPrivateBrowsingId
;
481 ThreadSafeAutoRefCnt mRefCnt
;
484 // True when IPC channel is open and Send*() methods are OK to use.
488 class SessionStorageObserverParent final
: public PSessionStorageObserverParent
,
489 public StorageObserverSink
{
490 bool mActorDestroyed
;
493 // Created in AllocPSessionStorageObserverParent.
494 SessionStorageObserverParent();
496 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::SessionStorageObserverParent
)
499 // Reference counted.
500 ~SessionStorageObserverParent();
502 // IPDL methods are only called by IPDL.
503 void ActorDestroy(ActorDestroyReason aWhy
) override
;
505 mozilla::ipc::IPCResult
RecvDeleteMe() override
;
507 // StorageObserverSink
508 nsresult
Observe(const char* aTopic
, const nsAString
& aOriginAttrPattern
,
509 const nsACString
& aOriginScope
) override
;
512 class SessionStorageCacheParent final
513 : public PBackgroundSessionStorageCacheParent
{
514 friend class PBackgroundSessionStorageCacheParent
;
515 const PrincipalInfo mPrincipalInfo
;
516 const nsCString mOriginKey
;
518 RefPtr
<SessionStorageManagerParent
> mManagerActor
;
519 FlippedOnce
<false> mLoadReceived
;
522 SessionStorageCacheParent(const PrincipalInfo
& aPrincipalInfo
,
523 const nsACString
& aOriginKey
,
524 SessionStorageManagerParent
* aActor
);
526 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::SessionStorageCacheParent
, override
)
528 const PrincipalInfo
& PrincipalInfo() const { return mPrincipalInfo
; }
529 const nsACString
& OriginKey() const { return mOriginKey
; }
532 ~SessionStorageCacheParent();
534 // IPDL methods are only called by IPDL.
535 void ActorDestroy(ActorDestroyReason aWhy
) override
;
537 mozilla::ipc::IPCResult
RecvLoad(nsTArray
<SSSetItemInfo
>* aData
) override
;
539 mozilla::ipc::IPCResult
RecvCheckpoint(
540 nsTArray
<SSWriteInfo
>&& aWriteInfos
) override
;
542 mozilla::ipc::IPCResult
RecvDeleteMe() override
;
545 class SessionStorageManagerParent final
546 : public PBackgroundSessionStorageManagerParent
{
547 friend class PBackgroundSessionStorageManagerParent
;
549 RefPtr
<BackgroundSessionStorageManager
> mBackgroundManager
;
552 explicit SessionStorageManagerParent(uint64_t aTopContextId
);
554 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::SessionStorageManagerParent
,
557 already_AddRefed
<PBackgroundSessionStorageCacheParent
>
558 AllocPBackgroundSessionStorageCacheParent(
559 const PrincipalInfo
& aPrincipalInfo
,
560 const nsACString
& aOriginKey
) override
;
562 BackgroundSessionStorageManager
* GetManager() const;
564 mozilla::ipc::IPCResult
RecvClearStorages(
565 const OriginAttributesPattern
& aPattern
,
566 const nsACString
& aOriginScope
) override
;
569 ~SessionStorageManagerParent();
571 // IPDL methods are only called by IPDL.
572 void ActorDestroy(ActorDestroyReason aWhy
) override
;
574 mozilla::ipc::IPCResult
RecvDeleteMe() override
;
577 PBackgroundLocalStorageCacheParent
* AllocPBackgroundLocalStorageCacheParent(
578 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
,
579 const nsACString
& aOriginKey
, const uint32_t& aPrivateBrowsingId
);
581 mozilla::ipc::IPCResult
RecvPBackgroundLocalStorageCacheConstructor(
582 mozilla::ipc::PBackgroundParent
* aBackgroundActor
,
583 PBackgroundLocalStorageCacheParent
* aActor
,
584 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
,
585 const nsACString
& aOriginKey
, const uint32_t& aPrivateBrowsingId
);
587 bool DeallocPBackgroundLocalStorageCacheParent(
588 PBackgroundLocalStorageCacheParent
* aActor
);
590 PBackgroundStorageParent
* AllocPBackgroundStorageParent(
591 const nsAString
& aProfilePath
, const uint32_t& aPrivateBrowsingId
);
593 mozilla::ipc::IPCResult
RecvPBackgroundStorageConstructor(
594 PBackgroundStorageParent
* aActor
, const nsAString
& aProfilePath
,
595 const uint32_t& aPrivateBrowsingId
);
597 bool DeallocPBackgroundStorageParent(PBackgroundStorageParent
* aActor
);
599 PSessionStorageObserverParent
* AllocPSessionStorageObserverParent();
601 bool RecvPSessionStorageObserverConstructor(
602 PSessionStorageObserverParent
* aActor
);
604 bool DeallocPSessionStorageObserverParent(
605 PSessionStorageObserverParent
* aActor
);
607 already_AddRefed
<PBackgroundSessionStorageCacheParent
>
608 AllocPBackgroundSessionStorageCacheParent(
609 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
,
610 const nsACString
& aOriginKey
);
612 already_AddRefed
<PBackgroundSessionStorageManagerParent
>
613 AllocPBackgroundSessionStorageManagerParent(const uint64_t& aTopContextId
);
615 } // namespace mozilla
617 #endif // mozilla_dom_StorageIPC_h