Issue #2641 - Speculative load changes for referrerpolicy

This commit is contained in:
Moonchild 2024-10-20 09:35:39 +02:00 • committed by roytam1
commit f6f046930d
20 changed files with 262 additions and 128 deletions

View file

@ -472,6 +472,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
nsAutoString media; nsAutoString media;
nsAutoString anchor; nsAutoString anchor;
nsAutoString crossOrigin; nsAutoString crossOrigin;
nsAutoString referrerPolicy;
nsAutoString destination; nsAutoString destination;
crossOrigin.SetIsVoid(true); crossOrigin.SetIsVoid(true);
@ -660,6 +661,15 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
destination = value; destination = value;
destination.StripWhitespace(); destination.StripWhitespace();
} }
} else if (attr.LowerCaseEqualsLiteral("referrerpolicy")) {
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#referrer-policy-attribute
// The spec says that the referrer policy attribute is an enumerated attribute,
// case insensitive and includes the empty string.
// We will parse the value with AttributeReferrerPolicyFromString
// later, which will handle parsing it as an enumerated attribute.
if (referrerPolicy.IsEmpty()) {
referrerPolicy = value;
}
} }
} }
} }
@ -673,7 +683,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
rv = ProcessLink(anchor, href, rel, rv = ProcessLink(anchor, href, rel,
// prefer RFC 5987 variant over non-I18zed version // prefer RFC 5987 variant over non-I18zed version
titleStar.IsEmpty() ? title : titleStar, titleStar.IsEmpty() ? title : titleStar,
type, media, crossOrigin, destination); type, media, crossOrigin, referrerPolicy, destination);
} }
href.Truncate(); href.Truncate();
@ -682,6 +692,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
type.Truncate(); type.Truncate();
media.Truncate(); media.Truncate();
anchor.Truncate(); anchor.Truncate();
referrerPolicy.Truncate();
crossOrigin.SetIsVoid(true); crossOrigin.SetIsVoid(true);
destination.Truncate(); destination.Truncate();
@ -696,7 +707,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
rv = ProcessLink(anchor, href, rel, rv = ProcessLink(anchor, href, rel,
// prefer RFC 5987 variant over non-I18zed version // prefer RFC 5987 variant over non-I18zed version
titleStar.IsEmpty() ? title : titleStar, titleStar.IsEmpty() ? title : titleStar,
type, media, crossOrigin, destination); type, media, crossOrigin, referrerPolicy, destination);
} }
return rv; return rv;
@ -708,6 +719,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
const nsSubstring& aRel, const nsSubstring& aTitle, const nsSubstring& aRel, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aMedia, const nsSubstring& aType, const nsSubstring& aMedia,
const nsSubstring& aCrossOrigin, const nsSubstring& aCrossOrigin,
const nsAString& aReferrerPolicy,
const nsSubstring& aDestination) const nsSubstring& aDestination)
{ {
uint32_t linkTypes = uint32_t linkTypes =
@ -749,7 +761,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
bool isAlternate = linkTypes & nsStyleLinkElement::eALTERNATE; bool isAlternate = linkTypes & nsStyleLinkElement::eALTERNATE;
return ProcessStyleLink(nullptr, aHref, isAlternate, aTitle, aType, return ProcessStyleLink(nullptr, aHref, isAlternate, aTitle, aType,
aMedia); aMedia, aReferrerPolicy);
} }
nsresult nsresult
@ -758,7 +770,8 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
bool aAlternate, bool aAlternate,
const nsSubstring& aTitle, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aType,
const nsSubstring& aMedia) const nsSubstring& aMedia,
const nsSubstring& aReferrerPolicy)
{ {
if (aAlternate && aTitle.IsEmpty()) { if (aAlternate && aTitle.IsEmpty()) {
// alternates must have title return without error, for now // alternates must have title return without error, for now
@ -797,13 +810,18 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
("nsContentSink::ProcessStyleLink, integrity=%s", ("nsContentSink::ProcessStyleLink, integrity=%s",
NS_ConvertUTF16toUTF8(integrity).get())); NS_ConvertUTF16toUTF8(integrity).get()));
} }
mozilla::net::ReferrerPolicy referrerPolicy =
mozilla::net::AttributeReferrerPolicyFromString(aReferrerPolicy);
if (referrerPolicy == net::RP_Unset) {
referrerPolicy = mDocument->GetReferrerPolicy();
}
// If this is a fragment parser, we don't want to observe. // If this is a fragment parser, we don't want to observe.
// We don't support CORS for processing instructions // We don't support CORS for processing instructions
bool isAlternate; bool isAlternate;
bool isExplicitlyEnabled; bool isExplicitlyEnabled;
rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate, rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
CORS_NONE, mDocument->GetReferrerPolicy(), CORS_NONE, referrerPolicy,
integrity, mRunsToCompletion ? nullptr : this, integrity, mRunsToCompletion ? nullptr : this,
&isAlternate, &isExplicitlyEnabled); &isAlternate, &isExplicitlyEnabled);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);

View file

@ -154,6 +154,7 @@ protected:
const nsSubstring& aHref, const nsSubstring& aRel, const nsSubstring& aHref, const nsSubstring& aRel,
const nsSubstring& aTitle, const nsSubstring& aType, const nsSubstring& aTitle, const nsSubstring& aType,
const nsSubstring& aMedia, const nsSubstring& aCrossOrigin, const nsSubstring& aMedia, const nsSubstring& aCrossOrigin,
const nsSubstring& aReferrerPolicy,
const nsSubstring& aDestination); const nsSubstring& aDestination);
virtual nsresult ProcessStyleLink(nsIContent* aElement, virtual nsresult ProcessStyleLink(nsIContent* aElement,
@ -161,7 +162,8 @@ protected:
bool aAlternate, bool aAlternate,
const nsSubstring& aTitle, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aType,
const nsSubstring& aMedia); const nsSubstring& aMedia,
const nsSubstring& aReferrerPolicy);
void PrefetchOrPreloadHref(const nsAString &aHref, void PrefetchOrPreloadHref(const nsAString &aHref,
nsINode *aSource, nsINode *aSource,

View file

@ -411,6 +411,16 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
bool doneLoading = false; bool doneLoading = false;
nsresult rv = NS_OK; nsresult rv = NS_OK;
// Load the link's referrerpolicy attribute. If the link does not provide a
// referrerpolicy attribute, ignore this and use the document's referrer
// policy
net::ReferrerPolicy referrerPolicy = GetLinkReferrerPolicy();
if (referrerPolicy == net::RP_Unset) {
referrerPolicy = doc->GetReferrerPolicy();
}
if (isInline) { if (isInline) {
nsAutoString text; nsAutoString text;
if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) { if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) {
@ -429,7 +439,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
// Parse the style sheet. // Parse the style sheet.
rv = doc->CSSLoader()-> rv = doc->CSSLoader()->
LoadInlineStyle(thisContent, text, mLineNumber, title, media, LoadInlineStyle(thisContent, text, mLineNumber, title, media, referrerPolicy,
scopeElement, aObserver, &doneLoading, &isAlternate, &isExplicitlyEnabled); scopeElement, aObserver, &doneLoading, &isAlternate, &isExplicitlyEnabled);
} else { } else {
nsAutoString integrity; nsAutoString integrity;
@ -440,15 +450,6 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
NS_ConvertUTF16toUTF8(integrity).get())); NS_ConvertUTF16toUTF8(integrity).get()));
} }
// if referrer attributes are enabled in preferences, load the link's referrer
// attribute. If the link does not provide a referrer attribute, ignore this
// and use the document's referrer policy
net::ReferrerPolicy referrerPolicy = GetLinkReferrerPolicy();
if (referrerPolicy == net::RP_Unset) {
referrerPolicy = doc->GetReferrerPolicy();
}
// XXXbz clone the URI here to work around content policies modifying URIs. // XXXbz clone the URI here to work around content policies modifying URIs.
nsCOMPtr<nsIURI> clonedURI; nsCOMPtr<nsIURI> clonedURI;
uri->Clone(getter_AddRefs(clonedURI)); uri->Clone(getter_AddRefs(clonedURI));

View file

@ -324,6 +324,12 @@ HTMLScriptElement::GetCORSMode() const
return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
} }
mozilla::net::ReferrerPolicy
HTMLScriptElement::GetReferrerPolicy()
{
return GetReferrerPolicyAsEnum();
}
bool bool
HTMLScriptElement::HasScriptContent() HTMLScriptElement::HasScriptContent()
{ {

View file

@ -42,6 +42,7 @@ public:
virtual void GetScriptCharset(nsAString& charset) override; virtual void GetScriptCharset(nsAString& charset) override;
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override; virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
virtual CORSMode GetCORSMode() const override; virtual CORSMode GetCORSMode() const override;
virtual mozilla::net::ReferrerPolicy GetReferrerPolicy() override;
// nsIContent // nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -96,6 +97,14 @@ public:
{ {
SetHTMLAttr(nsGkAtoms::integrity, aIntegrity, rv); SetHTMLAttr(nsGkAtoms::integrity, aIntegrity, rv);
} }
void SetReferrerPolicy(const nsAString& aReferrerPolicy, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrerPolicy, aError);
}
void GetReferrerPolicy(nsAString& aReferrerPolicy)
{
GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrerPolicy);
}
bool Async(); bool Async();
void SetAsync(bool aValue, ErrorResult& rv); void SetAsync(bool aValue, ErrorResult& rv);
bool NoModule(); bool NoModule();

View file

@ -24,7 +24,7 @@ SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests); SimpleTest.waitForFocus(runTests);
function runTests() { function runTests() {
var elements = [ "iframe", "img", "a", "area", "link" ]; var elements = [ "iframe", "img", "a", "area", "link", "script"];
for (var i = 0; i < elements.length; ++i) { for (var i = 0; i < elements.length; ++i) {
reflectLimitedEnumerated({ reflectLimitedEnumerated({

View file

@ -1563,7 +1563,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Step 15. and later in the HTML5 spec // Step 15. and later in the HTML5 spec
nsresult rv = NS_OK; nsresult rv = NS_OK;
RefPtr<ScriptLoadRequest> request; RefPtr<ScriptLoadRequest> request;
mozilla::net::ReferrerPolicy ourRefPolicy = mDocument->GetReferrerPolicy(); mozilla::net::ReferrerPolicy referrerPolicy = GetReferrerPolicy(aElement);
if (aElement->GetScriptExternal()) { if (aElement->GetScriptExternal()) {
// external script // external script
nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI(); nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
@ -1593,7 +1593,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
aElement->GetScriptCharset(elementCharset); aElement->GetScriptCharset(elementCharset);
if (elementCharset.Equals(preloadCharset) && if (elementCharset.Equals(preloadCharset) &&
ourCORSMode == request->CORSMode() && ourCORSMode == request->CORSMode() &&
ourRefPolicy == request->ReferrerPolicy() && referrerPolicy == request->ReferrerPolicy() &&
scriptKind == request->mKind) { scriptKind == request->mKind) {
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false); rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@ -1639,7 +1639,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
nsCOMPtr<nsIPrincipal> principal = scriptContent->NodePrincipal(); nsCOMPtr<nsIPrincipal> principal = scriptContent->NodePrincipal();
request = CreateLoadRequest(scriptKind, scriptURI, aElement, principal, request = CreateLoadRequest(scriptKind, scriptURI, aElement, principal,
ourCORSMode, sriMetadata, ourRefPolicy); ourCORSMode, sriMetadata, referrerPolicy);
request->mIsInline = false; request->mIsInline = false;
request->SetScriptMode(aElement->GetScriptDeferred(), request->SetScriptMode(aElement->GetScriptDeferred(),
aElement->GetScriptAsync()); aElement->GetScriptAsync());
@ -1760,7 +1760,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
mDocument->NodePrincipal(), mDocument->NodePrincipal(),
CORS_NONE, CORS_NONE,
SRIMetadata(), // SRI doesn't apply SRIMetadata(), // SRI doesn't apply
ourRefPolicy); referrerPolicy);
request->mIsInline = true; request->mIsInline = true;
request->mLineNo = aElement->GetScriptLineNumber(); request->mLineNo = aElement->GetScriptLineNumber();
@ -1826,6 +1826,17 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
return ProcessRequest(request) == NS_ERROR_HTMLPARSER_BLOCK; return ProcessRequest(request) == NS_ERROR_HTMLPARSER_BLOCK;
} }
mozilla::net::ReferrerPolicy
ScriptLoader::GetReferrerPolicy(nsIScriptElement* aElement)
{
mozilla::net::ReferrerPolicy scriptReferrerPolicy =
aElement->GetReferrerPolicy();
if (scriptReferrerPolicy != mozilla::net::RP_Unset) {
return scriptReferrerPolicy;
}
return mDocument->GetReferrerPolicy();
}
namespace { namespace {
class NotifyOffThreadScriptLoadCompletedRunnable : public Runnable class NotifyOffThreadScriptLoadCompletedRunnable : public Runnable

View file

@ -619,6 +619,12 @@ private:
void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest); void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest);
/**
* Given a script element, get the referrer policy that should be applied to
* load requests.
*/
mozilla::net::ReferrerPolicy GetReferrerPolicy(nsIScriptElement* aElement);
/** /**
* Helper function to check the content policy for a given request. * Helper function to check the content policy for a given request.
*/ */

View file

@ -16,6 +16,7 @@
#include "nsContentCreatorFunctions.h" #include "nsContentCreatorFunctions.h"
#include "nsIDOMHTMLScriptElement.h" #include "nsIDOMHTMLScriptElement.h"
#include "mozilla/CORSMode.h" #include "mozilla/CORSMode.h"
#include "mozilla/net/ReferrerPolicy.h"
#define NS_ISCRIPTELEMENT_IID \ #define NS_ISCRIPTELEMENT_IID \
{ 0xe60fca9b, 0x1b96, 0x4e4e, \ { 0xe60fca9b, 0x1b96, 0x4e4e, \
@ -263,6 +264,14 @@ public:
return mozilla::CORS_NONE; return mozilla::CORS_NONE;
} }
/**
* Get referrer policy of the script element
*/
virtual mozilla::net::ReferrerPolicy GetReferrerPolicy()
{
return mozilla::net::RP_Unset;
}
/** /**
* Fire an error event * Fire an error event
*/ */

View file

@ -25,6 +25,8 @@ interface HTMLScriptElement : HTMLElement {
[CEReactions, SetterThrows] [CEReactions, SetterThrows]
attribute DOMString? crossOrigin; attribute DOMString? crossOrigin;
[CEReactions, SetterThrows] [CEReactions, SetterThrows]
attribute DOMString referrerPolicy;
[CEReactions, SetterThrows]
attribute DOMString text; attribute DOMString text;
[CEReactions, SetterThrows, Pure] [CEReactions, SetterThrows, Pure]
attribute DOMString nonce; attribute DOMString nonce;

View file

@ -655,7 +655,8 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
bool aAlternate, bool aAlternate,
const nsSubstring& aTitle, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aType,
const nsSubstring& aMedia) const nsSubstring& aMedia,
const nsSubstring& aReferrerPolicy)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
mPrettyPrintXML = false; mPrettyPrintXML = false;
@ -714,7 +715,7 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
// Let nsContentSink deal with css. // Let nsContentSink deal with css.
rv = nsContentSink::ProcessStyleLink(aElement, aHref, aAlternate, rv = nsContentSink::ProcessStyleLink(aElement, aHref, aAlternate,
aTitle, aType, aMedia); aTitle, aType, aMedia, aReferrerPolicy);
// nsContentSink::ProcessStyleLink handles the bookkeeping here wrt // nsContentSink::ProcessStyleLink handles the bookkeeping here wrt
// pending sheets. // pending sheets.
@ -1261,7 +1262,9 @@ nsXMLContentSink::HandleProcessingInstruction(const char16_t *aTarget,
return DidProcessATokenImpl(); return DidProcessATokenImpl();
} }
rv = ProcessStyleLink(node, href, isAlternate, title, type, media); // <?xml-stylesheet?> processing instructions don't have a referrerpolicy
// pseudo-attribute, so we pass in an empty string
rv = ProcessStyleLink(node, href, isAlternate, title, type, media, EmptyString());
return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
} }

View file

@ -150,7 +150,8 @@ protected:
bool aAlternate, bool aAlternate,
const nsSubstring& aTitle, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aType,
const nsSubstring& aMedia) override; const nsSubstring& aMedia,
const nsSubstring& aReferrerPolicy) override;
nsresult LoadXSLStyleSheet(nsIURI* aUrl); nsresult LoadXSLStyleSheet(nsIURI* aUrl);

View file

@ -97,7 +97,9 @@ protected:
bool aAlternate, bool aAlternate,
const nsSubstring& aTitle, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aType,
const nsSubstring& aMedia) override; const nsSubstring& aMedia,
const nsSubstring& aReferrerPolicy) override;
nsresult LoadXSLStyleSheet(nsIURI* aUrl); nsresult LoadXSLStyleSheet(nsIURI* aUrl);
void StartLayout(); void StartLayout();
@ -332,7 +334,8 @@ nsXMLFragmentContentSink::ProcessStyleLink(nsIContent* aElement,
bool aAlternate, bool aAlternate,
const nsSubstring& aTitle, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aType,
const nsSubstring& aMedia) const nsSubstring& aMedia,
const nsSubstring& aReferrerPolicy)
{ {
// don't process until moved to document // don't process until moved to document
return NS_OK; return NS_OK;

View file

@ -1941,6 +1941,7 @@ Loader::LoadInlineStyle(nsIContent* aElement,
uint32_t aLineNumber, uint32_t aLineNumber,
const nsAString& aTitle, const nsAString& aTitle,
const nsAString& aMedia, const nsAString& aMedia,
ReferrerPolicy aReferrerPolicy,
Element* aScopeElement, Element* aScopeElement,
nsICSSLoaderObserver* aObserver, nsICSSLoaderObserver* aObserver,
bool* aCompleted, bool* aCompleted,
@ -1964,11 +1965,12 @@ Loader::LoadInlineStyle(nsIContent* aElement,
// Since we're not planning to load a URI, no need to hand a principal to the // Since we're not planning to load a URI, no need to hand a principal to the
// load data or to CreateSheet(). Also, OK to use CORS_NONE for the CORS // load data or to CreateSheet(). Also, OK to use CORS_NONE for the CORS
// mode and mDocument's ReferrerPolicy. // mode.
StyleSheetState state; StyleSheetState state;
RefPtr<StyleSheet> sheet; RefPtr<StyleSheet> sheet;
nsresult rv = CreateSheet(nullptr, aElement, nullptr, eAuthorSheetFeatures, nsresult rv = CreateSheet(nullptr, aElement, nullptr, eAuthorSheetFeatures,
CORS_NONE, mDocument->GetReferrerPolicy(), CORS_NONE, aReferrerPolicy,
EmptyString(), // no inline integrity checks EmptyString(), // no inline integrity checks
false, false, aTitle, state, aIsAlternate, false, false, aTitle, state, aIsAlternate,
&sheet); &sheet);

View file

@ -224,6 +224,7 @@ public:
* @param aLineNumber the line number at which the stylesheet data started. * @param aLineNumber the line number at which the stylesheet data started.
* @param aTitle the title of the sheet. * @param aTitle the title of the sheet.
* @param aMedia the media string for the sheet. * @param aMedia the media string for the sheet.
* @param aReferrerPolicy the referrer policy for loading the sheet.
* @param aObserver the observer to notify when the load completes. * @param aObserver the observer to notify when the load completes.
* May be null. * May be null.
* @param [out] aCompleted whether parsing of the sheet completed. * @param [out] aCompleted whether parsing of the sheet completed.
@ -237,6 +238,7 @@ public:
uint32_t aLineNumber, uint32_t aLineNumber,
const nsAString& aTitle, const nsAString& aTitle,
const nsAString& aMedia, const nsAString& aMedia,
ReferrerPolicy aReferrerPolicy,
mozilla::dom::Element* aScopeElement, mozilla::dom::Element* aScopeElement,
nsICSSLoaderObserver* aObserver, nsICSSLoaderObserver* aObserver,
bool* aCompleted, bool* aCompleted,

View file

@ -28,16 +28,18 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
{ {
switch (mOpCode) { switch (mOpCode) {
case eSpeculativeLoadBase: case eSpeculativeLoadBase:
aExecutor->SetSpeculationBase(mUrl); aExecutor->SetSpeculationBase(mUrlOrSizes);
break; break;
case eSpeculativeLoadCSP: case eSpeculativeLoadCSP:
aExecutor->AddSpeculationCSP(mMetaCSP); aExecutor->AddSpeculationCSP(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
break; break;
case eSpeculativeLoadMetaReferrer: case eSpeculativeLoadMetaReferrer:
aExecutor->SetSpeculationReferrerPolicy(mReferrerPolicy); aExecutor->SetSpeculationReferrerPolicy(mReferrerPolicyOrIntegrity);
break; break;
case eSpeculativeLoadImage: case eSpeculativeLoadImage:
aExecutor->PreloadImage(mUrl, mCrossOrigin, mSrcset, mSizes, mReferrerPolicy); aExecutor->PreloadImage(mUrlOrSizes, mCrossOriginOrMedia, mCharsetOrSrcset,
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
mReferrerPolicyOrIntegrity);
break; break;
case eSpeculativeLoadOpenPicture: case eSpeculativeLoadOpenPicture:
aExecutor->PreloadOpenPicture(); aExecutor->PreloadOpenPicture();
@ -46,55 +48,61 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
aExecutor->PreloadEndPicture(); aExecutor->PreloadEndPicture();
break; break;
case eSpeculativeLoadPictureSource: case eSpeculativeLoadPictureSource:
aExecutor->PreloadPictureSource(mSrcset, mSizes, mTypeOrCharsetSourceOrDocumentMode, aExecutor->PreloadPictureSource(mCharsetOrSrcset, mUrlOrSizes,
mMedia); mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
mCrossOriginOrMedia);
break; break;
case eSpeculativeLoadScript: case eSpeculativeLoadScript:
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode, aExecutor->PreloadScript(mUrlOrSizes, mCharsetOrSrcset,
mCrossOrigin, mIntegrity, false, mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity, mScriptReferrerPolicy, false,
mIsAsync, mIsDefer, false); mIsAsync, mIsDefer, false);
break; break;
case eSpeculativeLoadScriptFromHead: case eSpeculativeLoadScriptFromHead:
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode, aExecutor->PreloadScript(mUrlOrSizes, mCharsetOrSrcset,
mCrossOrigin, mIntegrity, true, mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity, mScriptReferrerPolicy, true,
mIsAsync, mIsDefer, false); mIsAsync, mIsDefer, false);
break; break;
case eSpeculativeLoadNoModuleScript: case eSpeculativeLoadNoModuleScript:
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode, aExecutor->PreloadScript(mUrlOrSizes, mCharsetOrSrcset,
mCrossOrigin, mIntegrity, false, mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity, mScriptReferrerPolicy, false,
mIsAsync, mIsDefer, true); mIsAsync, mIsDefer, true);
break; break;
case eSpeculativeLoadNoModuleScriptFromHead: case eSpeculativeLoadNoModuleScriptFromHead:
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode, aExecutor->PreloadScript(mUrlOrSizes, mCharsetOrSrcset,
mCrossOrigin, mIntegrity, true, mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity, mScriptReferrerPolicy, true,
mIsAsync, mIsDefer, true); mIsAsync, mIsDefer, true);
break; break;
case eSpeculativeLoadStyle: case eSpeculativeLoadStyle:
aExecutor->PreloadStyle(mUrl, mCharset, mCrossOrigin, mIntegrity); aExecutor->PreloadStyle(mUrlOrSizes, mCharsetOrSrcset, mCrossOriginOrMedia, mReferrerPolicyOrIntegrity,
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
break; break;
case eSpeculativeLoadManifest: case eSpeculativeLoadManifest:
aExecutor->ProcessOfflineManifest(mUrl); aExecutor->ProcessOfflineManifest(mUrlOrSizes);
break; break;
case eSpeculativeLoadSetDocumentCharset: { case eSpeculativeLoadSetDocumentCharset: {
nsAutoCString narrowName; nsAutoCString narrowName;
CopyUTF16toUTF8(mCharset, narrowName); CopyUTF16toUTF8(mCharsetOrSrcset, narrowName);
NS_ASSERTION(mTypeOrCharsetSourceOrDocumentMode.Length() == 1, NS_ASSERTION(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Length() == 1,
"Unexpected charset source string"); "Unexpected charset source string");
int32_t intSource = (int32_t)mTypeOrCharsetSourceOrDocumentMode.First(); int32_t intSource = (int32_t)mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.First();
aExecutor->SetDocumentCharsetAndSource(narrowName, aExecutor->SetDocumentCharsetAndSource(narrowName,
intSource); intSource);
} }
break; break;
case eSpeculativeLoadSetDocumentMode: { case eSpeculativeLoadSetDocumentMode: {
NS_ASSERTION(mTypeOrCharsetSourceOrDocumentMode.Length() == 1, NS_ASSERTION(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Length() == 1,
"Unexpected document mode string"); "Unexpected document mode string");
nsHtml5DocumentMode mode = nsHtml5DocumentMode mode =
(nsHtml5DocumentMode)mTypeOrCharsetSourceOrDocumentMode.First(); (nsHtml5DocumentMode)mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.First();
aExecutor->SetDocumentMode(mode); aExecutor->SetDocumentMode(mode);
} }
break; break;
case eSpeculativeLoadPreconnect: case eSpeculativeLoadPreconnect:
aExecutor->Preconnect(mUrl, mCrossOrigin); aExecutor->Preconnect(mUrlOrSizes, mCrossOriginOrMedia);
break; break;
default: default:
NS_NOTREACHED("Bogus speculative load."); NS_NOTREACHED("Bogus speculative load.");

View file

@ -7,6 +7,7 @@
#include "nsString.h" #include "nsString.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "mozilla/net/ReferrerPolicy.h"
class nsHtml5TreeOpExecutor; class nsHtml5TreeOpExecutor;
@ -43,7 +44,7 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadBase; mOpCode = eSpeculativeLoadBase;
aUrl.ToString(mUrl); aUrl.ToString(mUrlOrSizes);
} }
inline void InitMetaCSP(nsHtml5String aCSP) inline void InitMetaCSP(nsHtml5String aCSP)
@ -53,7 +54,7 @@ class nsHtml5SpeculativeLoad {
mOpCode = eSpeculativeLoadCSP; mOpCode = eSpeculativeLoadCSP;
nsString csp; // Not Auto, because using it to hold nsStringBuffer* nsString csp; // Not Auto, because using it to hold nsStringBuffer*
aCSP.ToString(csp); aCSP.ToString(csp);
mMetaCSP.Assign( mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp)); nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp));
} }
@ -65,7 +66,7 @@ class nsHtml5SpeculativeLoad {
nsString nsString
referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
aReferrerPolicy.ToString(referrerPolicy); aReferrerPolicy.ToString(referrerPolicy);
mReferrerPolicy.Assign( mReferrerPolicyOrIntegrity.Assign(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
referrerPolicy)); referrerPolicy));
} }
@ -79,16 +80,16 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadImage; mOpCode = eSpeculativeLoadImage;
aUrl.ToString(mUrl); aUrl.ToString(mUrlOrSizes);
aCrossOrigin.ToString(mCrossOrigin); aCrossOrigin.ToString(mCrossOriginOrMedia);
nsString nsString
referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
aReferrerPolicy.ToString(referrerPolicy); aReferrerPolicy.ToString(referrerPolicy);
mReferrerPolicy.Assign( mReferrerPolicyOrIntegrity.Assign(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
referrerPolicy)); referrerPolicy));
aSrcset.ToString(mSrcset); aSrcset.ToString(mCharsetOrSrcset);
aSizes.ToString(mSizes); aSizes.ToString(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
} }
// <picture> elements have multiple <source> nodes followed by an <img>, // <picture> elements have multiple <source> nodes followed by an <img>,
@ -120,10 +121,10 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadPictureSource; mOpCode = eSpeculativeLoadPictureSource;
aSrcset.ToString(mSrcset); aSrcset.ToString(mCharsetOrSrcset);
aSizes.ToString(mSizes); aSizes.ToString(mUrlOrSizes);
aType.ToString(mTypeOrCharsetSourceOrDocumentMode); aType.ToString(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
aMedia.ToString(mMedia); aMedia.ToString(mCrossOriginOrMedia);
} }
inline void InitScript(nsHtml5String aUrl, inline void InitScript(nsHtml5String aUrl,
@ -131,6 +132,7 @@ class nsHtml5SpeculativeLoad {
nsHtml5String aType, nsHtml5String aType,
nsHtml5String aCrossOrigin, nsHtml5String aCrossOrigin,
nsHtml5String aIntegrity, nsHtml5String aIntegrity,
nsHtml5String aReferrerPolicy,
bool aParserInHead, bool aParserInHead,
bool aAsync, bool aAsync,
bool aDefer, bool aDefer,
@ -145,11 +147,19 @@ class nsHtml5SpeculativeLoad {
mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead
: eSpeculativeLoadScript; : eSpeculativeLoadScript;
} }
aUrl.ToString(mUrl); aUrl.ToString(mUrlOrSizes);
aCharset.ToString(mCharset); aCharset.ToString(mCharsetOrSrcset);
aType.ToString(mTypeOrCharsetSourceOrDocumentMode); aType.ToString(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
aCrossOrigin.ToString(mCrossOrigin); aCrossOrigin.ToString(mCrossOriginOrMedia);
aIntegrity.ToString(mIntegrity); aIntegrity.ToString(mReferrerPolicyOrIntegrity);
nsAutoString referrerPolicy;
aReferrerPolicy.ToString(referrerPolicy);
referrerPolicy =
nsContentUtils::TrimWhitespace<
nsContentUtils::IsHTMLWhitespace>(referrerPolicy);
mScriptReferrerPolicy =
mozilla::net::AttributeReferrerPolicyFromString(referrerPolicy);
mIsAsync = aAsync; mIsAsync = aAsync;
mIsDefer = aDefer; mIsDefer = aDefer;
} }
@ -157,15 +167,22 @@ class nsHtml5SpeculativeLoad {
inline void InitStyle(nsHtml5String aUrl, inline void InitStyle(nsHtml5String aUrl,
nsHtml5String aCharset, nsHtml5String aCharset,
nsHtml5String aCrossOrigin, nsHtml5String aCrossOrigin,
nsHtml5String aReferrerPolicy,
nsHtml5String aIntegrity) nsHtml5String aIntegrity)
{ {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadStyle; mOpCode = eSpeculativeLoadStyle;
aUrl.ToString(mUrl); aUrl.ToString(mUrlOrSizes);
aCharset.ToString(mCharset); aCharset.ToString(mCharsetOrSrcset);
aCrossOrigin.ToString(mCrossOrigin); aCrossOrigin.ToString(mCrossOriginOrMedia);
aIntegrity.ToString(mIntegrity); nsString
referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
aReferrerPolicy.ToString(referrerPolicy);
mReferrerPolicyOrIntegrity.Assign(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
referrerPolicy));
aIntegrity.ToString(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
} }
/** /**
@ -184,7 +201,7 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadManifest; mOpCode = eSpeculativeLoadManifest;
aUrl.ToString(mUrl); aUrl.ToString(mUrlOrSizes);
} }
/** /**
@ -203,8 +220,8 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadSetDocumentCharset; mOpCode = eSpeculativeLoadSetDocumentCharset;
CopyUTF8toUTF16(aCharset, mCharset); CopyUTF8toUTF16(aCharset, mCharsetOrSrcset);
mTypeOrCharsetSourceOrDocumentMode.Assign((char16_t)aCharsetSource); mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign((char16_t)aCharsetSource);
} }
/** /**
@ -218,7 +235,7 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadSetDocumentMode; mOpCode = eSpeculativeLoadSetDocumentMode;
mTypeOrCharsetSourceOrDocumentMode.Assign((char16_t)aMode); mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign((char16_t)aMode);
} }
inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin)
@ -226,8 +243,8 @@ class nsHtml5SpeculativeLoad {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!"); "Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadPreconnect; mOpCode = eSpeculativeLoadPreconnect;
aUrl.ToString(mUrl); aUrl.ToString(mUrlOrSizes);
aCrossOrigin.ToString(mCrossOrigin); aCrossOrigin.ToString(mCrossOriginOrMedia);
} }
void Perform(nsHtml5TreeOpExecutor* aExecutor); void Perform(nsHtml5TreeOpExecutor* aExecutor);
@ -241,55 +258,56 @@ class nsHtml5SpeculativeLoad {
bool mIsAsync; bool mIsAsync;
bool mIsDefer; bool mIsDefer;
nsString mUrl; /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
nsString mReferrerPolicy; * "sizes" attribute. If the attribute is not set, this will be a void
nsString mMetaCSP; * string. Otherwise it empty or the value of the url.
*/
nsString mUrlOrSizes;
/**
* If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
* "integrity" attribute. If the attribute is not set, this will be a void
* string. Otherwise it is empty or the value of the referrer policy.
*/
nsString mReferrerPolicyOrIntegrity;
/** /**
* If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead] * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
* then this is the value of the "charset" attribute. For * then this is the value of the "charset" attribute. For
* eSpeculativeLoadSetDocumentCharset it is the charset that the * eSpeculativeLoadSetDocumentCharset it is the charset that the
* document's charset is being set to. Otherwise it's empty. * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
* or eSpeculativeLoadPictureSource, this is the value of the "srcset" attribute.
* If the attribute is not set, this will be a void string. Otherwise it's empty.
*/ */
nsString mCharset; nsString mCharsetOrSrcset;
/** /**
* If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
* one-character string whose single character's code point is to be * one-character string whose single character's code point is to be
* interpreted as a charset source integer. If mOpCode is * interpreted as a charset source integer. If mOpCode is
* eSpeculativeLoadSetDocumentMode, this is a one-character string whose * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
* single character's code point is to be interpreted as an * single character's code point is to be interpreted as an
* nsHtml5DocumentMode. Otherwise, it is empty or the value of the type * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
* attribute. * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
* value of the "sizes" attribute. If the attribute is not set, this will
* be a void string. If mOpCode is eSpeculativeLoadStyle, this
* is the value of the "integrity" attribute. If the attribute is not set,
* this will be a void string. Otherwise it is empty or the value of the
* referrer policy. Otherwise, it is empty or the value of the type attribute.
*/ */
nsString mTypeOrCharsetSourceOrDocumentMode; nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity;
/** /**
* If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead] * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
* or eSpeculativeLoadPreconnect this is the value of the "crossorigin" * or eSpeculativeLoadPreconnect this is the value of the "crossorigin"
* attribute. If the attribute is not set, this will be a void string. * attribute. If the attribute is not set, this will be a void string.
* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
* "media" attribute. If the attribute is not set, this will be a void string.
*/ */
nsString mCrossOrigin; nsString mCrossOriginOrMedia;
/** /**
* If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadPictureSource, * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
* this is the value of "srcset" attribute. If the attribute is not set, * of the "referrerpolicy" attribute. This field holds one of the values
* this will be a void string. * (REFERRER_POLICY_*) defined in nsIHttpChannel.
*/ */
nsString mSrcset; mozilla::net::ReferrerPolicy mScriptReferrerPolicy;
/**
* If mOpCode is eSpeculativeLoadPictureSource, this is the value of "sizes"
* attribute. If the attribute is not set, this will be a void string.
*/
nsString mSizes;
/**
* If mOpCode is eSpeculativeLoadPictureSource, this is the value of "media"
* attribute. If the attribute is not set, this will be a void string.
*/
nsString mMedia;
/**
* If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
* "integrity" attribute. If the attribute is not set, this will be a void
* string.
*/
nsString mIntegrity;
}; };
#endif // nsHtml5SpeculativeLoad_h #endif // nsHtml5SpeculativeLoad_h

View file

@ -184,6 +184,8 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
nsHtml5String integrity = nsHtml5String integrity =
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
nsHtml5String referrerPolicy =
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
bool async = bool async =
aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC); aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC);
bool defer = bool defer =
@ -196,6 +198,7 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
type, type,
crossOrigin, crossOrigin,
integrity, integrity,
referrerPolicy,
mode == nsHtml5TreeBuilder::IN_HEAD, mode == nsHtml5TreeBuilder::IN_HEAD,
async, async,
defer, defer,
@ -218,8 +221,10 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
nsHtml5String integrity = nsHtml5String integrity =
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
nsHtml5String referrerPolicy =
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
mSpeculativeLoadQueue.AppendElement()->InitStyle( mSpeculativeLoadQueue.AppendElement()->InitStyle(
url, charset, crossOrigin, integrity); url, charset, crossOrigin, referrerPolicy, integrity);
} }
} else if (rel.LowerCaseEqualsASCII("preconnect")) { } else if (rel.LowerCaseEqualsASCII("preconnect")) {
nsHtml5String url = nsHtml5String url =
@ -245,12 +250,15 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
nsHtml5String integrity = nsHtml5String integrity =
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
nsHtml5String referrerPolicy =
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
mSpeculativeLoadQueue.AppendElement()->InitScript( mSpeculativeLoadQueue.AppendElement()->InitScript(
url, url,
charset, charset,
type, type,
crossOrigin, crossOrigin,
integrity, integrity,
referrerPolicy,
mode == nsHtml5TreeBuilder::IN_HEAD, mode == nsHtml5TreeBuilder::IN_HEAD,
false, false,
false, false,
@ -263,8 +271,10 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
nsHtml5String integrity = nsHtml5String integrity =
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
nsHtml5String referrerPolicy =
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
mSpeculativeLoadQueue.AppendElement()->InitStyle( mSpeculativeLoadQueue.AppendElement()->InitStyle(
url, charset, crossOrigin, integrity); url, charset, crossOrigin, referrerPolicy, integrity);
} else if (preloadAs.LowerCaseEqualsASCII("image")) { } else if (preloadAs.LowerCaseEqualsASCII("image")) {
nsHtml5String srcset = nsHtml5String srcset =
aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET); aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
@ -345,12 +355,15 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
nsHtml5String integrity = nsHtml5String integrity =
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
nsHtml5String referrerPolicy =
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
mSpeculativeLoadQueue.AppendElement()->InitScript( mSpeculativeLoadQueue.AppendElement()->InitScript(
url, url,
nullptr, nullptr,
type, type,
crossOrigin, crossOrigin,
integrity, integrity,
referrerPolicy,
mode == nsHtml5TreeBuilder::IN_HEAD, mode == nsHtml5TreeBuilder::IN_HEAD,
false /* async */, false /* async */,
false /* defer */, false /* defer */,
@ -368,8 +381,10 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
nsHtml5String integrity = nsHtml5String integrity =
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
nsHtml5String referrerPolicy =
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
mSpeculativeLoadQueue.AppendElement()->InitStyle( mSpeculativeLoadQueue.AppendElement()->InitStyle(
url, nullptr, crossOrigin, integrity); url, nullptr, crossOrigin, referrerPolicy, integrity);
} }
} }
break; break;

View file

@ -914,12 +914,23 @@ nsHtml5TreeOpExecutor::ShouldPreloadURI(nsIURI *aURI)
return true; return true;
} }
net::ReferrerPolicy
nsHtml5TreeOpExecutor::GetPreloadReferrerPolicy(
const nsAString& aReferrerPolicy)
{
net::ReferrerPolicy referrerPolicy =
net::AttributeReferrerPolicyFromString(aReferrerPolicy);
return referrerPolicy != net::RP_Unset ? referrerPolicy :
mSpeculationReferrerPolicy;
}
void void
nsHtml5TreeOpExecutor::PreloadScript(const nsAString& aURL, nsHtml5TreeOpExecutor::PreloadScript(const nsAString& aURL,
const nsAString& aCharset, const nsAString& aCharset,
const nsAString& aType, const nsAString& aType,
const nsAString& aCrossOrigin, const nsAString& aCrossOrigin,
const nsAString& aIntegrity, const nsAString& aIntegrity,
net::ReferrerPolicy aReferrerPolicy,
bool aScriptFromHead, bool aScriptFromHead,
bool aAsync, bool aAsync,
bool aDefer, bool aDefer,
@ -929,24 +940,35 @@ nsHtml5TreeOpExecutor::PreloadScript(const nsAString& aURL,
if (!uri) { if (!uri) {
return; return;
} }
mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin, net::ReferrerPolicy referrerPolicy = aReferrerPolicy != net::RP_Unset ?
aIntegrity, aScriptFromHead, aAsync, aReferrerPolicy : mSpeculationReferrerPolicy;
aDefer, aNoModule, mDocument->ScriptLoader()
mSpeculationReferrerPolicy); ->PreloadURI(uri,
aCharset,
aType,
aCrossOrigin,
aIntegrity,
aScriptFromHead,
aAsync,
aDefer,
aNoModule,
referrerPolicy);
} }
void void
nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL, nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL,
const nsAString& aCharset, const nsAString& aCharset,
const nsAString& aCrossOrigin, const nsAString& aCrossOrigin,
const nsAString& aReferrerPolicy,
const nsAString& aIntegrity) const nsAString& aIntegrity)
{ {
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL); nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
if (!uri) { if (!uri) {
return; return;
} }
mDocument->PreloadStyle(uri, aCharset, aCrossOrigin,
mSpeculationReferrerPolicy, aIntegrity); mDocument->PreloadStyle(uri, aCharset, aCrossOrigin, GetPreloadReferrerPolicy(aReferrerPolicy),
aIntegrity);
} }
void void
@ -962,18 +984,10 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
aSizes, &isImgSet); aSizes, &isImgSet);
if (uri && ShouldPreloadURI(uri)) { if (uri && ShouldPreloadURI(uri)) {
// use document wide referrer policy // use document wide referrer policy
mozilla::net::ReferrerPolicy referrerPolicy = mSpeculationReferrerPolicy; mDocument->MaybePreLoadImage(uri,
// if enabled in preferences, use the referrer attribute from the image, if provided aCrossOrigin,
bool referrerAttributeEnabled = Preferences::GetBool("network.http.enablePerElementReferrer", true); GetPreloadReferrerPolicy(aImageReferrerPolicy),
if (referrerAttributeEnabled) { isImgSet);
mozilla::net::ReferrerPolicy imageReferrerPolicy =
mozilla::net::AttributeReferrerPolicyFromString(aImageReferrerPolicy);
if (imageReferrerPolicy != mozilla::net::RP_Unset) {
referrerPolicy = imageReferrerPolicy;
}
}
mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy, isImgSet);
} }
} }

View file

@ -249,6 +249,7 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
const nsAString& aType, const nsAString& aType,
const nsAString& aCrossOrigin, const nsAString& aCrossOrigin,
const nsAString& aIntegrity, const nsAString& aIntegrity,
ReferrerPolicy aReferrerPolicy,
bool aScriptFromHead, bool aScriptFromHead,
bool aAsync, bool aAsync,
bool aDefer, bool aDefer,
@ -256,6 +257,7 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
void PreloadStyle(const nsAString& aURL, const nsAString& aCharset, void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
const nsAString& aCrossOrigin, const nsAString& aCrossOrigin,
const nsAString& aReferrerPolicy,
const nsAString& aIntegrity); const nsAString& aIntegrity);
void PreloadImage(const nsAString& aURL, void PreloadImage(const nsAString& aURL,
@ -304,6 +306,8 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
* list of preloaded URIs * list of preloaded URIs
*/ */
bool ShouldPreloadURI(nsIURI *aURI); bool ShouldPreloadURI(nsIURI *aURI);
ReferrerPolicy GetPreloadReferrerPolicy(const nsAString& aReferrerPolicy);
}; };
#endif // nsHtml5TreeOpExecutor_h #endif // nsHtml5TreeOpExecutor_h