Bug 1781201 - Generate unique anonymous origins for private browsing; r=hsingh

The generated origins are cached in a hash map. There's also a hash map for
getting the original origin from a generated origin which will be needed for
metadata loading once generated origins are actually used for creating origin
directories and for creating metadata files.

The patch is partially based on D176751.

Differential Revision: https://phabricator.services.mozilla.com/D176875
This commit is contained in:
Jan Varga 2023-05-03 18:36:08 +00:00
Родитель 246e7d8ff8
Коммит 915fb54734
7 изменённых файлов: 138 добавлений и 13 удалений

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

@ -85,6 +85,7 @@
#include "mozilla/dom/quota/AssertionsImpl.h"
#include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/Constants.h"
#include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/PQuota.h"
@ -122,6 +123,7 @@
#include "nsIBinaryOutputStream.h"
#include "nsIConsoleService.h"
#include "nsIDirectoryEnumerator.h"
#include "nsIDUtils.h"
#include "nsIEventTarget.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
@ -146,6 +148,7 @@
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsPrintfCString.h"
#include "nsStandardURL.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsStringFlags.h"
@ -6451,16 +6454,40 @@ QuotaManager::GetInfoFromValidatedPrincipalInfo(
const ContentPrincipalInfo& info =
aPrincipalInfo.get_ContentPrincipalInfo();
nsCString suffix;
info.attrs().CreateSuffix(suffix);
nsCString origin = info.originNoSuffix() + suffix;
if (StringBeginsWith(origin, kUUIDOriginScheme)) {
QM_TRY_INSPECT(const auto& originalOrigin,
GetOriginFromStorageOrigin(origin));
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateContentPrincipal(originalOrigin);
QM_TRY(MOZ_TO_RESULT(principal));
PrincipalInfo principalInfo;
QM_TRY(
MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)));
return GetInfoFromValidatedPrincipalInfo(principalInfo);
}
PrincipalMetadata principalMetadata;
info.attrs().CreateSuffix(principalMetadata.mSuffix);
principalMetadata.mSuffix = suffix;
principalMetadata.mGroup = info.baseDomain() + principalMetadata.mSuffix;
principalMetadata.mGroup = info.baseDomain() + suffix;
principalMetadata.mOrigin =
info.originNoSuffix() + principalMetadata.mSuffix;
principalMetadata.mOrigin = origin;
principalMetadata.mStorageOrigin = principalMetadata.mOrigin;
if (info.attrs().mPrivateBrowsingId != 0) {
QM_TRY_UNWRAP(principalMetadata.mStorageOrigin,
EnsureStorageOriginFromOrigin(origin));
} else {
principalMetadata.mStorageOrigin = origin;
}
principalMetadata.mIsPrivate = info.attrs().mPrivateBrowsingId != 0;
@ -7095,6 +7122,59 @@ bool QuotaManager::IsSanitizedOriginValid(const nsACString& aSanitizedOrigin) {
});
}
Result<nsCString, nsresult> QuotaManager::EnsureStorageOriginFromOrigin(
const nsACString& aOrigin) {
MutexAutoLock lock(mQuotaMutex);
QM_TRY_UNWRAP(
auto storageOrigin,
mOriginToStorageOriginMap.TryLookupOrInsertWith(
aOrigin, [this, &aOrigin]() -> Result<nsCString, nsresult> {
OriginAttributes originAttributes;
nsCString originNoSuffix;
QM_TRY(MOZ_TO_RESULT(
originAttributes.PopulateFromOrigin(aOrigin, originNoSuffix)));
nsCOMPtr<nsIURI> uri;
QM_TRY(MOZ_TO_RESULT(
NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
.SetSpec(originNoSuffix)
.SetScheme("uuid"_ns)
.SetHost(NSID_TrimBracketsASCII(nsID::GenerateUUID()))
.SetPort(-1)
.Finalize(uri)));
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateContentPrincipal(uri, OriginAttributes{});
QM_TRY(MOZ_TO_RESULT(principal));
QM_TRY_UNWRAP(auto origin,
MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(
nsAutoCString, principal, GetOrigin));
mStorageOriginToOriginMap.WithEntryHandle(
origin,
[&aOrigin](auto entryHandle) { entryHandle.Insert(aOrigin); });
return nsCString(std::move(origin));
}));
return nsCString(std::move(storageOrigin));
}
Result<nsCString, nsresult> QuotaManager::GetOriginFromStorageOrigin(
const nsACString& aStorageOrigin) {
MutexAutoLock lock(mQuotaMutex);
auto maybeOrigin = mStorageOriginToOriginMap.MaybeGet(aStorageOrigin);
if (maybeOrigin.isNothing()) {
return Err(NS_ERROR_FAILURE);
}
return maybeOrigin.ref();
}
int64_t QuotaManager::GenerateDirectoryLockId() {
const int64_t directorylockId = mNextDirectoryLockId;
@ -8392,7 +8472,8 @@ nsresult GetOriginUsageOp::DoInit(QuotaManager& aQuotaManager) {
QM_TRY_UNWRAP(
PrincipalMetadata principalMetadata,
aQuotaManager.GetInfoFromValidatedPrincipalInfo(mParams.principalInfo()));
MOZ_ASSERT(principalMetadata.mOrigin == principalMetadata.mStorageOrigin);
principalMetadata.AssertInvariants();
mSuffix = std::move(principalMetadata.mSuffix);
mGroup = std::move(principalMetadata.mGroup);
@ -8671,7 +8752,8 @@ nsresult InitializeOriginRequestBase::DoInit(QuotaManager& aQuotaManager) {
QM_TRY_UNWRAP(
auto principalMetadata,
aQuotaManager.GetInfoFromValidatedPrincipalInfo(mPrincipalInfo));
MOZ_ASSERT(principalMetadata.mOrigin == principalMetadata.mStorageOrigin);
principalMetadata.AssertInvariants();
mSuffix = std::move(principalMetadata.mSuffix);
mGroup = std::move(principalMetadata.mGroup);
@ -8773,7 +8855,8 @@ nsresult GetFullOriginMetadataOp::DoInit(QuotaManager& aQuotaManager) {
QM_TRY_UNWRAP(
PrincipalMetadata principalMetadata,
aQuotaManager.GetInfoFromValidatedPrincipalInfo(mParams.principalInfo()));
MOZ_ASSERT(principalMetadata.mOrigin == principalMetadata.mStorageOrigin);
principalMetadata.AssertInvariants();
mOriginMetadata = {std::move(principalMetadata), mParams.persistenceType()};
@ -9284,7 +9367,8 @@ nsresult PersistRequestBase::DoInit(QuotaManager& aQuotaManager) {
QM_TRY_UNWRAP(
PrincipalMetadata principalMetadata,
aQuotaManager.GetInfoFromValidatedPrincipalInfo(mPrincipalInfo));
MOZ_ASSERT(principalMetadata.mOrigin == principalMetadata.mStorageOrigin);
principalMetadata.AssertInvariants();
mSuffix = std::move(principalMetadata.mSuffix);
mGroup = std::move(principalMetadata.mGroup);
@ -9448,7 +9532,8 @@ nsresult EstimateOp::DoInit(QuotaManager& aQuotaManager) {
QM_TRY_UNWRAP(
PrincipalMetadata principalMetadata,
aQuotaManager.GetInfoFromValidatedPrincipalInfo(mParams.principalInfo()));
MOZ_ASSERT(principalMetadata.mOrigin == principalMetadata.mStorageOrigin);
principalMetadata.AssertInvariants();
mOriginMetadata = {std::move(principalMetadata), PERSISTENCE_TYPE_DEFAULT};

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

@ -10,6 +10,7 @@
#include <utility>
#include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/Constants.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "nsString.h"
@ -34,7 +35,13 @@ struct PrincipalMetadata {
mOrigin{std::move(aOrigin)},
mStorageOrigin{std::move(aStorageOrigin)},
mIsPrivate{aIsPrivate} {
MOZ_ASSERT(mOrigin == mStorageOrigin);
AssertInvariants();
}
void AssertInvariants() const {
MOZ_ASSERT(!StringBeginsWith(mOrigin, kUUIDOriginScheme));
MOZ_ASSERT_IF(!mIsPrivate, mOrigin == mStorageOrigin);
MOZ_ASSERT_IF(mIsPrivate, mOrigin != mStorageOrigin);
}
};

18
dom/quota/Constants.h Normal file
Просмотреть файл

@ -0,0 +1,18 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DOM_QUOTA_CONSTANTS_H_
#define DOM_QUOTA_CONSTANTS_H_
#include "nsLiteralString.h"
namespace mozilla::dom::quota {
constexpr nsLiteralCString kUUIDOriginScheme = "uuid"_ns;
} // namespace mozilla::dom::quota
#endif // DOM_QUOTA_CONSTANTS_H_

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

@ -42,7 +42,10 @@ DirectoryLockImpl::DirectoryLockImpl(
MOZ_ASSERT_IF(!aInternal, !aGroup.IsEmpty());
MOZ_ASSERT_IF(!aInternal, aOriginScope.IsOrigin());
MOZ_ASSERT_IF(!aInternal, !aStorageOrigin.IsEmpty());
MOZ_ASSERT_IF(!aInternal, aOriginScope.GetOrigin() == aStorageOrigin);
MOZ_ASSERT_IF(!aInternal && !aIsPrivate,
aOriginScope.GetOrigin() == aStorageOrigin);
MOZ_ASSERT_IF(!aInternal && aIsPrivate,
aOriginScope.GetOrigin() != aStorageOrigin);
MOZ_ASSERT_IF(!aInternal, !aClientType.IsNull());
MOZ_ASSERT_IF(!aInternal, aClientType.Value() < Client::TypeMax());
}

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

@ -30,7 +30,8 @@ OriginInfo::OriginInfo(GroupInfo* aGroupInfo, const nsACString& aOrigin,
mPersisted(aPersisted),
mDirectoryExists(aDirectoryExists) {
MOZ_ASSERT(aGroupInfo);
MOZ_ASSERT(aOrigin == aStorageOrigin);
MOZ_ASSERT_IF(!aIsPrivate, aOrigin == aStorageOrigin);
MOZ_ASSERT_IF(aIsPrivate, aOrigin != aStorageOrigin);
MOZ_ASSERT(aClientUsages.Length() == Client::TypeMax());
MOZ_ASSERT_IF(aPersisted,
aGroupInfo->mPersistenceType == PERSISTENCE_TYPE_DEFAULT);

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

@ -577,6 +577,12 @@ class QuotaManager final : public BackgroundThreadObject {
bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
Result<nsCString, nsresult> EnsureStorageOriginFromOrigin(
const nsACString& aOrigin);
Result<nsCString, nsresult> GetOriginFromStorageOrigin(
const nsACString& aStorageOrigin);
int64_t GenerateDirectoryLockId();
bool ShutdownStarted() const;
@ -655,6 +661,10 @@ class QuotaManager final : public BackgroundThreadObject {
// it is only ever touched on the IO thread.
nsTHashMap<nsCStringHashKey, bool> mValidOrigins;
// These maps are protected by mQuotaMutex.
nsTHashMap<nsCStringHashKey, nsCString> mOriginToStorageOriginMap;
nsTHashMap<nsCStringHashKey, nsCString> mStorageOriginToOriginMap;
// This array is populated at initialization time and then never modified, so
// it can be iterated on any thread.
LazyInitializedOnce<const AutoTArray<RefPtr<Client>, Client::TYPE_MAX>>

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

@ -34,6 +34,7 @@ EXPORTS.mozilla.dom.quota += [
"ClientImpl.h",
"CommonMetadata.h",
"Config.h",
"Constants.h",
"DebugOnlyMacro.h",
"DecryptingInputStream.h",
"DecryptingInputStream_impl.h",