Bug 1166910 - Referrer attribute for img tag. r=ckerschb, r=hsivonen, r=bz

--HG--
extra : rebase_source : ceb3a3d18acf7deb9d13cfae499b7e112db8ffce
This commit is contained in:
Franziskus Kiefer 2015-06-05 15:25:24 -07:00
Родитель 8e360c243e
Коммит 2ae91f6891
14 изменённых файлов: 114 добавлений и 10 удалений

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

@ -46,6 +46,7 @@
#include "mozilla/EventStates.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/Preferences.h"
#ifdef LoadImage
// Undefine LoadImage to prevent naming conflict with Windows.
@ -930,15 +931,27 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
loadFlags |= imgILoader::LOAD_CORS_USE_CREDENTIALS;
}
// get document wide referrer policy
mozilla::net::ReferrerPolicy referrerPolicy = aDocument->GetReferrerPolicy();
bool referrerAttributeEnabled = Preferences::GetBool("network.http.enablePerElementReferrer", false);
// if referrer attributes are enabled in preferences, load img referrer attribute
nsresult rv;
if (referrerAttributeEnabled) {
mozilla::net::ReferrerPolicy imgReferrerPolicy = GetImageReferrerPolicy();
// if the image does not provide a referrer attribute, ignore this
if (imgReferrerPolicy != mozilla::net::RP_Unset) {
referrerPolicy = imgReferrerPolicy;
}
}
// Not blocked. Do the load.
nsRefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
nsresult rv;
rv = nsContentUtils::LoadImage(aNewURI, aDocument,
aDocument->NodePrincipal(),
aDocument->GetDocumentURI(),
aDocument->GetReferrerPolicy(),
referrerPolicy,
this, loadFlags,
content->LocalName(),
getter_AddRefs(req),
@ -1566,3 +1579,11 @@ nsImageLoadingContent::ImageObserver::~ImageObserver()
MOZ_COUNT_DTOR(ImageObserver);
NS_CONTENT_DELETE_LIST_MEMBER(ImageObserver, this, mNext);
}
// Only HTMLInputElement.h overrides this for <img> tags
// all other subclasses use this one, i.e. ignore referrer attributes
mozilla::net::ReferrerPolicy
nsImageLoadingContent::GetImageReferrerPolicy()
{
return mozilla::net::RP_Unset;
};

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

@ -24,6 +24,7 @@
#include "nsAutoPtr.h"
#include "nsIContentPolicy.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/net/ReferrerPolicy.h"
class nsIURI;
class nsIDocument;
@ -198,6 +199,8 @@ protected:
*/
virtual mozilla::CORSMode GetCORSMode();
virtual mozilla::net::ReferrerPolicy GetImageReferrerPolicy();
// Subclasses are *required* to call BindToTree/UnbindFromTree.
void BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent, bool aCompileEventHandlers);

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

@ -189,6 +189,20 @@ public:
{
SetHTMLAttr(nsGkAtoms::border, aBorder, aError);
}
void SetReferrer(const nsAString& aReferrer, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::referrer, aReferrer, aError);
}
void GetReferrer(nsAString& aReferrer)
{
GetEnumAttr(nsGkAtoms::referrer, nullptr, aReferrer);
}
mozilla::net::ReferrerPolicy
GetImageReferrerPolicy()
{
return GetReferrerPolicy();
}
int32_t X();
int32_t Y();

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

@ -106,6 +106,8 @@
#include "mozilla/dom/HTMLBodyElement.h"
#include "imgIContainer.h"
#include "mozilla/net/ReferrerPolicy.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -995,6 +997,10 @@ nsGenericHTMLElement::ParseAttribute(int32_t aNamespaceID,
return aResult.ParseIntValue(aValue);
}
if (aAttribute == nsGkAtoms::referrer) {
return ParseReferrerAttribute(aValue, aResult);
}
if (aAttribute == nsGkAtoms::name) {
// Store name as an atom. name="" means that the element has no name,
// not that it has an emptystring as the name.
@ -1262,6 +1268,19 @@ nsGenericHTMLElement::ParseImageAttribute(nsIAtom* aAttribute,
return false;
}
bool
nsGenericHTMLElement::ParseReferrerAttribute(const nsAString& aString,
nsAttrValue& aResult)
{
static const nsAttrValue::EnumTable kReferrerTable[] = {
{ "no-referrer", net::RP_No_Referrer },
{ "origin", net::RP_Origin },
{ "unsafe-url", net::RP_Unsafe_URL },
{ 0 }
};
return aResult.ParseEnumValue(aString, kReferrerTable, false);
}
bool
nsGenericHTMLElement::ParseFrameborderValue(const nsAString& aString,
nsAttrValue& aResult)

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

@ -233,6 +233,17 @@ public:
mScrollgrab = aValue;
}
mozilla::net::ReferrerPolicy
GetReferrerPolicy()
{
nsAutoString aPolicyString;
GetEnumAttr(nsGkAtoms::referrer, nullptr, aPolicyString);
if (aPolicyString.IsEmpty()) {
return mozilla::net::RP_Unset;
}
return mozilla::net::ReferrerPolicyFromString(aPolicyString);
}
/**
* Determine whether an attribute is an event (onclick, etc.)
* @param aName the attribute
@ -711,6 +722,10 @@ public:
static bool ParseImageAttribute(nsIAtom* aAttribute,
const nsAString& aString,
nsAttrValue& aResult);
static bool ParseReferrerAttribute(const nsAString& aString,
nsAttrValue& aResult);
/**
* Convert a frameborder string to value (yes/no/1/0)
*

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

@ -30,6 +30,8 @@ interface HTMLImageElement : HTMLElement {
[SetterThrows]
attribute DOMString useMap;
[SetterThrows]
attribute DOMString referrer;
[SetterThrows]
attribute boolean isMap;
[SetterThrows]
attribute unsigned long width;

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

@ -670,6 +670,9 @@ ValidateSecurityInfo(imgRequest* request, bool forcePrincipalCheck,
nsISupports* aCX, ReferrerPolicy referrerPolicy)
{
// If the entry's Referrer Policy doesn't match, we can't use this request.
// XXX: this will return false if an image has different referrer attributes,
// i.e. we currently don't use the cached image but reload the image with
// the new referrer policy bug 1174921
if (referrerPolicy != request->GetReferrerPolicy()) {
return false;
}

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

@ -1274,6 +1274,9 @@ pref("network.http.referer.XOriginPolicy", 0);
// By default this is enabled for compatibility (see bug 141641)
pref("network.http.sendSecureXSiteReferrer", true);
// Controls whether referrer attributes in <a>, <img>, <area>, and <iframe> are honoured
pref("network.http.enablePerElementReferrer", false);
// Maximum number of consecutive redirects before aborting.
pref("network.http.redirection-limit", 20);

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

@ -25,7 +25,10 @@ enum ReferrerPolicy {
RP_Origin_When_Crossorigin = nsIHttpChannel::REFERRER_POLICY_ORIGIN_WHEN_XORIGIN,
/* spec tokens: always unsafe-url */
RP_Unsafe_URL = nsIHttpChannel::REFERRER_POLICY_UNSAFE_URL
RP_Unsafe_URL = nsIHttpChannel::REFERRER_POLICY_UNSAFE_URL,
/* referrer policy is not set */
RP_Unset = nsIHttpChannel::REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE
};
inline ReferrerPolicy

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

@ -28,10 +28,10 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
aExecutor->SetSpeculationBase(mUrl);
break;
case eSpeculativeLoadMetaReferrer:
aExecutor->SetSpeculationReferrerPolicy(mMetaReferrerPolicy);
aExecutor->SetSpeculationReferrerPolicy(mReferrerPolicy);
break;
case eSpeculativeLoadImage:
aExecutor->PreloadImage(mUrl, mCrossOrigin, mSrcset, mSizes);
aExecutor->PreloadImage(mUrl, mCrossOrigin, mSrcset, mSizes, mReferrerPolicy);
break;
case eSpeculativeLoadOpenPicture:
aExecutor->PreloadOpenPicture();

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

@ -45,12 +45,13 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadMetaReferrer;
mMetaReferrerPolicy.Assign(
mReferrerPolicy.Assign(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aReferrerPolicy));
}
inline void InitImage(const nsAString& aUrl,
const nsAString& aCrossOrigin,
const nsAString& aReferrerPolicy,
const nsAString& aSrcset,
const nsAString& aSizes)
{
@ -59,6 +60,8 @@ class nsHtml5SpeculativeLoad {
mOpCode = eSpeculativeLoadImage;
mUrl.Assign(aUrl);
mCrossOrigin.Assign(aCrossOrigin);
mReferrerPolicy.Assign(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aReferrerPolicy));
mSrcset.Assign(aSrcset);
mSizes.Assign(aSizes);
}
@ -179,7 +182,7 @@ class nsHtml5SpeculativeLoad {
private:
eHtml5SpeculativeLoad mOpCode;
nsString mUrl;
nsString mMetaReferrerPolicy;
nsString mReferrerPolicy;
/**
* If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
* then this is the value of the "charset" attribute. For

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

@ -125,11 +125,14 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
nsString* crossOrigin =
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
nsString* referrerPolicy =
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRER);
nsString* sizes =
aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
mSpeculativeLoadQueue.AppendElement()->
InitImage(url ? *url : NullString(),
crossOrigin ? *crossOrigin : NullString(),
referrerPolicy ? *referrerPolicy : NullString(),
srcset ? *srcset : NullString(),
sizes ? *sizes : NullString());
} else if (nsHtml5Atoms::source == aName) {
@ -202,6 +205,7 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
if (url) {
mSpeculativeLoadQueue.AppendElement()->InitImage(*url, NullString(),
NullString(),
NullString(),
NullString());
}
@ -238,6 +242,7 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
if (url) {
mSpeculativeLoadQueue.AppendElement()->InitImage(*url, NullString(),
NullString(),
NullString(),
NullString());
}

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

@ -943,13 +943,25 @@ void
nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
const nsAString& aCrossOrigin,
const nsAString& aSrcset,
const nsAString& aSizes)
const nsAString& aSizes,
const nsAString& aImageReferrerPolicy)
{
nsCOMPtr<nsIURI> baseURI = BaseURIForPreload();
nsCOMPtr<nsIURI> uri = mDocument->ResolvePreloadImage(baseURI, aURL, aSrcset,
aSizes);
if (uri && ShouldPreloadURI(uri)) {
mDocument->MaybePreLoadImage(uri, aCrossOrigin, mSpeculationReferrerPolicy);
// use document wide referrer policy
mozilla::net::ReferrerPolicy referrerPolicy = mSpeculationReferrerPolicy;
// if enabled in preferences, use the referrer attribute from the image, if provided
bool referrerAttributeEnabled = Preferences::GetBool("network.http.enablePerElementReferrer", false);
if (referrerAttributeEnabled) {
mozilla::net::ReferrerPolicy imageReferrerPolicy = mozilla::net::ReferrerPolicyFromString(aImageReferrerPolicy);
if (imageReferrerPolicy != mozilla::net::RP_Unset) {
referrerPolicy = imageReferrerPolicy;
}
}
mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy);
}
}

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

@ -256,7 +256,8 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
void PreloadImage(const nsAString& aURL,
const nsAString& aCrossOrigin,
const nsAString& aSrcset,
const nsAString& aSizes);
const nsAString& aSizes,
const nsAString& aImageReferrerPolicy);
void PreloadOpenPicture();