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 #include "SessionStorageManager.h"
9 #include "StorageIPC.h"
10 #include "SessionStorage.h"
11 #include "SessionStorageCache.h"
12 #include "SessionStorageObserver.h"
13 #include "StorageUtils.h"
14 #include "mozilla/ClearOnShutdown.h"
15 #include "mozilla/OriginAttributes.h"
16 #include "mozilla/PrincipalHashKey.h"
17 #include "mozilla/ScopeExit.h"
18 #include "mozilla/StoragePrincipalHelper.h"
19 #include "mozilla/dom/CanonicalBrowsingContext.h"
20 #include "mozilla/dom/ContentChild.h"
21 #include "mozilla/dom/LocalStorageCommon.h"
22 #include "mozilla/dom/PBackgroundSessionStorageCache.h"
23 #include "mozilla/dom/PBackgroundSessionStorageManager.h"
24 #include "mozilla/dom/PermissionMessageUtils.h"
25 #include "mozilla/dom/WindowGlobalParent.h"
26 #include "mozilla/ipc/BackgroundChild.h"
27 #include "mozilla/ipc/BackgroundParent.h"
28 #include "mozilla/ipc/PBackgroundChild.h"
29 #include "nsTHashMap.h"
30 #include "nsThreadUtils.h"
35 using namespace StorageUtils
;
37 // Parent process, background thread hashmap that stores top context id and
40 nsRefPtrHashtable
<nsUint64HashKey
, BackgroundSessionStorageManager
>>
43 bool RecvShutdownBackgroundSessionStorageManagers() {
44 ::mozilla::ipc::AssertIsOnBackgroundThread();
50 void RecvPropagateBackgroundSessionStorageManager(
51 uint64_t aCurrentTopContextId
, uint64_t aTargetTopContextId
) {
52 ::mozilla::ipc::AssertIsOnBackgroundThread();
55 if (RefPtr
<BackgroundSessionStorageManager
> mgr
=
56 sManagers
->Get(aCurrentTopContextId
)) {
57 mgr
->MaybeDispatchSessionStoreUpdate();
58 mgr
->SetCurrentBrowsingContextId(aTargetTopContextId
);
59 // Because of bfcache, we may re-register aTargetTopContextId in
60 // CanonicalBrowsingContext::ReplacedBy.
61 // XXXBFCache do we want to tweak this behavior and ensure this is
63 sManagers
->InsertOrUpdate(aTargetTopContextId
, std::move(mgr
));
68 bool RecvRemoveBackgroundSessionStorageManager(uint64_t aTopContextId
) {
69 ::mozilla::ipc::AssertIsOnBackgroundThread();
72 RefPtr
<BackgroundSessionStorageManager
> mgr
;
73 sManagers
->Remove(aTopContextId
, getter_AddRefs(mgr
));
76 mgr
->CancelSessionStoreUpdate();
83 bool RecvLoadSessionStorageData(
84 uint64_t aTopContextId
,
85 nsTArray
<mozilla::dom::SSCacheCopy
>&& aCacheCopyList
) {
86 if (aCacheCopyList
.IsEmpty()) {
90 RefPtr
<BackgroundSessionStorageManager
> manager
=
91 BackgroundSessionStorageManager::GetOrCreate(aTopContextId
);
97 for (const auto& cacheInit
: aCacheCopyList
) {
98 OriginAttributes attrs
;
99 StoragePrincipalHelper::GetOriginAttributes(cacheInit
.principalInfo(),
102 nsAutoCString originAttrs
;
103 attrs
.CreateSuffix(originAttrs
);
105 manager
->UpdateData(originAttrs
, cacheInit
.originKey(), cacheInit
.data());
111 bool RecvGetSessionStorageData(
112 uint64_t aTopContextId
, uint32_t aSizeLimit
, bool aCancelSessionStoreTimer
,
113 ::mozilla::ipc::PBackgroundParent::GetSessionStorageManagerDataResolver
&&
115 nsTArray
<mozilla::dom::SSCacheCopy
> data
;
116 auto resolve
= MakeScopeExit([&]() { aResolver(std::move(data
)); });
122 RefPtr
<BackgroundSessionStorageManager
> manager
=
123 sManagers
->Get(aTopContextId
);
128 if (aCancelSessionStoreTimer
) {
129 manager
->CancelSessionStoreUpdate();
132 manager
->GetData(aSizeLimit
, data
);
137 void SessionStorageManagerBase::ClearStoragesInternal(
138 const OriginAttributesPattern
& aPattern
, const nsACString
& aOriginScope
) {
139 for (const auto& oaEntry
: mOATable
) {
141 DebugOnly
<bool> ok
= oa
.PopulateFromSuffix(oaEntry
.GetKey());
143 if (!aPattern
.Matches(oa
)) {
144 // This table doesn't match the given origin attributes pattern
148 OriginKeyHashTable
* table
= oaEntry
.GetWeak();
149 for (const auto& originKeyEntry
: *table
) {
150 if (aOriginScope
.IsEmpty() ||
151 StringBeginsWith(originKeyEntry
.GetKey(), aOriginScope
)) {
152 const auto cache
= originKeyEntry
.GetData()->mCache
;
154 cache
->ResetWriteInfos();
160 SessionStorageManagerBase::OriginRecord
*
161 SessionStorageManagerBase::GetOriginRecord(
162 const nsACString
& aOriginAttrs
, const nsACString
& aOriginKey
,
163 const bool aMakeIfNeeded
, SessionStorageCache
* const aCloneFrom
) {
164 // XXX It seems aMakeIfNeeded is always known at compile-time, so this could
165 // be split into two functions.
168 return mOATable
.GetOrInsertNew(aOriginAttrs
)
169 ->LookupOrInsertWith(
172 auto newOriginRecord
= MakeUnique
<OriginRecord
>();
174 newOriginRecord
->mCache
= aCloneFrom
->Clone();
176 newOriginRecord
->mCache
= new SessionStorageCache();
178 return newOriginRecord
;
183 auto* const table
= mOATable
.Get(aOriginAttrs
);
184 if (!table
) return nullptr;
186 return table
->Get(aOriginKey
);
189 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SessionStorageManager
)
190 NS_INTERFACE_MAP_ENTRY(nsISupports
)
191 NS_INTERFACE_MAP_ENTRY(nsIDOMStorageManager
)
192 NS_INTERFACE_MAP_ENTRY(nsIDOMSessionStorageManager
)
195 NS_IMPL_CYCLE_COLLECTION(SessionStorageManager
, mBrowsingContext
)
196 NS_IMPL_CYCLE_COLLECTING_ADDREF(SessionStorageManager
)
197 NS_IMPL_CYCLE_COLLECTING_RELEASE(SessionStorageManager
)
199 SessionStorageManager::SessionStorageManager(
200 RefPtr
<BrowsingContext
> aBrowsingContext
)
201 : mBrowsingContext(std::move(aBrowsingContext
)), mActor(nullptr) {
202 AssertIsOnMainThread();
204 StorageObserver
* observer
= StorageObserver::Self();
207 "No StorageObserver, cannot observe private data delete notifications!");
210 observer
->AddSink(this);
213 if (!XRE_IsParentProcess() && NextGenLocalStorageEnabled()) {
214 // When LSNG is enabled the thread IPC bridge doesn't exist, so we have to
215 // create own protocol to distribute chrome observer notifications to
216 // content processes.
217 mObserver
= SessionStorageObserver::Get();
220 ContentChild
* contentActor
= ContentChild::GetSingleton();
221 MOZ_ASSERT(contentActor
);
223 RefPtr
<SessionStorageObserver
> observer
= new SessionStorageObserver();
225 SessionStorageObserverChild
* actor
=
226 new SessionStorageObserverChild(observer
);
229 contentActor
->SendPSessionStorageObserverConstructor(actor
));
231 observer
->SetActor(actor
);
233 mObserver
= std::move(observer
);
238 SessionStorageManager::~SessionStorageManager() {
239 StorageObserver
* observer
= StorageObserver::Self();
241 observer
->RemoveSink(this);
245 mActor
->SendDeleteMeInternal();
246 MOZ_ASSERT(!mActor
, "SendDeleteMeInternal should have cleared!");
250 bool SessionStorageManager::CanLoadData() {
251 AssertIsOnMainThread();
253 return mBrowsingContext
&& !mBrowsingContext
->IsDiscarded();
256 void SessionStorageManager::SetActor(SessionStorageManagerChild
* aActor
) {
257 AssertIsOnMainThread();
264 bool SessionStorageManager::ActorExists() const {
265 AssertIsOnMainThread();
270 void SessionStorageManager::ClearActor() {
271 AssertIsOnMainThread();
277 nsresult
SessionStorageManager::EnsureManager() {
278 AssertIsOnMainThread();
279 MOZ_ASSERT(CanLoadData());
285 ::mozilla::ipc::PBackgroundChild
* backgroundActor
=
286 ::mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
287 if (NS_WARN_IF(!backgroundActor
)) {
288 return NS_ERROR_FAILURE
;
291 RefPtr
<SessionStorageManagerChild
> actor
=
292 new SessionStorageManagerChild(this);
294 if (!backgroundActor
->SendPBackgroundSessionStorageManagerConstructor(
295 actor
, mBrowsingContext
->Top()->Id())) {
296 return NS_ERROR_FAILURE
;
304 SessionStorageCacheChild
* SessionStorageManager::EnsureCache(
305 nsIPrincipal
& aPrincipal
, const nsCString
& aOriginKey
,
306 SessionStorageCache
& aCache
) {
307 AssertIsOnMainThread();
308 MOZ_ASSERT(CanLoadData());
309 MOZ_ASSERT(ActorExists());
311 if (aCache
.Actor()) {
312 return aCache
.Actor();
315 mozilla::ipc::PrincipalInfo info
;
316 nsresult rv
= PrincipalToPrincipalInfo(&aPrincipal
, &info
);
322 RefPtr
<SessionStorageCacheChild
> actor
=
323 new SessionStorageCacheChild(&aCache
);
324 if (!mActor
->SendPBackgroundSessionStorageCacheConstructor(actor
, info
,
329 aCache
.SetActor(actor
);
334 nsresult
SessionStorageManager::LoadData(nsIPrincipal
& aPrincipal
,
335 SessionStorageCache
& aCache
) {
336 AssertIsOnMainThread();
339 nsAutoCString originKey
;
340 nsresult rv
= aPrincipal
.GetStorageOriginKey(originKey
);
341 if (NS_WARN_IF(NS_FAILED(rv
))) {
345 nsAutoCString originAttributes
;
346 aPrincipal
.OriginAttributesRef().CreateSuffix(originAttributes
);
348 auto* const originRecord
=
349 GetOriginRecord(originAttributes
, originKey
, true, nullptr);
350 MOZ_ASSERT(originRecord
);
352 if (originRecord
->mLoaded
) {
356 RefPtr
<SessionStorageCacheChild
> cacheActor
=
357 EnsureCache(aPrincipal
, originKey
, aCache
);
360 return NS_ERROR_FAILURE
;
363 nsTArray
<SSSetItemInfo
> data
;
364 if (!cacheActor
->SendLoad(&data
)) {
365 return NS_ERROR_FAILURE
;
368 originRecord
->mCache
->DeserializeData(data
);
370 originRecord
->mLoaded
.Flip();
371 aCache
.SetLoadedOrCloned();
376 void SessionStorageManager::CheckpointData(nsIPrincipal
& aPrincipal
,
377 SessionStorageCache
& aCache
) {
378 AssertIsOnMainThread();
381 nsAutoCString originKey
;
382 nsresult rv
= aPrincipal
.GetStorageOriginKey(originKey
);
383 if (NS_WARN_IF(NS_FAILED(rv
))) {
387 return CheckpointDataInternal(aPrincipal
, originKey
, aCache
);
390 void SessionStorageManager::CheckpointDataInternal(
391 nsIPrincipal
& aPrincipal
, const nsCString
& aOriginKey
,
392 SessionStorageCache
& aCache
) {
393 AssertIsOnMainThread();
396 nsTArray
<SSWriteInfo
> writeInfos
= aCache
.SerializeWriteInfos();
398 if (writeInfos
.IsEmpty()) {
402 RefPtr
<SessionStorageCacheChild
> cacheActor
=
403 EnsureCache(aPrincipal
, aOriginKey
, aCache
);
409 Unused
<< cacheActor
->SendCheckpoint(writeInfos
);
411 aCache
.ResetWriteInfos();
415 SessionStorageManager::PrecacheStorage(nsIPrincipal
* aPrincipal
,
416 nsIPrincipal
* aStoragePrincipal
,
418 // Nothing to preload.
423 SessionStorageManager::GetSessionStorageCache(
424 nsIPrincipal
* aPrincipal
, nsIPrincipal
* aStoragePrincipal
,
425 RefPtr
<SessionStorageCache
>* aRetVal
) {
426 return GetSessionStorageCacheHelper(aStoragePrincipal
, true, nullptr,
430 nsresult
SessionStorageManager::GetSessionStorageCacheHelper(
431 nsIPrincipal
* aPrincipal
, bool aMakeIfNeeded
,
432 SessionStorageCache
* aCloneFrom
, RefPtr
<SessionStorageCache
>* aRetVal
) {
433 nsAutoCString originKey
;
434 nsAutoCString originAttributes
;
435 nsresult rv
= aPrincipal
->GetStorageOriginKey(originKey
);
436 aPrincipal
->OriginAttributesRef().CreateSuffix(originAttributes
);
438 return NS_ERROR_NOT_AVAILABLE
;
441 return GetSessionStorageCacheHelper(originAttributes
, originKey
,
442 aMakeIfNeeded
, aCloneFrom
, aRetVal
);
445 nsresult
SessionStorageManager::GetSessionStorageCacheHelper(
446 const nsACString
& aOriginAttrs
, const nsACString
& aOriginKey
,
447 bool aMakeIfNeeded
, SessionStorageCache
* aCloneFrom
,
448 RefPtr
<SessionStorageCache
>* aRetVal
) {
449 if (OriginRecord
* const originRecord
= GetOriginRecord(
450 aOriginAttrs
, aOriginKey
, aMakeIfNeeded
, aCloneFrom
)) {
451 *aRetVal
= originRecord
->mCache
;
459 SessionStorageManager::CreateStorage(mozIDOMWindow
* aWindow
,
460 nsIPrincipal
* aPrincipal
,
461 nsIPrincipal
* aStoragePrincipal
,
462 const nsAString
& aDocumentURI
,
463 bool aPrivate
, Storage
** aRetval
) {
464 RefPtr
<SessionStorageCache
> cache
;
465 nsresult rv
= GetSessionStorageCache(aPrincipal
, aStoragePrincipal
, &cache
);
470 nsCOMPtr
<nsPIDOMWindowInner
> inner
= nsPIDOMWindowInner::From(aWindow
);
472 RefPtr
<SessionStorage
> storage
=
473 new SessionStorage(inner
, aPrincipal
, aStoragePrincipal
, cache
, this,
474 aDocumentURI
, aPrivate
);
476 storage
.forget(aRetval
);
481 SessionStorageManager::GetStorage(mozIDOMWindow
* aWindow
,
482 nsIPrincipal
* aPrincipal
,
483 nsIPrincipal
* aStoragePrincipal
,
484 bool aPrivate
, Storage
** aRetval
) {
487 RefPtr
<SessionStorageCache
> cache
;
489 GetSessionStorageCacheHelper(aStoragePrincipal
, false, nullptr, &cache
);
490 if (NS_FAILED(rv
) || !cache
) {
494 nsCOMPtr
<nsPIDOMWindowInner
> inner
= nsPIDOMWindowInner::From(aWindow
);
496 RefPtr
<SessionStorage
> storage
= new SessionStorage(
497 inner
, aPrincipal
, aStoragePrincipal
, cache
, this, u
""_ns
, aPrivate
);
499 storage
.forget(aRetval
);
504 SessionStorageManager::CloneStorage(Storage
* aStorage
) {
505 if (NS_WARN_IF(!aStorage
)) {
506 return NS_ERROR_UNEXPECTED
;
509 if (aStorage
->Type() != Storage::eSessionStorage
) {
510 return NS_ERROR_UNEXPECTED
;
513 // ToDo: At the moment, we clone the cache on the child process and then
514 // send the checkpoint. It would be nicer if we either serailizing all the
515 // data and sync to the parent process directly or clonig storage on the
516 // parnet process and sync it to the child process on demand.
518 RefPtr
<SessionStorageCache
> cache
;
519 nsresult rv
= GetSessionStorageCacheHelper(
520 aStorage
->StoragePrincipal(), true,
521 static_cast<SessionStorage
*>(aStorage
)->Cache(), &cache
);
522 if (NS_WARN_IF(NS_FAILED(rv
))) {
526 // If cache was cloned from other storage, then we shouldn't load the cache
527 // at the first access.
528 cache
->SetLoadedOrCloned();
531 rv
= EnsureManager();
532 if (NS_WARN_IF(NS_FAILED(rv
))) {
536 CheckpointData(*aStorage
->StoragePrincipal(), *cache
);
543 SessionStorageManager::CheckStorage(nsIPrincipal
* aPrincipal
, Storage
* aStorage
,
545 if (NS_WARN_IF(!aStorage
)) {
546 return NS_ERROR_UNEXPECTED
;
550 return NS_ERROR_NOT_AVAILABLE
;
555 RefPtr
<SessionStorageCache
> cache
;
557 GetSessionStorageCacheHelper(aPrincipal
, false, nullptr, &cache
);
558 if (NS_FAILED(rv
) || !cache
) {
562 if (aStorage
->Type() != Storage::eSessionStorage
) {
566 RefPtr
<SessionStorage
> sessionStorage
=
567 static_cast<SessionStorage
*>(aStorage
);
568 if (sessionStorage
->Cache() != cache
) {
572 if (!StorageUtils::PrincipalsEqual(aStorage
->StoragePrincipal(),
581 void SessionStorageManager::ClearStorages(
582 const OriginAttributesPattern
& aPattern
, const nsACString
& aOriginScope
) {
584 nsresult rv
= EnsureManager();
585 if (NS_WARN_IF(NS_FAILED(rv
))) {
589 mActor
->SendClearStorages(aPattern
, nsCString(aOriginScope
));
592 ClearStoragesInternal(aPattern
, aOriginScope
);
595 nsresult
SessionStorageManager::Observe(
596 const char* aTopic
, const nsAString
& aOriginAttributesPattern
,
597 const nsACString
& aOriginScope
) {
598 OriginAttributesPattern pattern
;
599 if (!pattern
.Init(aOriginAttributesPattern
)) {
600 NS_ERROR("Cannot parse origin attributes pattern");
601 return NS_ERROR_FAILURE
;
604 // Clear everything, caches + database
605 if (!strcmp(aTopic
, "cookie-cleared")) {
606 ClearStorages(pattern
, ""_ns
);
610 // Clear from caches everything that has been stored
611 // while in session-only mode
612 if (!strcmp(aTopic
, "session-only-cleared")) {
613 ClearStorages(pattern
, aOriginScope
);
617 // Clear everything (including so and pb data) from caches and database
618 // for the given domain and subdomains.
619 if (!strcmp(aTopic
, "browser:purge-sessionStorage")) {
620 ClearStorages(pattern
, aOriginScope
);
624 // Clear entries which match an OriginAttributesPattern.
625 if (!strcmp(aTopic
, "dom-storage:clear-origin-attributes-data") ||
626 !strcmp(aTopic
, "session-storage:clear-origin-attributes-data")) {
627 ClearStorages(pattern
, aOriginScope
);
631 if (!strcmp(aTopic
, "profile-change")) {
632 // For case caches are still referenced - clear them completely
633 ClearStorages(pattern
, ""_ns
);
641 SessionStorageManager::OriginRecord::~OriginRecord() = default;
644 void BackgroundSessionStorageManager::RemoveManager(uint64_t aTopContextId
) {
645 MOZ_ASSERT(XRE_IsParentProcess());
646 AssertIsOnMainThread();
648 ::mozilla::ipc::PBackgroundChild
* backgroundActor
=
649 ::mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
650 if (NS_WARN_IF(!backgroundActor
)) {
654 if (NS_WARN_IF(!backgroundActor
->SendRemoveBackgroundSessionStorageManager(
661 void BackgroundSessionStorageManager::PropagateManager(
662 uint64_t aCurrentTopContextId
, uint64_t aTargetTopContextId
) {
663 MOZ_ASSERT(XRE_IsParentProcess());
664 AssertIsOnMainThread();
665 MOZ_ASSERT(aCurrentTopContextId
!= aTargetTopContextId
);
667 ::mozilla::ipc::PBackgroundChild
* backgroundActor
=
668 ::mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
669 if (NS_WARN_IF(!backgroundActor
)) {
673 if (NS_WARN_IF(!backgroundActor
->SendPropagateBackgroundSessionStorageManager(
674 aCurrentTopContextId
, aTargetTopContextId
))) {
680 void BackgroundSessionStorageManager::LoadData(
681 uint64_t aTopContextId
,
682 const nsTArray
<mozilla::dom::SSCacheCopy
>& aCacheCopyList
) {
683 MOZ_ASSERT(XRE_IsParentProcess());
684 AssertIsOnMainThread();
686 ::mozilla::ipc::PBackgroundChild
* backgroundActor
=
687 ::mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
688 if (NS_WARN_IF(!backgroundActor
)) {
692 if (NS_WARN_IF(!backgroundActor
->SendLoadSessionStorageManagerData(
693 aTopContextId
, aCacheCopyList
))) {
699 BackgroundSessionStorageManager
* BackgroundSessionStorageManager::GetOrCreate(
700 uint64_t aTopContextId
) {
701 MOZ_ASSERT(XRE_IsParentProcess());
702 ::mozilla::ipc::AssertIsOnBackgroundThread();
705 sManagers
= new nsRefPtrHashtable
<nsUint64HashKey
,
706 BackgroundSessionStorageManager
>();
707 NS_DispatchToMainThread(NS_NewRunnableFunction(
708 "dom::BackgroundSessionStorageManager::GetOrCreate", [] {
711 ::mozilla::ipc::PBackgroundChild
* backgroundActor
= ::mozilla::
712 ipc::BackgroundChild::GetOrCreateForCurrentThread();
713 if (NS_WARN_IF(!backgroundActor
)) {
719 ->SendShutdownBackgroundSessionStorageManagers())) {
723 ShutdownPhase::XPCOMShutdown
);
728 ->LookupOrInsertWith(
731 return new BackgroundSessionStorageManager(aTopContextId
);
736 BackgroundSessionStorageManager::BackgroundSessionStorageManager(
737 uint64_t aBrowsingContextId
)
738 : mCurrentBrowsingContextId(aBrowsingContextId
) {
739 MOZ_ASSERT(XRE_IsParentProcess());
740 ::mozilla::ipc::AssertIsOnBackgroundThread();
743 BackgroundSessionStorageManager::~BackgroundSessionStorageManager() = default;
745 void BackgroundSessionStorageManager::CopyDataToContentProcess(
746 const nsACString
& aOriginAttrs
, const nsACString
& aOriginKey
,
747 nsTArray
<SSSetItemInfo
>& aData
) {
748 MOZ_ASSERT(XRE_IsParentProcess());
749 ::mozilla::ipc::AssertIsOnBackgroundThread();
751 auto* const originRecord
=
752 GetOriginRecord(aOriginAttrs
, aOriginKey
, false, nullptr);
757 aData
= originRecord
->mCache
->SerializeData();
761 RefPtr
<BackgroundSessionStorageManager::DataPromise
>
762 BackgroundSessionStorageManager::GetData(BrowsingContext
* aContext
,
764 bool aClearSessionStoreTimer
) {
765 MOZ_ASSERT(XRE_IsParentProcess());
766 MOZ_ASSERT(aContext
->IsTop());
768 AssertIsOnMainThread();
770 ::mozilla::ipc::PBackgroundChild
* backgroundActor
=
771 ::mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
772 if (NS_WARN_IF(!backgroundActor
)) {
773 return DataPromise::CreateAndReject(
774 ::mozilla::ipc::ResponseRejectReason::SendError
, __func__
);
777 return backgroundActor
->SendGetSessionStorageManagerData(
778 aContext
->Id(), aSizeLimit
, aClearSessionStoreTimer
);
781 void BackgroundSessionStorageManager::GetData(
782 uint32_t aSizeLimit
, nsTArray
<SSCacheCopy
>& aCacheCopyList
) {
783 for (auto& managerActor
: mParticipatingActors
) {
784 for (auto* cacheActor
:
785 managerActor
->ManagedPBackgroundSessionStorageCacheParent()) {
786 auto* cache
= static_cast<SessionStorageCacheParent
*>(cacheActor
);
787 ::mozilla::ipc::PrincipalInfo info
= cache
->PrincipalInfo();
789 OriginAttributes attributes
;
790 StoragePrincipalHelper::GetOriginAttributes(cache
->PrincipalInfo(),
793 nsAutoCString originAttrs
;
794 attributes
.CreateSuffix(originAttrs
);
797 GetOriginRecord(originAttrs
, cache
->OriginKey(), false, nullptr);
803 if (record
->mCache
->GetOriginQuotaUsage() > aSizeLimit
) {
807 nsTArray
<SSSetItemInfo
> data
= record
->mCache
->SerializeData();
808 if (data
.IsEmpty()) {
812 SSCacheCopy
& cacheCopy
= *aCacheCopyList
.AppendElement();
813 cacheCopy
.originKey() = cache
->OriginKey();
814 cacheCopy
.principalInfo() = info
;
815 cacheCopy
.data().SwapElements(data
);
820 void BackgroundSessionStorageManager::UpdateData(
821 const nsACString
& aOriginAttrs
, const nsACString
& aOriginKey
,
822 const nsTArray
<SSWriteInfo
>& aWriteInfos
) {
823 MOZ_ASSERT(XRE_IsParentProcess());
824 ::mozilla::ipc::AssertIsOnBackgroundThread();
826 auto* const originRecord
=
827 GetOriginRecord(aOriginAttrs
, aOriginKey
, true, nullptr);
828 MOZ_ASSERT(originRecord
);
830 MaybeScheduleSessionStoreUpdate();
832 originRecord
->mCache
->DeserializeWriteInfos(aWriteInfos
);
835 void BackgroundSessionStorageManager::UpdateData(
836 const nsACString
& aOriginAttrs
, const nsACString
& aOriginKey
,
837 const nsTArray
<SSSetItemInfo
>& aData
) {
838 MOZ_ASSERT(XRE_IsParentProcess());
839 ::mozilla::ipc::AssertIsOnBackgroundThread();
841 auto* const originRecord
=
842 GetOriginRecord(aOriginAttrs
, aOriginKey
, true, nullptr);
843 MOZ_ASSERT(originRecord
);
845 originRecord
->mCache
->DeserializeData(aData
);
848 void BackgroundSessionStorageManager::ClearStorages(
849 const OriginAttributesPattern
& aPattern
, const nsCString
& aOriginScope
) {
850 MOZ_ASSERT(XRE_IsParentProcess());
851 ::mozilla::ipc::AssertIsOnBackgroundThread();
852 ClearStoragesInternal(aPattern
, aOriginScope
);
855 void BackgroundSessionStorageManager::SetCurrentBrowsingContextId(
856 uint64_t aBrowsingContextId
) {
857 MOZ_DIAGNOSTIC_ASSERT(aBrowsingContextId
!= mCurrentBrowsingContextId
);
858 mCurrentBrowsingContextId
= aBrowsingContextId
;
861 void BackgroundSessionStorageManager::MaybeScheduleSessionStoreUpdate() {
862 if constexpr (!SessionStoreUtils::NATIVE_LISTENER
) {
866 if (mSessionStoreCallbackTimer
) {
870 if (StaticPrefs::browser_sessionstore_debug_no_auto_updates()) {
871 DispatchSessionStoreUpdate();
875 auto result
= NS_NewTimerWithFuncCallback(
876 [](nsITimer
*, void* aClosure
) {
877 auto* mgr
= static_cast<BackgroundSessionStorageManager
*>(aClosure
);
878 mgr
->DispatchSessionStoreUpdate();
880 this, StaticPrefs::browser_sessionstore_interval(),
881 nsITimer::TYPE_ONE_SHOT
,
882 "BackgroundSessionStorageManager::DispatchSessionStoreUpdate");
884 if (result
.isErr()) {
888 mSessionStoreCallbackTimer
= result
.unwrap();
891 void BackgroundSessionStorageManager::MaybeDispatchSessionStoreUpdate() {
892 if (mSessionStoreCallbackTimer
) {
893 BackgroundSessionStorageManager::DispatchSessionStoreUpdate();
897 void BackgroundSessionStorageManager::DispatchSessionStoreUpdate() {
898 ::mozilla::ipc::AssertIsOnBackgroundThread();
899 NS_DispatchToMainThread(NS_NewRunnableFunction(
900 "CanonicalBrowsingContext::UpdateSessionStore",
901 [targetBrowsingContextId
= mCurrentBrowsingContextId
]() {
902 CanonicalBrowsingContext::UpdateSessionStoreForStorage(
903 targetBrowsingContextId
);
906 CancelSessionStoreUpdate();
909 void BackgroundSessionStorageManager::CancelSessionStoreUpdate() {
910 if (mSessionStoreCallbackTimer
) {
911 mSessionStoreCallbackTimer
->Cancel();
912 mSessionStoreCallbackTimer
= nullptr;
916 void BackgroundSessionStorageManager::AddParticipatingActor(
917 SessionStorageManagerParent
* aActor
) {
918 ::mozilla::ipc::AssertIsOnBackgroundThread();
919 mParticipatingActors
.AppendElement(aActor
);
922 void BackgroundSessionStorageManager::RemoveParticipatingActor(
923 SessionStorageManagerParent
* aActor
) {
924 ::mozilla::ipc::AssertIsOnBackgroundThread();
925 mParticipatingActors
.RemoveElement(aActor
);
929 } // namespace mozilla