Bug 1694993 - Part 6: Preserve precursor principal through LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, r=ckerschb,smaug

If we don't preserve the precursor principal in this case, we'll end up
doing an unnecessary process switch in some cases, which lead to a
test failure.

This patch also cleans up some logic around the first party origin
attribute with null principals, as the logic was only used in one place
and generally added some unnecessary complexity to NullPrincipal
itself.

Differential Revision: https://phabricator.services.mozilla.com/D155277
This commit is contained in:
Nika Layzell 2022-09-20 23:29:08 +00:00
Родитель cfdd2c8fad
Коммит 613c259d7c
9 изменённых файлов: 71 добавлений и 108 удалений

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

@ -46,29 +46,27 @@ NullPrincipal::NullPrincipal(nsIURI* aURI, const nsACString& aOriginNoSuffix,
already_AddRefed<NullPrincipal> NullPrincipal::CreateWithInheritedAttributes(
nsIPrincipal* aInheritFrom) {
MOZ_ASSERT(aInheritFrom);
return CreateInternal(Cast(aInheritFrom)->OriginAttributesRef(), false,
nullptr, aInheritFrom);
}
/* static */
already_AddRefed<NullPrincipal> NullPrincipal::CreateWithInheritedAttributes(
nsIDocShell* aDocShell, bool aIsFirstParty) {
MOZ_ASSERT(aDocShell);
OriginAttributes attrs = nsDocShell::Cast(aDocShell)->GetOriginAttributes();
return CreateWithInheritedAttributes(attrs, aIsFirstParty);
}
/* static */
already_AddRefed<NullPrincipal> NullPrincipal::CreateWithInheritedAttributes(
const OriginAttributes& aOriginAttributes, bool aIsFirstParty) {
return CreateInternal(aOriginAttributes, aIsFirstParty);
nsCOMPtr<nsIURI> uri = CreateURI(aInheritFrom);
return Create(Cast(aInheritFrom)->OriginAttributesRef(), uri);
}
/* static */
already_AddRefed<NullPrincipal> NullPrincipal::Create(
const OriginAttributes& aOriginAttributes, nsIURI* aURI) {
return CreateInternal(aOriginAttributes, false, aURI);
const OriginAttributes& aOriginAttributes, nsIURI* aNullPrincipalURI) {
nsCOMPtr<nsIURI> uri = aNullPrincipalURI;
if (!uri) {
uri = NullPrincipal::CreateURI(nullptr);
}
MOZ_RELEASE_ASSERT(uri->SchemeIs(NS_NULLPRINCIPAL_SCHEME));
nsAutoCString originNoSuffix;
DebugOnly<nsresult> rv = uri->GetSpec(originNoSuffix);
MOZ_ASSERT(NS_SUCCEEDED(rv));
RefPtr<NullPrincipal> nullPrin =
new NullPrincipal(uri, originNoSuffix, aOriginAttributes);
return nullPrin.forget();
}
/* static */
@ -152,40 +150,6 @@ already_AddRefed<nsIURI> NullPrincipal::CreateURI(
return uri.forget();
}
already_AddRefed<NullPrincipal> NullPrincipal::CreateInternal(
const OriginAttributes& aOriginAttributes, bool aIsFirstParty, nsIURI* aURI,
nsIPrincipal* aPrecursor) {
MOZ_ASSERT_IF(aPrecursor, !aURI);
nsCOMPtr<nsIURI> uri = aURI;
if (!uri) {
uri = NullPrincipal::CreateURI(aPrecursor);
}
MOZ_RELEASE_ASSERT(uri->SchemeIs(NS_NULLPRINCIPAL_SCHEME));
nsAutoCString originNoSuffix;
DebugOnly<nsresult> rv = uri->GetSpec(originNoSuffix);
MOZ_ASSERT(NS_SUCCEEDED(rv));
OriginAttributes attrs(aOriginAttributes);
if (aIsFirstParty) {
// The FirstPartyDomain attribute will not include information about the
// precursor origin.
nsAutoCString path;
rv = uri->GetFilePath(path);
MOZ_ASSERT(NS_SUCCEEDED(rv));
// remove the '{}' characters from both ends.
path.Mid(path, 1, path.Length() - 2);
path.AppendLiteral(".mozilla");
attrs.SetFirstPartyDomain(true, path);
}
RefPtr<NullPrincipal> nullPrin =
new NullPrincipal(uri, originNoSuffix, attrs);
return nullPrin.forget();
}
nsresult NullPrincipal::GetScriptLocation(nsACString& aStr) {
return mURI->GetSpec(aStr);
}

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

@ -50,20 +50,21 @@ class NullPrincipal final : public BasePrincipal {
NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
NS_IMETHOD GetPrecursorPrincipal(nsIPrincipal** aPrecursor) override;
// Create a NullPrincipal, inheriting origin attributes from the given
// principal.
// If aInheritFrom is a content principal, or has a content principal
// precursor, it will be used as the precursor for this principal.
static already_AddRefed<NullPrincipal> CreateWithInheritedAttributes(
nsIPrincipal* aInheritFrom);
// Create NullPrincipal with origin attributes from docshell.
// If aIsFirstParty is true, and the pref 'privacy.firstparty.isolate' is also
// enabled, the mFirstPartyDomain value of the origin attributes will be set
// to an unique value.
static already_AddRefed<NullPrincipal> CreateWithInheritedAttributes(
nsIDocShell* aDocShell, bool aIsFirstParty = false);
static already_AddRefed<NullPrincipal> CreateWithInheritedAttributes(
const OriginAttributes& aOriginAttributes, bool aIsFirstParty = false);
// Create a new NullPrincipal with the specified OriginAttributes.
//
// If `aNullPrincipalURI` is specified, it must be a NS_NULLPRINCIPAL_SCHEME
// URI previously created using `NullPrincipal::CreateURI`, and will be used
// as the origin URI for this principal.
static already_AddRefed<NullPrincipal> Create(
const OriginAttributes& aOriginAttributes, nsIURI* aURI = nullptr);
const OriginAttributes& aOriginAttributes,
nsIURI* aNullPrincipalURI = nullptr);
static already_AddRefed<NullPrincipal> CreateWithoutOriginAttributes();
@ -115,20 +116,10 @@ class NullPrincipal final : public BasePrincipal {
const nsCOMPtr<nsIURI> mURI;
private:
FRIEND_TEST(OriginAttributes, NullPrincipal);
FRIEND_TEST(NullPrincipalPrecursor, EscapingRoundTrips);
static void EscapePrecursorQuery(nsACString& aPrecursorQuery);
static void UnescapePrecursorQuery(nsACString& aPrecursorQuery);
// If aIsFirstParty is true, this NullPrincipal will be initialized based on
// the aOriginAttributes with FirstPartyDomain set to a unique value. This
// value is generated from mURI.filePath, with ".mozilla" appended at the end.
// aURI is used for testing purpose to assign a specific UUID rather than a
// randomly generated one.
static already_AddRefed<NullPrincipal> CreateInternal(
const OriginAttributes& aOriginAttributes, bool aIsFirstParty,
nsIURI* aURI = nullptr, nsIPrincipal* aPrecursor = nullptr);
};
} // namespace mozilla

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

@ -13,6 +13,7 @@
#include "nsIURI.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsString.h"
#include "nsURLHelper.h"
static const char kSourceChar = ':';
@ -78,6 +79,21 @@ static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument,
return;
}
// If a null principal URI was provided, extract the UUID portion of the URI
// to use for the first-party domain.
if (scheme.EqualsLiteral("moz-nullprincipal")) {
// Get the UUID portion of the URI, ignoring the precursor principal.
nsAutoCString filePath;
rv = aURI->GetFilePath(filePath);
MOZ_ASSERT(NS_SUCCEEDED(rv));
// Remove the `{}` characters from both ends.
filePath.Mid(filePath, 1, filePath.Length() - 2);
filePath.AppendLiteral(".mozilla");
// Store the generated file path.
topLevelInfo = NS_ConvertUTF8toUTF16(filePath);
return;
}
// Add-on principals should never get any first-party domain
// attributes in order to guarantee their storage integrity when switching
// FPI on and off.

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

@ -72,6 +72,12 @@ TEST(OriginAttributes, FirstPartyDomain_default)
TEST_FPD(u"about:config",
u"about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla");
TEST_FPD(u"moz-extension://f5b6ca10-5bd4-4ed6-9baf-820dc5152bc1", u"");
TEST_FPD(u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}",
u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla");
TEST_FPD(
u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}"
u"?https://www.example.com",
u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla");
Preferences::SetBool(FPI_PREF, oldFpiPref);
Preferences::SetBool(SITE_PREF, oldSitePref);
@ -98,28 +104,12 @@ TEST(OriginAttributes, FirstPartyDomain_site)
TEST_FPD(u"about:config",
u"(about,about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla)");
TEST_FPD(u"moz-extension://f5b6ca10-5bd4-4ed6-9baf-820dc5152bc1", u"");
Preferences::SetBool(FPI_PREF, oldFpiPref);
Preferences::SetBool(SITE_PREF, oldSitePref);
}
TEST(OriginAttributes, NullPrincipal)
{
bool oldFpiPref = Preferences::GetBool(FPI_PREF);
Preferences::SetBool(FPI_PREF, true);
bool oldSitePref = Preferences::GetBool(SITE_PREF);
Preferences::SetBool(SITE_PREF, true);
constexpr auto spec =
u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}"_ns;
constexpr auto expected = u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"_ns;
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), spec);
RefPtr<NullPrincipal> prin =
NullPrincipal::CreateInternal(OriginAttributes(), true, uri);
EXPECT_TRUE(prin->OriginAttributesRef().mFirstPartyDomain.Equals(expected));
TEST_FPD(u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}",
u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla");
TEST_FPD(
u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}"
u"?https://www.example.com",
u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla");
Preferences::SetBool(FPI_PREF, oldFpiPref);
Preferences::SetBool(SITE_PREF, oldSitePref);

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

@ -1755,9 +1755,7 @@ nsresult CanonicalBrowsingContext::PendingRemotenessChange::FinishSubframe() {
}
nsCOMPtr<nsIPrincipal> initialPrincipal =
NullPrincipal::CreateWithInheritedAttributes(
target->OriginAttributesRef(),
/* isFirstParty */ false);
NullPrincipal::Create(target->OriginAttributesRef());
WindowGlobalInit windowInit =
WindowGlobalActor::AboutBlankInitializer(target, initialPrincipal);

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

@ -6725,7 +6725,7 @@ nsresult nsDocShell::CreateAboutBlankContentViewer(
if (aPrincipal) {
principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
} else {
principal = NullPrincipal::CreateWithInheritedAttributes(this);
principal = NullPrincipal::Create(GetOriginAttributes());
}
partitionedPrincipal = principal;
} else {
@ -12071,7 +12071,7 @@ nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
// URIs will pick it up from the about:blank page we just loaded,
// and we don't really want even that in this case.
nsCOMPtr<nsIPrincipal> principal =
NullPrincipal::CreateWithInheritedAttributes(this);
NullPrincipal::Create(GetOriginAttributes());
aLoadState->SetTriggeringPrincipal(principal);
}
}

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

@ -819,8 +819,7 @@ nsresult nsDocShellLoadState::SetupInheritingPrincipal(
//
// We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
// have origin attributes.
mPrincipalToInherit = NullPrincipal::CreateWithInheritedAttributes(
aOriginAttributes, false);
mPrincipalToInherit = NullPrincipal::Create(aOriginAttributes);
mInheritPrincipal = false;
}
}
@ -832,10 +831,16 @@ nsresult nsDocShellLoadState::SetupInheritingPrincipal(
if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
mInheritPrincipal = false;
// Create a new null principal URI based on our precursor principal.
nsCOMPtr<nsIURI> nullPrincipalURI =
NullPrincipal::CreateURI(mPrincipalToInherit);
// If mFirstParty is true and the pref 'privacy.firstparty.isolate' is
// enabled, we will set firstPartyDomain on the origin attributes.
mPrincipalToInherit = NullPrincipal::CreateWithInheritedAttributes(
aOriginAttributes, mFirstParty);
OriginAttributes attrs(aOriginAttributes);
if (mFirstParty) {
attrs.SetFirstPartyDomain(true, nullPrincipalURI);
}
mPrincipalToInherit = NullPrincipal::Create(attrs, nullPrincipalURI);
}
return NS_OK;

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

@ -995,8 +995,7 @@ TestHTTPAnswerRunnable::Notify(nsITimer* aTimer) {
}
mozilla::OriginAttributes attrs = origLoadInfo->GetOriginAttributes();
RefPtr<nsIPrincipal> nullPrincipal =
mozilla::NullPrincipal::CreateWithInheritedAttributes(attrs);
RefPtr<nsIPrincipal> nullPrincipal = mozilla::NullPrincipal::Create(attrs);
uint32_t loadFlags =
nsIRequest::LOAD_ANONYMOUS | nsIRequest::INHIBIT_CACHING |

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

@ -839,8 +839,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// inherit origin attributes from the system principal, so use the parent
// BC if it's available.
if (parentBC) {
newWindowPrincipal = NullPrincipal::CreateWithInheritedAttributes(
parentBC->OriginAttributesRef());
newWindowPrincipal =
NullPrincipal::Create(parentBC->OriginAttributesRef());
} else {
newWindowPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
}