Beispiel #1
0
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;
}
Beispiel #3
0
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;
}
Beispiel #5
0
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);
  }
}
Beispiel #6
0
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());
    }
  }
}
Beispiel #7
0
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);
    }
}
Beispiel #8
0
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());
        }
    }
}
Beispiel #9
0
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;
}
Beispiel #11
0
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));
    }
}
Beispiel #12
0
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()));
  }
}