Bug 1260931 - Part 3: Propagate firstPartyDomain. r=smaug

This commit is contained in:
Yoshi Huang 2016-08-26 12:41:37 +08:00
parent 1f96f1431b
commit 6cca1d0c54
6 changed files with 87 additions and 31 deletions

View File

@ -12,6 +12,7 @@
#endif
#include "nsIAddonPolicyService.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIEffectiveTLDService.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
@ -100,7 +101,9 @@ NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aA
}
void
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs)
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs,
const bool aIsTopLevelDocument,
nsIURI* aURI)
{
mAppId = aAttrs.mAppId;
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
@ -113,7 +116,24 @@ NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes
// mSignedPkg accordingly by mSignedPkgInBrowser
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
bool isFirstPartyEnabled = IsFirstPartyEnabled();
// When the pref is on, we also compute the firstPartyDomain attribute
// if this is for top-level document.
if (isFirstPartyEnabled && aIsTopLevelDocument) {
nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
MOZ_ASSERT(tldService);
if (!tldService) {
return;
}
nsAutoCString baseDomain;
tldService->GetBaseDomain(aURI, 0, baseDomain);
mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain);
} else {
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
}
void
@ -326,6 +346,20 @@ OriginAttributes::SetFromGenericAttributes(const GenericOriginAttributes& aAttrs
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
bool
OriginAttributes::IsFirstPartyEnabled()
{
// Cache the privacy.firstparty.isolate pref.
static bool sFirstPartyIsolation = false;
static bool sCachedFirstPartyPref = false;
if (!sCachedFirstPartyPref) {
sCachedFirstPartyPref = true;
Preferences::AddBoolVarCache(&sFirstPartyIsolation, "privacy.firstparty.isolate");
}
return sFirstPartyIsolation;
}
BasePrincipal::BasePrincipal()
{}

View File

@ -66,6 +66,9 @@ protected:
OriginAttributes() {}
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
: OriginAttributesDictionary(aOther) {}
// check if "privacy.firstparty.isolate" is enabled.
bool IsFirstPartyEnabled();
};
class PrincipalOriginAttributes;
@ -137,7 +140,11 @@ public:
// is made.
void InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs);
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs);
// Inheriting OriginAttributes from a docshell when loading a top-level
// document.
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs,
const bool aIsTopLevelDocument = false,
nsIURI* aURI = nullptr);
};
// For operating on OriginAttributes not associated with any data structure.

View File

@ -436,37 +436,16 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadContext> loadContext;
NS_QueryNotificationCallbacks(aChannel, loadContext);
nsCOMPtr<nsILoadInfo> loadInfo;
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INVALID;
if (loadInfo) {
contentPolicyType = loadInfo->GetExternalContentPolicyType();
}
// Inherit the origin attributes from loadInfo.
// If this is a top-level document load, the origin attributes of the
// loadInfo will be set from nsDocShell::DoURILoad.
// For subresource loading, the origin attributes of the loadInfo is from
// its loadingPrincipal.
PrincipalOriginAttributes attrs;
if (nsIContentPolicy::TYPE_DOCUMENT == contentPolicyType ||
nsIContentPolicy::TYPE_SUBDOCUMENT == contentPolicyType) {
// If it's document or sub-document, inherit originAttributes from
// the document.
if (loadContext) {
DocShellOriginAttributes docShellAttrs;
loadContext->GetOriginAttributes(docShellAttrs);
attrs.InheritFromDocShellToDoc(docShellAttrs, uri);
}
} else {
// Inherit origin attributes from loading principal if any.
nsCOMPtr<nsIPrincipal> loadingPrincipal;
if (loadInfo) {
loadInfo->GetLoadingPrincipal(getter_AddRefs(loadingPrincipal));
}
if (loadingPrincipal) {
attrs = BasePrincipal::Cast(loadingPrincipal)->OriginAttributesRef();
}
}
attrs.InheritFromNecko(loadInfo->GetOriginAttributes());
rv = MaybeSetAddonIdFromURI(attrs, uri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);

View File

@ -10812,7 +10812,10 @@ nsDocShell::DoURILoad(nsIURI* aURI,
// OriginAttributes of the parent document. Or in case there isn't a
// parent document.
NeckoOriginAttributes neckoAttrs;
neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes());
bool isTopLevelDoc = aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT &&
mItemType == typeContent &&
!GetIsMozBrowserOrApp();
neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes(), isTopLevelDoc, aURI);
rv = loadInfo->SetOriginAttributes(neckoAttrs);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

View File

@ -2098,6 +2098,38 @@ nsFrameLoader::MaybeCreateDocShell()
attrs = nsDocShell::Cast(docShell)->GetOriginAttributes();
}
// Inherit origin attributes from parent document if
// 1. It's in a content docshell.
// 2. its nodePrincipal is not a SystemPrincipal.
// 3. It's not a mozbrowser nor mozapp frame.
//
// For example, firstPartyDomain is computed from top-level document, it
// doesn't exist in the top-level docshell.
if (parentType == nsIDocShellTreeItem::typeContent &&
!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()) &&
!OwnerIsMozBrowserOrAppFrame()) {
PrincipalOriginAttributes poa = BasePrincipal::Cast(doc->NodePrincipal())->OriginAttributesRef();
// Assert on the firstPartyDomain from top-level docshell should be empty
if (mIsTopLevelContent) {
MOZ_ASSERT(attrs.mFirstPartyDomain.IsEmpty(),
"top-level docshell shouldn't have firstPartyDomain attribute.");
}
// So far we want to make sure InheritFromDocToChildDocShell doesn't override
// any other origin attribute than firstPartyDomain.
MOZ_ASSERT(attrs.mAppId == poa.mAppId,
"docshell and document should have the same appId attribute.");
MOZ_ASSERT(attrs.mUserContextId == poa.mUserContextId,
"docshell and document should have the same userContextId attribute.");
MOZ_ASSERT(attrs.mInIsolatedMozBrowser == poa.mInIsolatedMozBrowser,
"docshell and document should have the same inIsolatedMozBrowser attribute.");
MOZ_ASSERT(attrs.mPrivateBrowsingId == poa.mPrivateBrowsingId,
"docshell and document should have the same privateBrowsingId attribute.");
attrs.InheritFromDocToChildDocShell(poa);
}
if (OwnerIsAppFrame()) {
// You can't be both an app and a browser frame.
MOZ_ASSERT(!OwnerIsMozBrowserFrame());

View File

@ -148,6 +148,7 @@ NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
aAttrs.mSignedPkg = aSerialized.mOriginAttributes.mSignedPkg;
aAttrs.mUserContextId = aSerialized.mOriginAttributes.mUserContextId;
aAttrs.mPrivateBrowsingId = aSerialized.mOriginAttributes.mPrivateBrowsingId;
aAttrs.mFirstPartyDomain = aSerialized.mOriginAttributes.mFirstPartyDomain;
return nullptr;
}