зеркало из https://github.com/mozilla/gecko-dev.git
bug 1174152 - crossorigin attribute for link rel=preconnect r=hsivonen
This commit is contained in:
Родитель
dfed61553f
Коммит
cc04db5e46
|
@ -446,6 +446,9 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
|||
nsAutoString type;
|
||||
nsAutoString media;
|
||||
nsAutoString anchor;
|
||||
nsAutoString crossOrigin;
|
||||
|
||||
crossOrigin.SetIsVoid(true);
|
||||
|
||||
// copy to work buffer
|
||||
nsAutoString stringList(aLinkData);
|
||||
|
@ -620,6 +623,12 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
|||
anchor = value;
|
||||
anchor.StripWhitespace();
|
||||
}
|
||||
} else if (attr.LowerCaseEqualsLiteral("crossorigin")) {
|
||||
if (crossOrigin.IsVoid()) {
|
||||
crossOrigin.SetIsVoid(false);
|
||||
crossOrigin = value;
|
||||
crossOrigin.StripWhitespace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +642,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
|||
rv = ProcessLink(anchor, href, rel,
|
||||
// prefer RFC 5987 variant over non-I18zed version
|
||||
titleStar.IsEmpty() ? title : titleStar,
|
||||
type, media);
|
||||
type, media, crossOrigin);
|
||||
}
|
||||
|
||||
href.Truncate();
|
||||
|
@ -642,6 +651,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
|||
type.Truncate();
|
||||
media.Truncate();
|
||||
anchor.Truncate();
|
||||
crossOrigin.SetIsVoid(true);
|
||||
|
||||
seenParameters = false;
|
||||
}
|
||||
|
@ -654,7 +664,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
|||
rv = ProcessLink(anchor, href, rel,
|
||||
// prefer RFC 5987 variant over non-I18zed version
|
||||
titleStar.IsEmpty() ? title : titleStar,
|
||||
type, media);
|
||||
type, media, crossOrigin);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -664,7 +674,8 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
|||
nsresult
|
||||
nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
|
||||
const nsSubstring& aRel, const nsSubstring& aTitle,
|
||||
const nsSubstring& aType, const nsSubstring& aMedia)
|
||||
const nsSubstring& aType, const nsSubstring& aMedia,
|
||||
const nsSubstring& aCrossOrigin)
|
||||
{
|
||||
uint32_t linkTypes =
|
||||
nsStyleLinkElement::ParseLinkTypes(aRel, mDocument->NodePrincipal());
|
||||
|
@ -688,7 +699,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
|
|||
}
|
||||
|
||||
if (!aHref.IsEmpty() && (linkTypes & nsStyleLinkElement::ePRECONNECT)) {
|
||||
Preconnect(aHref);
|
||||
Preconnect(aHref, aCrossOrigin);
|
||||
}
|
||||
|
||||
// is it a stylesheet link?
|
||||
|
@ -875,7 +886,7 @@ nsContentSink::PrefetchDNS(const nsAString &aHref)
|
|||
}
|
||||
|
||||
void
|
||||
nsContentSink::Preconnect(const nsAString &aHref)
|
||||
nsContentSink::Preconnect(const nsAString& aHref, const nsAString& aCrossOrigin)
|
||||
{
|
||||
// construct URI using document charset
|
||||
const nsACString& charset = mDocument->GetDocumentCharacterSet();
|
||||
|
@ -885,7 +896,7 @@ nsContentSink::Preconnect(const nsAString &aHref)
|
|||
mDocument->GetDocBaseURI());
|
||||
|
||||
if (uri && mDocument) {
|
||||
mDocument->MaybePreconnect(uri);
|
||||
mDocument->MaybePreconnect(uri, dom::Element::StringToCORSMode(aCrossOrigin));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ protected:
|
|||
nsresult ProcessLink(const nsSubstring& aAnchor,
|
||||
const nsSubstring& aHref, const nsSubstring& aRel,
|
||||
const nsSubstring& aTitle, const nsSubstring& aType,
|
||||
const nsSubstring& aMedia);
|
||||
const nsSubstring& aMedia, const nsSubstring& aCrossOrigin);
|
||||
|
||||
virtual nsresult ProcessStyleLink(nsIContent* aElement,
|
||||
const nsSubstring& aHref,
|
||||
|
@ -225,7 +225,7 @@ public:
|
|||
|
||||
// For Preconnect() aHref can either be the usual
|
||||
// URI format or of the form "//www.hostname.com" without a scheme.
|
||||
void Preconnect(const nsAString &aHref);
|
||||
void Preconnect(const nsAString& aHref, const nsAString& aCrossOrigin);
|
||||
|
||||
protected:
|
||||
// Tries to scroll to the URI's named anchor. Once we've successfully
|
||||
|
|
|
@ -9763,8 +9763,26 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
|
|||
}
|
||||
|
||||
void
|
||||
nsDocument::MaybePreconnect(nsIURI* uri)
|
||||
nsDocument::MaybePreconnect(nsIURI* aOrigURI, mozilla::CORSMode aCORSMode)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_FAILED(aOrigURI->Clone(getter_AddRefs(uri)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The URI created here is used in 2 contexts. One is nsISpeculativeConnect
|
||||
// which ignores the path and uses only the origin. The other is for the
|
||||
// document mPreloadedPreconnects de-duplication hash. Anonymous vs
|
||||
// non-Anonymous preconnects create different connections on the wire and
|
||||
// therefore should not be considred duplicates of each other and we
|
||||
// normalize the path before putting it in the hash to accomplish that.
|
||||
|
||||
if (aCORSMode == CORS_ANONYMOUS) {
|
||||
uri->SetPath(NS_LITERAL_CSTRING("/anonymous"));
|
||||
} else {
|
||||
uri->SetPath(NS_LITERAL_CSTRING("/"));
|
||||
}
|
||||
|
||||
if (mPreloadedPreconnects.Contains(uri)) {
|
||||
return;
|
||||
}
|
||||
|
@ -9776,7 +9794,11 @@ nsDocument::MaybePreconnect(nsIURI* uri)
|
|||
return;
|
||||
}
|
||||
|
||||
speculator->SpeculativeConnect(uri, nullptr);
|
||||
if (aCORSMode == CORS_ANONYMOUS) {
|
||||
speculator->SpeculativeAnonymousConnect(uri, nullptr);
|
||||
} else {
|
||||
speculator->SpeculativeConnect(uri, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1141,7 +1141,8 @@ public:
|
|||
ReferrerPolicy aReferrerPolicy) override;
|
||||
virtual void ForgetImagePreload(nsIURI* aURI) override;
|
||||
|
||||
virtual void MaybePreconnect(nsIURI* uri) override;
|
||||
virtual void MaybePreconnect(nsIURI* uri,
|
||||
mozilla::CORSMode aCORSMode) override;
|
||||
|
||||
virtual void PreloadStyle(nsIURI* uri, const nsAString& charset,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "nsClassHashtable.h"
|
||||
#include "prclist.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include <bitset> // for member
|
||||
|
||||
class imgIRequest;
|
||||
|
@ -2037,7 +2038,8 @@ public:
|
|||
/**
|
||||
* Called by Parser for link rel=preconnect
|
||||
*/
|
||||
virtual void MaybePreconnect(nsIURI* uri) = 0;
|
||||
virtual void MaybePreconnect(nsIURI* uri,
|
||||
mozilla::CORSMode aCORSMode) = 0;
|
||||
|
||||
enum DocumentTheme {
|
||||
Doc_Theme_Uninitialized, // not determined yet
|
||||
|
|
|
@ -316,7 +316,7 @@ HTMLLinkElement::UpdatePreconnect()
|
|||
if (owner) {
|
||||
nsCOMPtr<nsIURI> uri = GetHrefURI();
|
||||
if (uri) {
|
||||
owner->MaybePreconnect(uri);
|
||||
owner->MaybePreconnect(uri, GetCORSMode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ function handleRequest(request, response)
|
|||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Link", "<" +
|
||||
request.getHeader('X-Link') +
|
||||
">; rel=preconnect");
|
||||
">; rel=preconnect" + ", " +
|
||||
"<" +
|
||||
request.getHeader('X-Link') +
|
||||
">; rel=preconnect; crossOrigin=anonymous");
|
||||
response.write("check that header");
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ function TestServer1(nextTest) {
|
|||
}
|
||||
|
||||
TestServer1.prototype = {
|
||||
remainder : 2,
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
iid = SpecialPowers.wrap(iid);
|
||||
if (iid.equals(Ci.nsIServerSocketListener) ||
|
||||
|
@ -32,12 +34,12 @@ TestServer1.prototype = {
|
|||
onSocketAccepted: function(socket, trans) {
|
||||
try { socket.close(); } catch(e) {}
|
||||
try { trans.close(); } catch(e) {}
|
||||
ok(true, "received connect");
|
||||
srv1.listener.close();
|
||||
if(srv1.nextTest != null) {
|
||||
setTimeout(srv1.nextTest, 0);
|
||||
this.remainder--;
|
||||
ok(true, "received connect remainder = " + this.remainder);
|
||||
if (!this.remainder) {
|
||||
srv1.listener.close();
|
||||
setTimeout(srv1.nextTest, 0);
|
||||
}
|
||||
srv1.nextTest = null;
|
||||
},
|
||||
onStopListening: function(socket) {}
|
||||
};
|
||||
|
@ -51,6 +53,8 @@ function TestServer2(nextTest) {
|
|||
}
|
||||
|
||||
TestServer2.prototype = {
|
||||
remainder : 2,
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
iid = SpecialPowers.wrap(iid);
|
||||
if (iid.equals(Ci.nsIServerSocketListener) ||
|
||||
|
@ -61,12 +65,12 @@ TestServer2.prototype = {
|
|||
onSocketAccepted: function(socket, trans) {
|
||||
try { socket.close(); } catch(e) {}
|
||||
try { trans.close(); } catch(e) {}
|
||||
ok(true, "received connect");
|
||||
srv2.listener.close();
|
||||
if(srv2.nextTest != null) {
|
||||
setTimeout(srv2.nextTest, 0);
|
||||
this.remainder--;
|
||||
ok(true, "received connect srv2 remainder = " + this.remainder);
|
||||
if (!this.remainder) {
|
||||
srv2.listener.close();
|
||||
setTimeout(srv2.nextTest, 0);
|
||||
}
|
||||
srv2.nextTest = null;
|
||||
},
|
||||
onStopListening: function(socket) {}
|
||||
};
|
||||
|
@ -75,18 +79,25 @@ var originalLimit = SpecialPowers.getIntPref("network.http.speculative-parallel-
|
|||
|
||||
function testElement()
|
||||
{
|
||||
// test the link rel=preconnect element in the head
|
||||
// test the link rel=preconnect element in the head for both normal
|
||||
// and crossOrigin=anonymous
|
||||
srv1 = new TestServer1(testHeader);
|
||||
SpecialPowers.setIntPref("network.http.speculative-parallel-limit", 1);
|
||||
SpecialPowers.setIntPref("network.http.speculative-parallel-limit", 2);
|
||||
var link = document.createElement("link");
|
||||
link.rel = "preconnect";
|
||||
link.href = "//localhost:" + srv1.listener.port;
|
||||
document.head.appendChild(link);
|
||||
link = document.createElement("link");
|
||||
link.rel = "preconnect";
|
||||
link.href = "//localhost:" + srv1.listener.port;
|
||||
link.crossOrigin = "anonymous";
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
function testHeader()
|
||||
{
|
||||
// test the http link response header
|
||||
// test the http link response header - the test contains both a
|
||||
// normal and anonymous preconnect link header
|
||||
srv2 = new TestServer2(testDone);
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", 'rel_preconnect.sjs', false);
|
||||
|
|
|
@ -68,7 +68,7 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
|
|||
}
|
||||
break;
|
||||
case eSpeculativeLoadPreconnect:
|
||||
aExecutor->Preconnect(mUrl);
|
||||
aExecutor->Preconnect(mUrl, mCrossOrigin);
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Bogus speculative load.");
|
||||
|
|
|
@ -164,12 +164,14 @@ class nsHtml5SpeculativeLoad {
|
|||
mTypeOrCharsetSource.Assign((char16_t)aCharsetSource);
|
||||
}
|
||||
|
||||
inline void InitPreconnect(const nsAString& aUrl)
|
||||
inline void InitPreconnect(const nsAString& aUrl,
|
||||
const nsAString& aCrossOrigin)
|
||||
{
|
||||
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
|
||||
"Trying to reinitialize a speculative load!");
|
||||
mOpCode = eSpeculativeLoadPreconnect;
|
||||
mUrl.Assign(aUrl);
|
||||
mCrossOrigin.Assign(aCrossOrigin);
|
||||
}
|
||||
|
||||
void Perform(nsHtml5TreeOpExecutor* aExecutor);
|
||||
|
@ -193,9 +195,9 @@ class nsHtml5SpeculativeLoad {
|
|||
*/
|
||||
nsString mTypeOrCharsetSource;
|
||||
/**
|
||||
* If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead],
|
||||
* this is the value of the "crossorigin" attribute. If the
|
||||
* attribute is not set, this will be a void string.
|
||||
* If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
|
||||
* or eSpeculativeLoadPreconnect this is the value of the "crossorigin"
|
||||
* attribute. If the attribute is not set, this will be a void string.
|
||||
*/
|
||||
nsString mCrossOrigin;
|
||||
/**
|
||||
|
|
|
@ -191,8 +191,10 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
|
|||
} else if (rel->LowerCaseEqualsASCII("preconnect")) {
|
||||
nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
|
||||
if (url) {
|
||||
nsString* crossOrigin =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
|
||||
mSpeculativeLoadQueue.AppendElement()->
|
||||
InitPreconnect(*url);
|
||||
InitPreconnect(*url, (crossOrigin) ? *crossOrigin : NullString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче