Bug 1711886 - Part 1: Store PrincipalInfo in SessionStorageCacheParent. r=asuth

By storing the PrincipalInfo in the parent copy it is possible to
query the BackgroundSessionStorageManager withouth the need of a
preprocessing step matching resulting data to principals using the
browsing context tree. Instead the result from the query contains the
principal info.

To be able to initialize the parent actor lazily with a principal
info, it was needed to make clearing the storage be a less fine
grained transaction. Instead of sending updates per cache, we after
clearing in the child process we send a message to the parent that in
turn performs the same steps.

Differential Revision: https://phabricator.services.mozilla.com/D125680
This commit is contained in:
Andreas Farre 2021-09-22 15:42:46 +00:00
Родитель 5ecbe6bdff
Коммит cd96fe70a4
9 изменённых файлов: 184 добавлений и 105 удалений

Просмотреть файл

@ -36,7 +36,7 @@ union SSWriteInfo
struct SSCacheCopy {
nsCString originKey;
nsCString originAttributes;
PrincipalInfo principalInfo;
SSSetItemInfo[] data;
};

Просмотреть файл

@ -4,6 +4,10 @@
include protocol PBackground;
include protocol PBackgroundSessionStorageCache;
include PBackgroundSharedTypes;
using mozilla::OriginAttributesPattern
from "mozilla/OriginAttributes.h";
namespace mozilla {
namespace dom {
@ -14,7 +18,9 @@ namespace dom {
manages PBackgroundSessionStorageCache;
parent:
async PBackgroundSessionStorageCache(nsCString aOriginAttrs, nsCString aOriginKey);
async PBackgroundSessionStorageCache(PrincipalInfo aPrincipalInfo, nsCString aOriginKey);
async ClearStorages(OriginAttributesPattern aPattern, nsCString aOriginScope);
async DeleteMe();

Просмотреть файл

@ -8,6 +8,7 @@
#include "LocalStorageManager.h"
#include "StorageIPC.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/LSWriteOptimizer.h"
#include "mozilla/dom/PBackgroundSessionStorageCache.h"
#include "nsDOMString.h"

Просмотреть файл

@ -11,8 +11,7 @@
#include "mozilla/dom/LSWriteOptimizerImpl.h"
#include "nsTHashMap.h"
namespace mozilla {
namespace dom {
namespace mozilla::dom {
class SSSetItemInfo;
class SSWriteInfo;
@ -95,7 +94,6 @@ class SessionStorageCache final {
bool mLoadedOrCloned;
};
} // namespace dom
} // namespace mozilla
} // namespace mozilla::dom
#endif // mozilla_dom_SessionStorageCache_h

Просмотреть файл

@ -95,8 +95,14 @@ bool RecvLoadSessionStorageData(
}
for (const auto& cacheInit : aCacheCopyList) {
manager->UpdateData(cacheInit.originAttributes(), cacheInit.originKey(),
cacheInit.data());
OriginAttributes attrs;
StoragePrincipalHelper::GetOriginAttributes(cacheInit.principalInfo(),
attrs);
nsAutoCString originAttrs;
attrs.CreateSuffix(originAttrs);
manager->UpdateData(originAttrs, cacheInit.originKey(), cacheInit.data());
}
return true;
@ -128,6 +134,29 @@ bool RecvGetSessionStorageData(
return true;
}
void SessionStorageManagerBase::ClearStoragesInternal(
const OriginAttributesPattern& aPattern, const nsACString& aOriginScope) {
for (const auto& oaEntry : mOATable) {
OriginAttributes oa;
DebugOnly<bool> ok = oa.PopulateFromSuffix(oaEntry.GetKey());
MOZ_ASSERT(ok);
if (!aPattern.Matches(oa)) {
// This table doesn't match the given origin attributes pattern
continue;
}
OriginKeyHashTable* table = oaEntry.GetWeak();
for (const auto& originKeyEntry : *table) {
if (aOriginScope.IsEmpty() ||
StringBeginsWith(originKeyEntry.GetKey(), aOriginScope)) {
const auto cache = originKeyEntry.GetData()->mCache;
cache->Clear(false);
cache->ResetWriteInfos();
}
}
}
}
SessionStorageManagerBase::OriginRecord*
SessionStorageManagerBase::GetOriginRecord(
const nsACString& aOriginAttrs, const nsACString& aOriginKey,
@ -261,11 +290,11 @@ nsresult SessionStorageManager::EnsureManager() {
RefPtr<SessionStorageManagerChild> actor =
new SessionStorageManagerChild(this);
MOZ_ASSERT(actor);
MOZ_ALWAYS_TRUE(
backgroundActor->SendPBackgroundSessionStorageManagerConstructor(
actor, mBrowsingContext->Top()->Id()));
if (!backgroundActor->SendPBackgroundSessionStorageManagerConstructor(
actor, mBrowsingContext->Top()->Id())) {
return NS_ERROR_FAILURE;
}
SetActor(actor);
@ -273,7 +302,7 @@ nsresult SessionStorageManager::EnsureManager() {
}
SessionStorageCacheChild* SessionStorageManager::EnsureCache(
const nsCString& aOriginAttrs, const nsCString& aOriginKey,
nsIPrincipal& aPrincipal, const nsCString& aOriginKey,
SessionStorageCache& aCache) {
AssertIsOnMainThread();
MOZ_ASSERT(CanLoadData());
@ -283,10 +312,19 @@ SessionStorageCacheChild* SessionStorageManager::EnsureCache(
return aCache.Actor();
}
mozilla::ipc::PrincipalInfo info;
nsresult rv = PrincipalToPrincipalInfo(&aPrincipal, &info);
if (NS_FAILED(rv)) {
return nullptr;
}
RefPtr<SessionStorageCacheChild> actor =
new SessionStorageCacheChild(&aCache);
MOZ_ALWAYS_TRUE(mActor->SendPBackgroundSessionStorageCacheConstructor(
actor, aOriginAttrs, aOriginKey));
if (!mActor->SendPBackgroundSessionStorageCacheConstructor(actor, info,
aOriginKey)) {
return nullptr;
}
aCache.SetActor(actor);
@ -316,7 +354,11 @@ nsresult SessionStorageManager::LoadData(nsIPrincipal& aPrincipal,
}
RefPtr<SessionStorageCacheChild> cacheActor =
EnsureCache(originAttributes, originKey, aCache);
EnsureCache(aPrincipal, originKey, aCache);
if (!cacheActor) {
return NS_ERROR_FAILURE;
}
nsTArray<SSSetItemInfo> data;
if (!cacheActor->SendLoad(&data)) {
@ -342,14 +384,11 @@ void SessionStorageManager::CheckpointData(nsIPrincipal& aPrincipal,
return;
}
nsAutoCString originAttributes;
aPrincipal.OriginAttributesRef().CreateSuffix(originAttributes);
return CheckpointDataInternal(originAttributes, originKey, aCache);
return CheckpointDataInternal(aPrincipal, originKey, aCache);
}
void SessionStorageManager::CheckpointDataInternal(
const nsCString& aOriginAttrs, const nsCString& aOriginKey,
nsIPrincipal& aPrincipal, const nsCString& aOriginKey,
SessionStorageCache& aCache) {
AssertIsOnMainThread();
MOZ_ASSERT(mActor);
@ -361,7 +400,11 @@ void SessionStorageManager::CheckpointDataInternal(
}
RefPtr<SessionStorageCacheChild> cacheActor =
EnsureCache(aOriginAttrs, aOriginKey, aCache);
EnsureCache(aPrincipal, aOriginKey, aCache);
if (!cacheActor) {
return;
}
Unused << cacheActor->SendCheckpoint(writeInfos);
@ -467,7 +510,7 @@ SessionStorageManager::CloneStorage(Storage* aStorage) {
return NS_ERROR_UNEXPECTED;
}
// ToDo: At the momnet, we clone the cache on the child process and then
// ToDo: At the moment, we clone the cache on the child process and then
// send the checkpoint. It would be nicer if we either serailizing all the
// data and sync to the parent process directly or clonig storage on the
// parnet process and sync it to the child process on demand.
@ -542,32 +585,11 @@ void SessionStorageManager::ClearStorages(
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
mActor->SendClearStorages(aPattern, nsCString(aOriginScope));
}
for (const auto& oaEntry : mOATable) {
OriginAttributes oa;
DebugOnly<bool> ok = oa.PopulateFromSuffix(oaEntry.GetKey());
MOZ_ASSERT(ok);
if (!aPattern.Matches(oa)) {
// This table doesn't match the given origin attributes pattern
continue;
}
OriginKeyHashTable* table = oaEntry.GetWeak();
for (const auto& originKeyEntry : *table) {
if (aOriginScope.IsEmpty() ||
StringBeginsWith(originKeyEntry.GetKey(), aOriginScope)) {
const auto cache = originKeyEntry.GetData()->mCache;
cache->Clear(false);
if (CanLoadData()) {
MOZ_ASSERT(ActorExists());
CheckpointDataInternal(nsCString{oaEntry.GetKey()},
nsCString{originKeyEntry.GetKey()}, *cache);
}
}
}
}
ClearStoragesInternal(aPattern, aOriginScope);
}
nsresult SessionStorageManager::Observe(
@ -758,23 +780,38 @@ BackgroundSessionStorageManager::GetData(BrowsingContext* aContext,
void BackgroundSessionStorageManager::GetData(
uint32_t aSizeLimit, nsTArray<SSCacheCopy>& aCacheCopyList) {
for (auto attributesIter = mOATable.ConstIter(); !attributesIter.Done();
attributesIter.Next()) {
for (auto originIter = attributesIter.UserData()->ConstIter();
!originIter.Done(); originIter.Next()) {
const auto& cache = originIter.UserData()->mCache;
if (cache->GetOriginQuotaUsage() > aSizeLimit) {
for (auto& managerActor : mParticipatingActors) {
for (auto* cacheActor :
managerActor->ManagedPBackgroundSessionStorageCacheParent()) {
auto* cache = static_cast<SessionStorageCacheParent*>(cacheActor);
::mozilla::ipc::PrincipalInfo info = cache->PrincipalInfo();
OriginAttributes attributes;
StoragePrincipalHelper::GetOriginAttributes(cache->PrincipalInfo(),
attributes);
nsAutoCString originAttrs;
attributes.CreateSuffix(originAttrs);
auto* record =
GetOriginRecord(originAttrs, cache->OriginKey(), false, nullptr);
if (!record) {
continue;
}
nsTArray<SSSetItemInfo> data = cache->SerializeData();
if (record->mCache->GetOriginQuotaUsage() > aSizeLimit) {
continue;
}
nsTArray<SSSetItemInfo> data = record->mCache->SerializeData();
if (data.IsEmpty()) {
continue;
}
SSCacheCopy& cacheCopy = *aCacheCopyList.AppendElement();
cacheCopy.originKey() = originIter.Key();
cacheCopy.originAttributes() = attributesIter.Key();
cacheCopy.originKey() = cache->OriginKey();
cacheCopy.principalInfo() = info;
cacheCopy.data().SwapElements(data);
}
}
@ -808,6 +845,13 @@ void BackgroundSessionStorageManager::UpdateData(
originRecord->mCache->DeserializeData(aData);
}
void BackgroundSessionStorageManager::ClearStorages(
const OriginAttributesPattern& aPattern, const nsCString& aOriginScope) {
MOZ_ASSERT(XRE_IsParentProcess());
::mozilla::ipc::AssertIsOnBackgroundThread();
ClearStoragesInternal(aPattern, aOriginScope);
}
void BackgroundSessionStorageManager::SetCurrentBrowsingContextId(
uint64_t aBrowsingContextId) {
MOZ_DIAGNOSTIC_ASSERT(aBrowsingContextId != mCurrentBrowsingContextId);
@ -869,5 +913,17 @@ void BackgroundSessionStorageManager::CancelSessionStoreUpdate() {
}
}
void BackgroundSessionStorageManager::AddParticipatingActor(
SessionStorageManagerParent* aActor) {
::mozilla::ipc::AssertIsOnBackgroundThread();
mParticipatingActors.AppendElement(aActor);
}
void BackgroundSessionStorageManager::RemoveParticipatingActor(
SessionStorageManagerParent* aActor) {
::mozilla::ipc::AssertIsOnBackgroundThread();
mParticipatingActors.RemoveElement(aActor);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -89,6 +89,9 @@ class SessionStorageManagerBase {
FlippedOnce<false> mLoaded;
};
void ClearStoragesInternal(const OriginAttributesPattern& aPattern,
const nsACString& aOriginScope);
OriginRecord* GetOriginRecord(const nsACString& aOriginAttrs,
const nsACString& aOriginKey,
bool aMakeIfNeeded,
@ -146,11 +149,11 @@ class SessionStorageManager final : public SessionStorageManagerBase,
void ClearStorages(const OriginAttributesPattern& aPattern,
const nsACString& aOriginScope);
SessionStorageCacheChild* EnsureCache(const nsCString& aOriginAttrs,
SessionStorageCacheChild* EnsureCache(nsIPrincipal& aPrincipal,
const nsCString& aOriginKey,
SessionStorageCache& aCache);
void CheckpointDataInternal(const nsCString& aOriginAttrs,
void CheckpointDataInternal(nsIPrincipal& aPrincipal,
const nsCString& aOriginKey,
SessionStorageCache& aCache);
@ -203,12 +206,19 @@ class BackgroundSessionStorageManager final : public SessionStorageManagerBase {
void UpdateData(const nsACString& aOriginAttrs, const nsACString& aOriginKey,
const nsTArray<SSSetItemInfo>& aData);
void ClearStorages(const OriginAttributesPattern& aPattern,
const nsCString& aOriginScope);
void SetCurrentBrowsingContextId(uint64_t aBrowsingContextId);
void MaybeDispatchSessionStoreUpdate();
void CancelSessionStoreUpdate();
void AddParticipatingActor(SessionStorageManagerParent* aActor);
void RemoveParticipatingActor(SessionStorageManagerParent* aActor);
private:
// Only be called by GetOrCreate() on the parent process.
explicit BackgroundSessionStorageManager(uint64_t aBrowsingContextId);
@ -253,6 +263,8 @@ class BackgroundSessionStorageManager final : public SessionStorageManagerBase {
// they use async-returns so the response is inherently matched up via
// the issued promise).
nsCOMPtr<nsITimer> mSessionStoreCallbackTimer;
nsTArray<RefPtr<SessionStorageManagerParent>> mParticipatingActors;
};
} // namespace dom

Просмотреть файл

@ -19,6 +19,7 @@
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/StoragePrincipalHelper.h"
#include "mozilla/Unused.h"
#include "nsCOMPtr.h"
#include "nsIPrincipal.h"
@ -1331,9 +1332,9 @@ nsresult SessionStorageObserverParent::Observe(
}
SessionStorageCacheParent::SessionStorageCacheParent(
const nsCString& aOriginAttrs, const nsCString& aOriginKey,
SessionStorageManagerParent* aActor)
: mOriginAttrs(aOriginAttrs),
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey, SessionStorageManagerParent* aActor)
: mPrincipalInfo(aPrincipalInfo),
mOriginKey(aOriginKey),
mManagerActor(aActor) {
::mozilla::ipc::AssertIsOnBackgroundThread();
@ -1358,7 +1359,14 @@ mozilla::ipc::IPCResult SessionStorageCacheParent::RecvLoad(
RefPtr<BackgroundSessionStorageManager> manager = mManagerActor->GetManager();
MOZ_ASSERT(manager);
manager->CopyDataToContentProcess(mOriginAttrs, mOriginKey, *aData);
OriginAttributes attrs;
MOZ_ALWAYS_TRUE(
StoragePrincipalHelper::GetOriginAttributes(mPrincipalInfo, attrs));
nsAutoCString originAttrs;
attrs.CreateSuffix(originAttrs);
manager->CopyDataToContentProcess(originAttrs, mOriginKey, *aData);
return IPC_OK();
}
@ -1371,7 +1379,13 @@ mozilla::ipc::IPCResult SessionStorageCacheParent::RecvCheckpoint(
RefPtr<BackgroundSessionStorageManager> manager = mManagerActor->GetManager();
MOZ_ASSERT(manager);
manager->UpdateData(mOriginAttrs, mOriginKey, aWriteInfos);
OriginAttributes attrs;
StoragePrincipalHelper::GetOriginAttributes(mPrincipalInfo, attrs);
nsAutoCString originAttrs;
attrs.CreateSuffix(originAttrs);
manager->UpdateData(originAttrs, mOriginKey, aWriteInfos);
return IPC_OK();
}
@ -1395,6 +1409,7 @@ SessionStorageManagerParent::SessionStorageManagerParent(uint64_t aTopContextId)
BackgroundSessionStorageManager::GetOrCreate(aTopContextId)) {
::mozilla::ipc::AssertIsOnBackgroundThread();
MOZ_ASSERT(mBackgroundManager);
mBackgroundManager->AddParticipatingActor(this);
}
SessionStorageManagerParent::~SessionStorageManagerParent() = default;
@ -1402,13 +1417,17 @@ SessionStorageManagerParent::~SessionStorageManagerParent() = default;
void SessionStorageManagerParent::ActorDestroy(ActorDestroyReason aWhy) {
::mozilla::ipc::AssertIsOnBackgroundThread();
if (mBackgroundManager) {
mBackgroundManager->RemoveParticipatingActor(this);
}
mBackgroundManager = nullptr;
}
already_AddRefed<PBackgroundSessionStorageCacheParent>
SessionStorageManagerParent::AllocPBackgroundSessionStorageCacheParent(
const nsCString& aOriginAttrs, const nsCString& aOriginKey) {
return MakeAndAddRef<SessionStorageCacheParent>(aOriginAttrs, aOriginKey,
const PrincipalInfo& aPrincipalInfo, const nsCString& aOriginKey) {
return MakeAndAddRef<SessionStorageCacheParent>(aPrincipalInfo, aOriginKey,
this);
}
@ -1417,10 +1436,19 @@ BackgroundSessionStorageManager* SessionStorageManagerParent::GetManager()
return mBackgroundManager;
}
mozilla::ipc::IPCResult SessionStorageManagerParent::RecvClearStorages(
const OriginAttributesPattern& aPattern, const nsCString& aOriginScope) {
::mozilla::ipc::AssertIsOnBackgroundThread();
mBackgroundManager->ClearStorages(aPattern, aOriginScope);
return IPC_OK();
}
mozilla::ipc::IPCResult SessionStorageManagerParent::RecvDeleteMe() {
::mozilla::ipc::AssertIsOnBackgroundThread();
MOZ_ASSERT(mBackgroundManager);
mBackgroundManager->RemoveParticipatingActor(this);
mBackgroundManager = nullptr;
IProtocol* mgr = Manager();

Просмотреть файл

@ -509,19 +509,22 @@ class SessionStorageObserverParent final : public PSessionStorageObserverParent,
class SessionStorageCacheParent final
: public PBackgroundSessionStorageCacheParent {
friend class PBackgroundSessionStorageCacheParent;
const nsCString mOriginAttrs;
const PrincipalInfo mPrincipalInfo;
const nsCString mOriginKey;
RefPtr<SessionStorageManagerParent> mManagerActor;
FlippedOnce<false> mLoadReceived;
public:
SessionStorageCacheParent(const nsCString& aOriginAttrs,
SessionStorageCacheParent(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
SessionStorageManagerParent* aActor);
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::SessionStorageCacheParent, override)
const PrincipalInfo& PrincipalInfo() const { return mPrincipalInfo; }
const nsCString& OriginKey() const { return mOriginKey; }
private:
~SessionStorageCacheParent();
@ -550,10 +553,15 @@ class SessionStorageManagerParent final
already_AddRefed<PBackgroundSessionStorageCacheParent>
AllocPBackgroundSessionStorageCacheParent(
const nsCString& aOriginAttrs, const nsCString& aOriginKey) override;
const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey) override;
BackgroundSessionStorageManager* GetManager() const;
mozilla::ipc::IPCResult RecvClearStorages(
const OriginAttributesPattern& aPattern,
const nsCString& aOriginScope) override;
private:
~SessionStorageManagerParent();
@ -594,8 +602,9 @@ bool DeallocPSessionStorageObserverParent(
PSessionStorageObserverParent* aActor);
already_AddRefed<PBackgroundSessionStorageCacheParent>
AllocPBackgroundSessionStorageCacheParent(const nsCString& aOriginAttrs,
const nsCString& aOriginKey);
AllocPBackgroundSessionStorageCacheParent(
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey);
already_AddRefed<PBackgroundSessionStorageManagerParent>
AllocPBackgroundSessionStorageManagerParent(const uint64_t& aTopContextId);

Просмотреть файл

@ -1567,8 +1567,7 @@ void SessionStoreUtils::RestoreSessionStorageFromParent(
SSCacheCopy& cacheInit = *cacheInitList.AppendElement();
cacheInit.originKey() = originKey;
storagePrincipal->OriginAttributesRef().CreateSuffix(
cacheInit.originAttributes());
PrincipalToPrincipalInfo(storagePrincipal, &cacheInit.principalInfo());
for (const auto& entry : originEntry.mValue.Entries()) {
SSSetItemInfo& setItemInfo = *cacheInit.data().AppendElement();
@ -1680,39 +1679,9 @@ nsresult SessionStoreUtils::ConstructSessionStorageValues(
return NS_ERROR_FAILURE;
}
// We wish to remove this step of mapping originAttributes+originKey
// to a storage principal in Bug 1711886 by consolidating the
// storage format in SessionStorageManagerBase and Session Store.
nsTHashMap<nsCStringHashKey, nsIPrincipal*> storagePrincipalList;
aBrowsingContext->PreOrderWalk([&storagePrincipalList](
BrowsingContext* aContext) {
WindowGlobalParent* windowParent =
aContext->Canonical()->GetCurrentWindowGlobal();
if (!windowParent) {
return;
}
nsIPrincipal* storagePrincipal = windowParent->DocumentStoragePrincipal();
if (!storagePrincipal) {
return;
}
const OriginAttributes& originAttributes =
storagePrincipal->OriginAttributesRef();
nsAutoCString originAttributesSuffix;
originAttributes.CreateSuffix(originAttributesSuffix);
nsAutoCString originKey;
storagePrincipal->GetStorageOriginKey(originKey);
storagePrincipalList.InsertOrUpdate(originAttributesSuffix + originKey,
storagePrincipal);
});
for (const auto& value : aValues) {
nsIPrincipal* storagePrincipal =
storagePrincipalList.Get(value.originAttributes() + value.originKey());
if (!storagePrincipal) {
auto storagePrincipal = PrincipalInfoToPrincipal(value.principalInfo());
if (storagePrincipal.isErr()) {
continue;
}
@ -1722,7 +1691,7 @@ nsresult SessionStoreUtils::ConstructSessionStorageValues(
return NS_ERROR_FAILURE;
}
if (NS_FAILED(storagePrincipal->GetOrigin(entry->mKey))) {
if (NS_FAILED(storagePrincipal.inspect()->GetOrigin(entry->mKey))) {
return NS_ERROR_FAILURE;
}