зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1174913 - anchor and area referrer attributes. r=ckerschb, r=bz
This commit is contained in:
Родитель
95250b2dbf
Коммит
e97220a88e
|
@ -5610,11 +5610,24 @@ function handleLinkClick(event, href, linkNode) {
|
|||
catch (e) { }
|
||||
}
|
||||
|
||||
// first get document wide referrer policy, then
|
||||
// get referrer attribute from clicked link and parse it and
|
||||
// allow per element referrer to overrule the document wide referrer if enabled
|
||||
let referrerPolicy = doc.referrerPolicy;
|
||||
if (Services.prefs.getBoolPref("network.http.enablePerElementReferrer") &&
|
||||
linkNode) {
|
||||
let referrerAttrValue = Services.netUtils.parseAttributePolicyString(linkNode.
|
||||
getAttribute("referrer"));
|
||||
if (referrerAttrValue != Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT) {
|
||||
referrerPolicy = referrerAttrValue;
|
||||
}
|
||||
}
|
||||
|
||||
urlSecurityCheck(href, doc.nodePrincipal);
|
||||
let params = { charset: doc.characterSet,
|
||||
allowMixedContent: persistAllowMixedContentInChildTab,
|
||||
referrerURI: referrerURI,
|
||||
referrerPolicy: doc.referrerPolicy,
|
||||
referrerPolicy: referrerPolicy,
|
||||
noReferrer: BrowserUtils.linkHasNoReferrer(linkNode) };
|
||||
openLinkIn(href, where, params);
|
||||
event.preventDefault();
|
||||
|
|
|
@ -105,6 +105,17 @@ let handleContentContextMenu = function (event) {
|
|||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
|
||||
// get referrer attribute from clicked link and parse it
|
||||
// if per element referrer is enabled, the element referrer overrules
|
||||
// the document wide referrer
|
||||
if (Services.prefs.getBoolPref("network.http.enablePerElementReferrer")) {
|
||||
let referrerAttrValue = Services.netUtils.parseAttributePolicyString(event.target.
|
||||
getAttribute("referrer"));
|
||||
if (referrerAttrValue !== Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT) {
|
||||
referrerPolicy = referrerAttrValue;
|
||||
}
|
||||
}
|
||||
|
||||
let disableSetDesktopBg = null;
|
||||
// Media related cache info parent needs for saving
|
||||
let contentType = null;
|
||||
|
@ -351,10 +362,23 @@ let ClickEventHandler = {
|
|||
|
||||
let [href, node] = this._hrefAndLinkNodeForClickEvent(event);
|
||||
|
||||
// get referrer attribute from clicked link and parse it
|
||||
// if per element referrer is enabled, the element referrer overrules
|
||||
// the document wide referrer
|
||||
let referrerPolicy = ownerDoc.referrerPolicy;
|
||||
if (Services.prefs.getBoolPref("network.http.enablePerElementReferrer") &&
|
||||
node) {
|
||||
let referrerAttrValue = Services.netUtils.parseAttributePolicyString(node.
|
||||
getAttribute("referrer"));
|
||||
if (referrerAttrValue !== Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT) {
|
||||
referrerPolicy = referrerAttrValue;
|
||||
}
|
||||
}
|
||||
|
||||
let json = { button: event.button, shiftKey: event.shiftKey,
|
||||
ctrlKey: event.ctrlKey, metaKey: event.metaKey,
|
||||
altKey: event.altKey, href: null, title: null,
|
||||
bookmark: false, referrerPolicy: ownerDoc.referrerPolicy };
|
||||
bookmark: false, referrerPolicy: referrerPolicy };
|
||||
|
||||
if (href) {
|
||||
try {
|
||||
|
|
|
@ -13515,6 +13515,22 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
|||
nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
|
||||
uint32_t refererPolicy = refererDoc->GetReferrerPolicy();
|
||||
|
||||
// get referrer attribute from clicked link and parse it
|
||||
// if per element referrer is enabled, the element referrer overrules
|
||||
// the document wide referrer
|
||||
if (IsElementAnchor(aContent)) {
|
||||
MOZ_ASSERT(aContent->IsHTMLElement());
|
||||
if (Preferences::GetBool("network.http.enablePerElementReferrer", false)) {
|
||||
nsAutoString referrerPolicy;
|
||||
if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::referrer, referrerPolicy)) {
|
||||
uint32_t refPolEnum = mozilla::net::ReferrerPolicyFromString(referrerPolicy);
|
||||
if (refPolEnum != mozilla::net::RP_Unset) {
|
||||
refererPolicy = refPolEnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
|
|
|
@ -123,6 +123,14 @@ public:
|
|||
{
|
||||
SetHTMLAttr(nsGkAtoms::rel, aValue, rv);
|
||||
}
|
||||
void SetReferrer(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::referrer, aValue, rv);
|
||||
}
|
||||
void GetReferrer(nsAString& aReferrer)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::referrer, aReferrer);
|
||||
}
|
||||
nsDOMTokenList* RelList();
|
||||
void GetHreflang(DOMString& aValue)
|
||||
{
|
||||
|
|
|
@ -128,6 +128,15 @@ public:
|
|||
}
|
||||
nsDOMTokenList* RelList();
|
||||
|
||||
void SetReferrer(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::referrer, aValue, rv);
|
||||
}
|
||||
void GetReferrer(nsAString& aReferrer)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::referrer, aReferrer);
|
||||
}
|
||||
|
||||
// The Link::GetOrigin is OK for us
|
||||
|
||||
using Link::GetProtocol;
|
||||
|
|
|
@ -21,6 +21,8 @@ interface HTMLAnchorElement : HTMLElement {
|
|||
attribute DOMString ping;
|
||||
[SetterThrows]
|
||||
attribute DOMString rel;
|
||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrer;
|
||||
readonly attribute DOMTokenList relList;
|
||||
[SetterThrows]
|
||||
attribute DOMString hreflang;
|
||||
|
|
|
@ -28,6 +28,8 @@ interface HTMLAreaElement : HTMLElement {
|
|||
attribute DOMString ping;
|
||||
[SetterThrows]
|
||||
attribute DOMString rel;
|
||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrer;
|
||||
readonly attribute DOMTokenList relList;
|
||||
|
||||
// not implemented.
|
||||
|
|
|
@ -31,28 +31,47 @@ enum ReferrerPolicy {
|
|||
RP_Unset = nsIHttpChannel::REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE
|
||||
};
|
||||
|
||||
/* spec tokens: never no-referrer */
|
||||
const char kRPS_Never[] = "never";
|
||||
const char kRPS_No_Referrer[] = "no-referrer";
|
||||
|
||||
/* spec tokens: origin */
|
||||
const char kRPS_Origin[] = "origin";
|
||||
|
||||
/* spec tokens: default no-referrer-when-downgrade */
|
||||
const char kRPS_Default[] = "default";
|
||||
const char kRPS_No_Referrer_When_Downgrade[] = "no-referrer-when-downgrade";
|
||||
|
||||
/* spec tokens: origin-when-cross-origin */
|
||||
const char kRPS_Origin_When_Cross_Origin[] = "origin-when-cross-origin";
|
||||
const char kRPS_Origin_When_Crossorigin[] = "origin-when-crossorigin";
|
||||
|
||||
/* spec tokens: always unsafe-url */
|
||||
const char kRPS_Always[] = "always";
|
||||
const char kRPS_Unsafe_URL[] = "unsafe-url";
|
||||
|
||||
inline ReferrerPolicy
|
||||
ReferrerPolicyFromString(const nsAString& content)
|
||||
{
|
||||
// This is implemented step by step as described in the Referrer Policy
|
||||
// specification, section 6.4 "Determine token's Policy".
|
||||
if (content.LowerCaseEqualsLiteral("never") ||
|
||||
content.LowerCaseEqualsLiteral("no-referrer")) {
|
||||
if (content.LowerCaseEqualsLiteral(kRPS_Never) ||
|
||||
content.LowerCaseEqualsLiteral(kRPS_No_Referrer)) {
|
||||
return RP_No_Referrer;
|
||||
}
|
||||
if (content.LowerCaseEqualsLiteral("origin")) {
|
||||
if (content.LowerCaseEqualsLiteral(kRPS_Origin)) {
|
||||
return RP_Origin;
|
||||
}
|
||||
if (content.LowerCaseEqualsLiteral("default") ||
|
||||
content.LowerCaseEqualsLiteral("no-referrer-when-downgrade")) {
|
||||
if (content.LowerCaseEqualsLiteral(kRPS_Default) ||
|
||||
content.LowerCaseEqualsLiteral(kRPS_No_Referrer_When_Downgrade)) {
|
||||
return RP_No_Referrer_When_Downgrade;
|
||||
}
|
||||
if (content.LowerCaseEqualsLiteral("origin-when-cross-origin") ||
|
||||
content.LowerCaseEqualsLiteral("origin-when-crossorigin")) {
|
||||
if (content.LowerCaseEqualsLiteral(kRPS_Origin_When_Cross_Origin) ||
|
||||
content.LowerCaseEqualsLiteral(kRPS_Origin_When_Crossorigin)) {
|
||||
return RP_Origin_When_Crossorigin;
|
||||
}
|
||||
if (content.LowerCaseEqualsLiteral("always") ||
|
||||
content.LowerCaseEqualsLiteral("unsafe-url")) {
|
||||
if (content.LowerCaseEqualsLiteral(kRPS_Always) ||
|
||||
content.LowerCaseEqualsLiteral(kRPS_Unsafe_URL)) {
|
||||
return RP_Unsafe_URL;
|
||||
}
|
||||
// Spec says if none of the previous match, use No_Referrer.
|
||||
|
@ -63,15 +82,42 @@ ReferrerPolicyFromString(const nsAString& content)
|
|||
inline bool
|
||||
IsValidReferrerPolicy(const nsAString& content)
|
||||
{
|
||||
return content.LowerCaseEqualsLiteral("never")
|
||||
|| content.LowerCaseEqualsLiteral("no-referrer")
|
||||
|| content.LowerCaseEqualsLiteral("origin")
|
||||
|| content.LowerCaseEqualsLiteral("default")
|
||||
|| content.LowerCaseEqualsLiteral("no-referrer-when-downgrade")
|
||||
|| content.LowerCaseEqualsLiteral("origin-when-cross-origin")
|
||||
|| content.LowerCaseEqualsLiteral("origin-when-crossorigin")
|
||||
|| content.LowerCaseEqualsLiteral("always")
|
||||
|| content.LowerCaseEqualsLiteral("unsafe-url");
|
||||
return content.LowerCaseEqualsLiteral(kRPS_Never)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_No_Referrer)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_Origin)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_Default)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_No_Referrer_When_Downgrade)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_Origin_When_Cross_Origin)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_Origin_When_Crossorigin)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_Always)
|
||||
|| content.LowerCaseEqualsLiteral(kRPS_Unsafe_URL);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsValidAttributeReferrerPolicy(const nsAString& aContent)
|
||||
{
|
||||
// Spec allows only these three policies at the moment
|
||||
// See bug 1178337
|
||||
return aContent.LowerCaseEqualsLiteral(kRPS_No_Referrer)
|
||||
|| aContent.LowerCaseEqualsLiteral(kRPS_Origin)
|
||||
|| aContent.LowerCaseEqualsLiteral(kRPS_Unsafe_URL);
|
||||
}
|
||||
|
||||
inline ReferrerPolicy
|
||||
AttributeReferrerPolicyFromString(const nsAString& aContent)
|
||||
{
|
||||
// if the referrer attribute string is empty, return RP_Unset
|
||||
if (aContent.IsEmpty()) {
|
||||
return RP_Unset;
|
||||
}
|
||||
// if the referrer attribute string is not empty and contains a valid
|
||||
// referrer policy, return the according enum value
|
||||
if (IsValidAttributeReferrerPolicy(aContent)) {
|
||||
return ReferrerPolicyFromString(aContent);
|
||||
}
|
||||
// in any other case the referrer attribute contains an invalid
|
||||
// policy value, we thus return RP_No_Referrer
|
||||
return RP_No_Referrer;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
|
|
|
@ -11,7 +11,7 @@ interface nsIPrefBranch;
|
|||
/**
|
||||
* nsINetUtil provides various network-related utility methods.
|
||||
*/
|
||||
[scriptable, uuid(ca68c485-9db3-4c12-82a6-4fab7948e2d5)]
|
||||
[scriptable, uuid(885d6940-1001-46e7-92ec-d494a78d7784)]
|
||||
interface nsINetUtil : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -192,4 +192,16 @@ interface nsINetUtil : nsISupports
|
|||
out AUTF8String aCharset,
|
||||
out long aCharsetStart,
|
||||
out long aCharsetEnd);
|
||||
|
||||
/**
|
||||
* Parse an attribute referrer policy string (no-referrer, origin, unsafe-url)
|
||||
* and return the according integer code (defined in nsIHttpChannel.idl)
|
||||
*
|
||||
* @param aPolicyString
|
||||
* the policy string given as attribute
|
||||
* @return aPolicyEnum
|
||||
* referrer policy code from nsIHttpChannel.idl, (see parser in
|
||||
* ReferrerPolicy.h for details)
|
||||
*/
|
||||
unsigned long parseAttributePolicyString(in AString aPolicyString);
|
||||
};
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include "CaptivePortalService.h"
|
||||
#include "ReferrerPolicy.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsINetworkManager.h"
|
||||
|
@ -1690,6 +1691,16 @@ nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// parse policyString to policy enum value (see ReferrerPolicy.h)
|
||||
NS_IMETHODIMP
|
||||
nsIOService::ParseAttributePolicyString(const nsAString& policyString,
|
||||
uint32_t *outPolicyEnum)
|
||||
{
|
||||
NS_ENSURE_ARG(outPolicyEnum);
|
||||
*outPolicyEnum = (uint32_t)mozilla::net::AttributeReferrerPolicyFromString(policyString);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISpeculativeConnect
|
||||
class IOServiceProxyCallback final : public nsIProtocolProxyCallback
|
||||
{
|
||||
|
|
|
@ -100,6 +100,7 @@ let initTable = [
|
|||
["focus", "@mozilla.org/focus-manager;1", "nsIFocusManager"],
|
||||
["uriFixup", "@mozilla.org/docshell/urifixup;1", "nsIURIFixup"],
|
||||
["blocklist", "@mozilla.org/extensions/blocklist;1", "nsIBlocklistService"],
|
||||
["netUtils", "@mozilla.org/network/util;1", "nsINetUtil"],
|
||||
];
|
||||
|
||||
initTable.forEach(([name, contract, intf, enabled = true]) => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче