Bug 1517703 - Part 1 - Implement ReferrerInfo class r=smaug

The class contains original full referrer and referrer policy will be
applied to the referrer.

Differential Revision: https://phabricator.services.mozilla.com/D17923
This commit is contained in:
Thomas Nguyen
2019-02-12 19:35:32 +00:00
parent 33e6f0e694
commit d13c22ef47
22 changed files with 361 additions and 227 deletions

View File

@@ -63,6 +63,7 @@
#include "mozilla/net/ReferrerPolicy.h"
#include "mozilla/net/UrlClassifierFeatureFactory.h"
#include "ReferrerInfo.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIApplicationCacheContainer.h"
@@ -331,7 +332,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext)
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
mLoadType(0),
mDefaultLoadFlags(nsIRequest::LOAD_NORMAL),
mReferrerPolicy((uint32_t)mozilla::net::ReferrerPolicy::RP_Unset),
mFailedLoadType(0),
mFrameType(FRAME_TYPE_REGULAR),
mPrivateBrowsingId(0),
@@ -3897,6 +3897,7 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
loadFlags &= ~EXTRA_LOAD_FLAGS;
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(uri);
loadState->SetReferrerInfo(aLoadURIOptions.mReferrerInfo);
/*
* If the user "Disables Protection on This Page", we have to make sure to
@@ -3912,9 +3913,6 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
loadState->SetLoadFlags(extraFlags);
loadState->SetFirstParty(true);
loadState->SetPostDataStream(postData);
loadState->SetReferrer(aLoadURIOptions.mReferrerURI);
loadState->SetReferrerPolicy(
(mozilla::net::ReferrerPolicy)aLoadURIOptions.mReferrerPolicy);
loadState->SetHeadersStream(aLoadURIOptions.mHeaders);
loadState->SetBaseURI(aLoadURIOptions.mBaseURI);
loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal);
@@ -4592,19 +4590,16 @@ nsDocShell::Reload(uint32_t aReloadFlags) {
// Stack variables to ensure changes to the member variables don't affect to
// the call.
nsCOMPtr<nsIURI> currentURI = mCurrentURI;
nsCOMPtr<nsIURI> referrerURI = mReferrerURI;
uint32_t referrerPolicy = mReferrerPolicy;
// Reload always rewrites result principal URI.
Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI);
loadState->SetReferrerInfo(mReferrerInfo);
loadState->SetOriginalURI(originalURI);
loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
loadState->SetLoadReplace(loadReplace);
loadState->SetReferrer(referrerURI);
loadState->SetReferrerPolicy((mozilla::net::ReferrerPolicy)referrerPolicy);
loadState->SetTriggeringPrincipal(triggeringPrincipal);
loadState->SetPrincipalToInherit(triggeringPrincipal);
loadState->SetLoadFlags(flags);
@@ -4693,16 +4688,6 @@ nsDocShell::GetCurrentURI(nsIURI** aURI) {
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetReferringURI(nsIURI** aURI) {
NS_ENSURE_ARG_POINTER(aURI);
*aURI = mReferrerURI;
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::InitSessionHistory() {
MOZ_ASSERT(!mIsBeingDestroyed);
@@ -5784,17 +5769,13 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
NS_ENSURE_ARG(aURI);
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
/* We do need to pass in a referrer, but we don't want it to
* be sent to the server.
*/
loadState->SetSendReferrer(false);
/* for most refreshes the current URI is an appropriate
* For most refreshes the current URI is an appropriate
* internal referrer
*/
loadState->SetReferrer(mCurrentURI);
nsCOMPtr<nsIReferrerInfo> referrerInfo =
new ReferrerInfo(mCurrentURI, mozilla::net::RP_Unset, false);
loadState->SetOriginalURI(mCurrentURI);
loadState->SetResultPrincipalURI(aURI);
loadState->SetResultPrincipalURIIsSome(true);
@@ -5829,15 +5810,12 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
/* for redirects we mimic HTTP, which passes the
* original referrer
*/
nsCOMPtr<nsIURI> internalReferrer;
GetReferringURI(getter_AddRefs(internalReferrer));
if (internalReferrer) {
loadState->SetReferrer(internalReferrer);
}
referrerInfo = mReferrerInfo;
} else {
loadState->SetLoadType(LOAD_REFRESH);
}
loadState->SetReferrerInfo(referrerInfo);
loadState->SetLoadFlags(
nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
loadState->SetFirstParty(true);
@@ -6106,7 +6084,7 @@ nsDocShell::SetupRefreshURI(nsIChannel* aChannel) {
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
SetupReferrerFromChannel(aChannel);
SetupReferrerInfoFromChannel(aChannel);
rv = SetupRefreshURIFromHeader(mCurrentURI, principal, refreshHeader);
if (NS_SUCCEEDED(rv)) {
return NS_REFRESHURI_HEADER_FOUND;
@@ -6489,10 +6467,6 @@ void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
// channel.
SaveLastVisit(aNewChannel, previousURI, previousFlags);
} else {
nsCOMPtr<nsIURI> referrer;
// Treat referrer as null if there is an error getting it.
(void)NS_GetReferrerFromChannel(aOldChannel, getter_AddRefs(referrer));
// Get the HTTP response code, if available.
uint32_t responseStatus = 0;
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
@@ -6501,7 +6475,7 @@ void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
}
// Add visit N -1 => N
AddURIVisit(oldURI, referrer, previousURI, previousFlags, responseStatus);
AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
// Since N + 1 could be the final destination, we will not save N => N + 1
// here. OnNewURI will do that, so we will cache it.
@@ -8755,11 +8729,7 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState,
// Set up our loadinfo so it will do the load as much like we would have
// as possible.
loadState->SetReferrer(aLoadState->Referrer());
loadState->SetReferrerPolicy(
(mozilla::net::ReferrerPolicy)aLoadState->ReferrerPolicy());
loadState->SetSendReferrer(
!(aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)));
loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
loadState->SetOriginalURI(aLoadState->OriginalURI());
Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
@@ -9354,10 +9324,14 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
if (browserChrome3) {
bool shouldLoad;
nsCOMPtr<nsIURI> referrer;
nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
if (referrerInfo) {
referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
}
rv = browserChrome3->ShouldLoadURI(
this, aLoadState->URI(), aLoadState->Referrer(),
!!aLoadState->PostDataStream(), aLoadState->TriggeringPrincipal(),
&shouldLoad);
this, aLoadState->URI(), referrer, !!aLoadState->PostDataStream(),
aLoadState->TriggeringPrincipal(), &shouldLoad);
if (NS_SUCCEEDED(rv) && !shouldLoad) {
return NS_OK;
}
@@ -10057,6 +10031,13 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
do_QueryInterface(channel));
nsCOMPtr<nsIURI> referrer;
uint32_t referrerPolicy = RP_Unset;
nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
if (referrerInfo) {
referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
referrerInfo->GetReferrerPolicy(&referrerPolicy);
}
if (httpChannelInternal) {
if (aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
rv = httpChannelInternal->SetThirdPartyFlags(
@@ -10067,7 +10048,7 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
rv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
MOZ_ASSERT(NS_SUCCEEDED(rv));
} else {
rv = httpChannelInternal->SetDocumentURI(aLoadState->Referrer());
rv = httpChannelInternal->SetDocumentURI(referrer);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
rv = httpChannelInternal->SetRedirectMode(
@@ -10080,7 +10061,7 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
// save true referrer for those who need it (e.g. xpinstall whitelisting)
// Currently only http and ftp channels support this.
props->SetPropertyAsInterface(
NS_LITERAL_STRING("docshell.internalReferrer"), aLoadState->Referrer());
NS_LITERAL_STRING("docshell.internalReferrer"), referrer);
}
nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
@@ -10153,11 +10134,10 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
rv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
}
// Set the referrer explicitly
if (aLoadState->Referrer() &&
if (referrer &&
!(aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))) {
// Referrer is currenly only set for link clicks here.
rv = httpChannel->SetReferrerWithPolicy(aLoadState->Referrer(),
aLoadState->ReferrerPolicy());
rv = httpChannel->SetReferrerWithPolicy(referrer, referrerPolicy);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
}
@@ -10545,18 +10525,17 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
return NS_OK;
}
void nsDocShell::SetupReferrerFromChannel(nsIChannel* aChannel) {
void nsDocShell::SetupReferrerInfoFromChannel(nsIChannel* aChannel) {
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
if (httpChannel) {
nsCOMPtr<nsIURI> referrer;
nsresult rv = httpChannel->GetReferrer(getter_AddRefs(referrer));
if (NS_SUCCEEDED(rv)) {
SetReferrerURI(referrer);
}
uint32_t referrerPolicy;
rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
if (NS_SUCCEEDED(rv)) {
SetReferrerPolicy(referrerPolicy);
uint32_t referrerPolicy;
rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
if (NS_SUCCEEDED(rv)) {
SetReferrerInfo(new ReferrerInfo(referrer, referrerPolicy));
}
}
}
}
@@ -10786,13 +10765,7 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
}
// Note: We don't use |referrer| when our global history is
// based on IHistory.
nsCOMPtr<nsIURI> referrer;
// Treat referrer as null if there is an error getting it.
(void)NS_GetReferrerFromChannel(aChannel, getter_AddRefs(referrer));
AddURIVisit(aURI, referrer, previousURI, previousFlags, responseStatus);
AddURIVisit(aURI, previousURI, previousFlags, responseStatus);
}
// If this was a history load or a refresh, or it was a history load but
@@ -10816,7 +10789,7 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
bool onLocationChangeNeeded =
SetCurrentURI(aURI, aChannel, aFireOnLocationChange, locationFlags);
// Make sure to store the referrer from the channel, if any
SetupReferrerFromChannel(aChannel);
SetupReferrerInfoFromChannel(aChannel);
return onLocationChangeNeeded;
}
@@ -10835,12 +10808,8 @@ bool nsDocShell::OnLoadingSite(nsIChannel* aChannel, bool aFireOnLocationChange,
aFireOnLocationChange, aAddToGlobalHistory, false);
}
void nsDocShell::SetReferrerURI(nsIURI* aURI) {
mReferrerURI = aURI; // This assigment addrefs
}
void nsDocShell::SetReferrerPolicy(uint32_t aReferrerPolicy) {
mReferrerPolicy = aReferrerPolicy;
void nsDocShell::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
mReferrerInfo = aReferrerInfo; // This assigment addrefs
}
//*****************************************************************************
@@ -11141,7 +11110,7 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
FireDummyOnLocationChange();
}
AddURIVisit(newURI, oldURI, oldURI, 0);
AddURIVisit(newURI, oldURI, 0);
// AddURIVisit doesn't set the title for the new URI in global history,
// so do that here.
@@ -11358,8 +11327,7 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
entry->SetOriginalURI(originalURI);
entry->SetResultPrincipalURI(resultPrincipalURI);
entry->SetLoadReplace(loadReplace);
entry->SetReferrerURI(referrerURI);
entry->SetReferrerPolicy(referrerPolicy);
entry->SetReferrerInfo(new ReferrerInfo(referrerURI, referrerPolicy));
nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
if (inStrmChan) {
bool isSrcdocChannel;
@@ -11467,13 +11435,12 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) {
nsCOMPtr<nsIURI> originalURI = aEntry->GetOriginalURI();
nsCOMPtr<nsIURI> resultPrincipalURI = aEntry->GetResultPrincipalURI();
bool loadReplace = aEntry->GetLoadReplace();
nsCOMPtr<nsIURI> referrerURI = aEntry->GetReferrerURI();
uint32_t referrerPolicy = aEntry->GetReferrerPolicy();
nsCOMPtr<nsIInputStream> postData = aEntry->GetPostData();
nsAutoCString contentType;
aEntry->GetContentType(contentType);
nsCOMPtr<nsIPrincipal> triggeringPrincipal = aEntry->GetTriggeringPrincipal();
nsCOMPtr<nsIPrincipal> principalToInherit = aEntry->GetPrincipalToInherit();
nsCOMPtr<nsIReferrerInfo> referrerInfo = aEntry->GetReferrerInfo();
// Calling CreateAboutBlankContentViewer can set mOSHE to null, and if
// that's the only thing holding a ref to aEntry that will cause aEntry to
@@ -11552,11 +11519,10 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) {
emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(uri);
loadState->SetReferrerInfo(referrerInfo);
loadState->SetOriginalURI(originalURI);
loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
loadState->SetLoadReplace(loadReplace);
loadState->SetReferrer(referrerURI);
loadState->SetReferrerPolicy((mozilla::net::ReferrerPolicy)referrerPolicy);
loadState->SetTriggeringPrincipal(triggeringPrincipal);
loadState->SetPrincipalToInherit(principalToInherit);
loadState->SetLoadFlags(flags);
@@ -11819,8 +11785,7 @@ void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
aChannelRedirectFlags);
}
void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aReferrerURI,
nsIURI* aPreviousURI,
void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
uint32_t aChannelRedirectFlags,
uint32_t aResponseStatus) {
MOZ_ASSERT(aURI, "Visited URI is null!");
@@ -12610,7 +12575,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
// Get the owner document of the link that was clicked, this will be
// the document that the link is in, or the last document that the
// link was in. From that document, we'll get the URI to use as the
// referer, since the current URI in this docshell may be a
// referrer, since the current URI in this docshell may be a
// new document that we're in the process of loading.
RefPtr<Document> refererDoc = aContent->OwnerDoc();
NS_ENSURE_TRUE(refererDoc, NS_ERROR_UNEXPECTED);
@@ -12626,7 +12591,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
return NS_OK;
}
nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
nsCOMPtr<nsIURI> referrer = refererDoc->GetDocumentURI();
uint32_t refererPolicy = refererDoc->GetReferrerPolicy();
// get referrer attribute from clicked link and parse it
@@ -12640,8 +12605,8 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
}
}
// referer could be null here in some odd cases, but that's ok,
// we'll just load the link w/o sending a referer in those cases.
// referrer could be null here in some odd cases, but that's ok,
// we'll just load the link w/o sending a referrer in those cases.
// If this is an anchor element, grab its type property to use as a hint
nsAutoString typeHint;
@@ -12664,9 +12629,11 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
flags |= INTERNAL_LOAD_FLAGS_IS_USER_TRIGGERED;
}
bool sendReferrer = !(flags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
nsCOMPtr<nsIReferrerInfo> referrerInfo =
new ReferrerInfo(referrer, refererPolicy, sendReferrer);
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
loadState->SetReferrer(referer);
loadState->SetReferrerPolicy((mozilla::net::ReferrerPolicy)refererPolicy);
loadState->SetReferrerInfo(referrerInfo);
loadState->SetTriggeringPrincipal(triggeringPrincipal);
loadState->SetPrincipalToInherit(aContent->NodePrincipal());
loadState->SetLoadFlags(flags);
@@ -12681,7 +12648,8 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
nsresult rv = InternalLoad(loadState, aDocShell, aRequest);
if (NS_SUCCEEDED(rv)) {
nsPingListener::DispatchPings(this, aContent, aURI, referer, refererPolicy);
nsPingListener::DispatchPings(this, aContent, aURI, referrer,
refererPolicy);
}
return rv;
}