bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const AtomicString& crossOriginMode, const String& type, const String& as, const KURL& href, Document& document) { // TODO(yoav): Convert all uses of the CrossOriginAttribute to CrossOriginAttributeValue. crbug.com/486689 // FIXME(crbug.com/463266): We're ignoring type here. Maybe we shouldn't. dnsPrefetchIfNeeded(relAttribute, href, document); preconnectIfNeeded(relAttribute, href, document, crossOriginAttributeValue(crossOriginMode)); preloadIfNeeded(relAttribute, href, document, as); // FIXME(crbug.com/323096): Should take care of import. if ((relAttribute.isLinkPrefetch() || relAttribute.isLinkSubresource() || relAttribute.isTransitionExitingStylesheet()) && href.isValid() && document.frame()) { if (!m_client->shouldLoadLink()) return false; Resource::Type type = relAttribute.isLinkSubresource() ? Resource::LinkSubresource : Resource::LinkPrefetch; FetchRequest linkRequest(ResourceRequest(document.completeURL(href)), FetchInitiatorTypeNames::link); if (!crossOriginMode.isNull()) linkRequest.setCrossOriginAccessControl(document.securityOrigin(), crossOriginMode); setResource(document.fetcher()->fetchLinkResource(type, linkRequest)); } if (const unsigned prerenderRelTypes = prerenderRelTypesFromRelAttribute(relAttribute)) { if (!m_prerender) { m_prerender = PrerenderHandle::create(document, this, href, prerenderRelTypes); } else if (m_prerender->url() != href) { m_prerender->cancel(); m_prerender = PrerenderHandle::create(document, this, href, prerenderRelTypes); } // TODO(gavinp): Handle changes to rel types of existing prerenders. } else if (m_prerender) { m_prerender->cancel(); m_prerender.clear(); } return true; }
bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const AtomicString& crossOriginMode, const String& type, const KURL& href, Document& document) { if (relAttribute.isDNSPrefetch()) { Settings* settings = document.settings(); // FIXME: The href attribute of the link element can be in "//hostname" form, and we shouldn't attempt // to complete that as URL <https://bugs.webkit.org/show_bug.cgi?id=48857>. if (settings && settings->dnsPrefetchingEnabled() && href.isValid() && !href.isEmpty()) prefetchDNS(href.host()); } // FIXME(crbug.com/323096): Should take care of import. if ((relAttribute.isLinkPrefetch() || relAttribute.isLinkSubresource()) && href.isValid() && document.frame()) { if (!m_client->shouldLoadLink()) return false; Resource::Type type = relAttribute.isLinkSubresource() ? Resource::LinkSubresource : Resource::LinkPrefetch; FetchRequest linkRequest(ResourceRequest(document.completeURL(href)), FetchInitiatorTypeNames::link); if (!crossOriginMode.isNull()) linkRequest.setCrossOriginAccessControl(document.securityOrigin(), crossOriginMode); setResource(document.fetcher()->fetchLinkResource(type, linkRequest)); } if (const unsigned prerenderRelTypes = prerenderRelTypesFromRelAttribute(relAttribute)) { if (!m_prerender) { m_prerender = PrerenderHandle::create(document, this, href, prerenderRelTypes); } else if (m_prerender->url() != href) { m_prerender->cancel(); m_prerender = PrerenderHandle::create(document, this, href, prerenderRelTypes); } // TODO(gavinp): Handle changes to rel types of existing prerenders. } else if (m_prerender) { m_prerender->cancel(); m_prerender.clear(); } return true; }
static unsigned prerenderRelTypesFromRelAttribute(const LinkRelAttribute& relAttribute) { unsigned result = 0; if (relAttribute.isLinkPrerender()) result |= PrerenderRelTypePrerender; if (relAttribute.isLinkNext()) result |= PrerenderRelTypeNext; return result; }
static unsigned prerenderRelTypesFromRelAttribute(const LinkRelAttribute& relAttribute, Document& document) { unsigned result = 0; if (relAttribute.isLinkPrerender()) { result |= PrerenderRelTypePrerender; UseCounter::count(document, UseCounter::LinkRelPrerender); } if (relAttribute.isLinkNext()) { result |= PrerenderRelTypeNext; UseCounter::count(document, UseCounter::LinkRelNext); } return result; }
static void preconnectIfNeeded( const LinkRelAttribute& relAttribute, const KURL& href, Document& document, const CrossOriginAttributeValue crossOrigin, const NetworkHintsInterface& networkHintsInterface, LinkCaller caller) { if (relAttribute.isPreconnect() && href.isValid() && href.protocolIsInHTTPFamily()) { UseCounter::count(document, UseCounter::LinkRelPreconnect); if (caller == LinkCalledFromHeader) UseCounter::count(document, UseCounter::LinkHeaderPreconnect); Settings* settings = document.settings(); if (settings && settings->logDnsPrefetchAndPreconnect()) { document.addConsoleMessage(ConsoleMessage::create( OtherMessageSource, DebugMessageLevel, String("Preconnect triggered for ") + href.getString())); if (crossOrigin != CrossOriginAttributeNotSet) { document.addConsoleMessage(ConsoleMessage::create( OtherMessageSource, DebugMessageLevel, String("Preconnect CORS setting is ") + String((crossOrigin == CrossOriginAttributeAnonymous) ? "anonymous" : "use-credentials"))); } } networkHintsInterface.preconnectHost(href, crossOrigin); } }
static void dnsPrefetchIfNeeded( const LinkRelAttribute& relAttribute, const KURL& href, Document& document, const NetworkHintsInterface& networkHintsInterface, LinkCaller caller) { if (relAttribute.isDNSPrefetch()) { UseCounter::count(document, UseCounter::LinkRelDnsPrefetch); if (caller == LinkCalledFromHeader) UseCounter::count(document, UseCounter::LinkHeaderDnsPrefetch); Settings* settings = document.settings(); // FIXME: The href attribute of the link element can be in "//hostname" // form, and we shouldn't attempt to complete that as URL // <https://bugs.webkit.org/show_bug.cgi?id=48857>. if (settings && settings->dnsPrefetchingEnabled() && href.isValid() && !href.isEmpty()) { if (settings->logDnsPrefetchAndPreconnect()) { document.addConsoleMessage(ConsoleMessage::create( OtherMessageSource, DebugMessageLevel, String("DNS prefetch triggered for " + href.host()))); } networkHintsInterface.dnsPrefetchHost(href.host()); } } }
static void preconnectIfNeeded(const LinkRelAttribute& relAttribute, const KURL& href, Document& document) { if (relAttribute.isPreconnect() && href.isValid()) { ASSERT(RuntimeEnabledFeatures::linkPreconnectEnabled()); if (document.settings()->logDnsPrefetchAndPreconnect()) document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, DebugMessageLevel, String("Preconnect triggered for " + href.host()))); preconnect(href); } }
static void dnsPrefetchIfNeeded(const LinkRelAttribute& relAttribute, const KURL& href, Document& document) { if (relAttribute.isDNSPrefetch()) { Settings* settings = document.settings(); // FIXME: The href attribute of the link element can be in "//hostname" form, and we shouldn't attempt // to complete that as URL <https://bugs.webkit.org/show_bug.cgi?id=48857>. if (settings && settings->dnsPrefetchingEnabled() && href.isValid() && !href.isEmpty()) { if (settings->logDnsPrefetchAndPreconnect()) document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, DebugMessageLevel, String("DNS prefetch triggered for " + href.host()))); prefetchDNS(href.host()); } } }
static void preconnectIfNeeded(const LinkRelAttribute& relAttribute, const KURL& href, Document& document, const CrossOriginAttributeValue crossOrigin) { if (relAttribute.isPreconnect() && href.isValid()) { ASSERT(RuntimeEnabledFeatures::linkPreconnectEnabled()); Settings* settings = document.settings(); if (settings && settings->logDnsPrefetchAndPreconnect()) { document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, DebugMessageLevel, String("Preconnect triggered for " + href.host()))); if (crossOrigin != CrossOriginAttributeNotSet) { document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, DebugMessageLevel, String("Preconnect CORS setting is ") + String((crossOrigin == CrossOriginAttributeAnonymous) ? "anonymous" : "use-credentials"))); } } preconnect(href, crossOrigin); } }
bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, CrossOriginAttributeValue crossOrigin, const String& type, const String& as, const String& media, const KURL& href, Document& document, const NetworkHintsInterface& networkHintsInterface) { // TODO(yoav): Do all links need to load only after they're in document??? // TODO(yoav): Convert all uses of the CrossOriginAttribute to CrossOriginAttributeValue. crbug.com/486689 // FIXME(crbug.com/463266): We're ignoring type here, for everything but preload. Maybe we shouldn't. dnsPrefetchIfNeeded(relAttribute, href, document, networkHintsInterface, LinkCalledFromMarkup); preconnectIfNeeded(relAttribute, href, document, crossOrigin, networkHintsInterface, LinkCalledFromMarkup); bool errorOccurred = false; if (m_client->shouldLoadLink()) createLinkPreloadResourceClient(preloadIfNeeded(relAttribute, href, document, as, type, media, crossOrigin, LinkCalledFromMarkup, errorOccurred, nullptr)); if (errorOccurred) m_linkLoadingErrorTimer.startOneShot(0, BLINK_FROM_HERE); if (href.isEmpty() || !href.isValid()) released(); // FIXME(crbug.com/323096): Should take care of import. if (relAttribute.isLinkPrefetch() && href.isValid() && document.frame()) { if (!m_client->shouldLoadLink()) return false; UseCounter::count(document, UseCounter::LinkRelPrefetch); FetchRequest linkRequest(ResourceRequest(document.completeURL(href)), FetchInitiatorTypeNames::link); if (crossOrigin != CrossOriginAttributeNotSet) linkRequest.setCrossOriginAccessControl(document.getSecurityOrigin(), crossOrigin); setResource(LinkFetchResource::fetch(Resource::LinkPrefetch, linkRequest, document.fetcher())); } if (const unsigned prerenderRelTypes = prerenderRelTypesFromRelAttribute(relAttribute, document)) { if (!m_prerender) { m_prerender = PrerenderHandle::create(document, this, href, prerenderRelTypes); } else if (m_prerender->url() != href) { m_prerender->cancel(); m_prerender = PrerenderHandle::create(document, this, href, prerenderRelTypes); } // TODO(gavinp): Handle changes to rel types of existing prerenders. } else if (m_prerender) { m_prerender->cancel(); m_prerender.clear(); } return true; }
void LinkLoader::preloadIfNeeded(const LinkRelAttribute& relAttribute, const KURL& href, Document& document, const String& as) { if (relAttribute.isLinkPreload()) { ASSERT(RuntimeEnabledFeatures::linkPreloadEnabled()); if (!href.isValid() || href.isEmpty()) { document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, WarningMessageLevel, String("<link rel=preload> has an invalid `href` value"))); return; } Resource::Type type; if (!getTypeFromAsAttribute(as, type)) { document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, WarningMessageLevel, String("<link rel=preload> must have a valid `as` value"))); return; } FetchRequest linkRequest(ResourceRequest(document.completeURL(href)), FetchInitiatorTypeNames::link); Settings* settings = document.settings(); if (settings && settings->logPreload()) document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, DebugMessageLevel, String("Preload triggered for " + href.host() + href.path()))); setResource(document.fetcher()->fetchLinkPreloadResource(type, linkRequest)); } }
void LinkLoader::prefetchIfNeeded(Document& document, const KURL& href, const LinkRelAttribute& relAttribute, CrossOriginAttributeValue crossOrigin, ReferrerPolicy referrerPolicy) { if (relAttribute.isLinkPrefetch() && href.isValid() && document.frame()) { UseCounter::count(document, UseCounter::LinkRelPrefetch); FetchRequest linkRequest(ResourceRequest(document.completeURL(href)), FetchInitiatorTypeNames::link); if (referrerPolicy != ReferrerPolicyDefault) { linkRequest.mutableResourceRequest().setHTTPReferrer( SecurityPolicy::generateReferrer(referrerPolicy, href, document.outgoingReferrer())); } if (crossOrigin != CrossOriginAttributeNotSet) { linkRequest.setCrossOriginAccessControl(document.getSecurityOrigin(), crossOrigin); } setResource(LinkFetchResource::fetch(Resource::LinkPrefetch, linkRequest, document.fetcher())); } }