summaryrefslogtreecommitdiff
path: root/Source/WebCore/loader/LinkLoader.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/loader/LinkLoader.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/loader/LinkLoader.cpp')
-rw-r--r--Source/WebCore/loader/LinkLoader.cpp202
1 files changed, 155 insertions, 47 deletions
diff --git a/Source/WebCore/loader/LinkLoader.cpp b/Source/WebCore/loader/LinkLoader.cpp
index e63bbf0c2..9b53ce87d 100644
--- a/Source/WebCore/loader/LinkLoader.cpp
+++ b/Source/WebCore/loader/LinkLoader.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -37,101 +38,208 @@
#include "CachedResourceLoader.h"
#include "CachedResourceRequest.h"
#include "ContainerNode.h"
-#include "DNS.h"
+#include "CrossOriginAccessControl.h"
#include "Document.h"
#include "Frame.h"
+#include "FrameLoaderClient.h"
#include "FrameView.h"
+#include "LinkHeader.h"
+#include "LinkPreloadResourceClients.h"
#include "LinkRelAttribute.h"
+#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
#include "StyleResolver.h"
namespace WebCore {
-LinkLoader::LinkLoader(LinkLoaderClient* client)
+LinkLoader::LinkLoader(LinkLoaderClient& client)
: m_client(client)
- , m_linkLoadTimer(this, &LinkLoader::linkLoadTimerFired)
- , m_linkLoadingErrorTimer(this, &LinkLoader::linkLoadingErrorTimerFired)
+ , m_weakPtrFactory(this)
{
}
LinkLoader::~LinkLoader()
{
if (m_cachedLinkResource)
- m_cachedLinkResource->removeClient(this);
+ m_cachedLinkResource->removeClient(*this);
+ if (m_preloadResourceClient)
+ m_preloadResourceClient->clear();
}
-void LinkLoader::linkLoadTimerFired(Timer<LinkLoader>& timer)
+void LinkLoader::triggerEvents(const CachedResource& resource)
{
- ASSERT_UNUSED(timer, &timer == &m_linkLoadTimer);
- m_client->linkLoaded();
+ if (resource.errorOccurred())
+ m_client.linkLoadingErrored();
+ else
+ m_client.linkLoaded();
}
-void LinkLoader::linkLoadingErrorTimerFired(Timer<LinkLoader>& timer)
+void LinkLoader::notifyFinished(CachedResource& resource)
{
- ASSERT_UNUSED(timer, &timer == &m_linkLoadingErrorTimer);
- m_client->linkLoadingErrored();
+ ASSERT_UNUSED(resource, m_cachedLinkResource.get() == &resource);
+
+ triggerEvents(*m_cachedLinkResource);
+
+ m_cachedLinkResource->removeClient(*this);
+ m_cachedLinkResource = nullptr;
}
-void LinkLoader::notifyFinished(CachedResource* resource)
+void LinkLoader::loadLinksFromHeader(const String& headerValue, const URL& baseURL, Document& document)
{
- ASSERT_UNUSED(resource, m_cachedLinkResource.get() == resource);
+ if (headerValue.isEmpty())
+ return;
+ LinkHeaderSet headerSet(headerValue);
+ for (auto& header : headerSet) {
+ if (!header.valid() || header.url().isEmpty() || header.rel().isEmpty())
+ continue;
+
+ LinkRelAttribute relAttribute(header.rel());
+ URL url(baseURL, header.url());
+ // Sanity check to avoid re-entrancy here.
+ if (equalIgnoringFragmentIdentifier(url, baseURL))
+ continue;
+ preloadIfNeeded(relAttribute, url, document, header.as(), header.crossOrigin(), nullptr, nullptr);
+ }
+}
- if (m_cachedLinkResource->errorOccurred())
- m_linkLoadingErrorTimer.startOneShot(0);
- else
- m_linkLoadTimer.startOneShot(0);
+std::optional<CachedResource::Type> LinkLoader::resourceTypeFromAsAttribute(const String& as)
+{
+ if (as.isEmpty())
+ return CachedResource::RawResource;
+ if (equalLettersIgnoringASCIICase(as, "image"))
+ return CachedResource::ImageResource;
+ if (equalLettersIgnoringASCIICase(as, "script"))
+ return CachedResource::Script;
+ if (equalLettersIgnoringASCIICase(as, "style"))
+ return CachedResource::CSSStyleSheet;
+ if (equalLettersIgnoringASCIICase(as, "media"))
+ return CachedResource::MediaResource;
+ if (equalLettersIgnoringASCIICase(as, "font"))
+ return CachedResource::FontResource;
+#if ENABLE(VIDEO_TRACK)
+ if (equalLettersIgnoringASCIICase(as, "track"))
+ return CachedResource::TextTrackResource;
+#endif
+ return std::nullopt;
+}
- m_cachedLinkResource->removeClient(this);
- m_cachedLinkResource = 0;
+static std::unique_ptr<LinkPreloadResourceClient> createLinkPreloadResourceClient(CachedResource& resource, LinkLoader& loader, CachedResource::Type type)
+{
+ switch (type) {
+ case CachedResource::ImageResource:
+ return LinkPreloadImageResourceClient::create(loader, static_cast<CachedImage&>(resource));
+ case CachedResource::Script:
+ return LinkPreloadScriptResourceClient::create(loader, static_cast<CachedScript&>(resource));
+ case CachedResource::CSSStyleSheet:
+ return LinkPreloadStyleResourceClient::create(loader, static_cast<CachedCSSStyleSheet&>(resource));
+ case CachedResource::FontResource:
+ return LinkPreloadFontResourceClient::create(loader, static_cast<CachedFont&>(resource));
+ case CachedResource::MediaResource:
+#if ENABLE(VIDEO_TRACK)
+ case CachedResource::TextTrackResource:
+#endif
+ case CachedResource::RawResource:
+ return LinkPreloadRawResourceClient::create(loader, static_cast<CachedRawResource&>(resource));
+ case CachedResource::MainResource:
+#if ENABLE(SVG_FONTS)
+ case CachedResource::SVGFontResource:
+#endif
+ case CachedResource::SVGDocumentResource:
+#if ENABLE(XSLT)
+ case CachedResource::XSLStyleSheet:
+#endif
+#if ENABLE(LINK_PREFETCH)
+ case CachedResource::LinkSubresource:
+ case CachedResource::LinkPrefetch:
+#endif
+ // None of these values is currently supported as an `as` value.
+ ASSERT_NOT_REACHED();
+ }
+ return nullptr;
}
-bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const String& type,
- const String& sizes, const URL& href, Document* document)
+std::unique_ptr<LinkPreloadResourceClient> LinkLoader::preloadIfNeeded(const LinkRelAttribute& relAttribute, const URL& href, Document& document, const String& as, const String& crossOriginMode, LinkLoader* loader, LinkLoaderClient* client)
{
- // We'll record this URL per document, even if we later only use it in top level frames
- if (relAttribute.m_iconType != InvalidIcon && href.isValid() && !href.isEmpty()) {
- if (!m_client->shouldLoadLink())
- return false;
- document->addIconURL(href.string(), type, sizes, relAttribute.m_iconType);
+ if (!document.loader() || !relAttribute.isLinkPreload)
+ return nullptr;
+
+ ASSERT(RuntimeEnabledFeatures::sharedFeatures().linkPreloadEnabled());
+ if (!href.isValid()) {
+ document.addConsoleMessage(MessageSource::Other, MessageLevel::Error, String("<link rel=preload> has an invalid `href` value"));
+ return nullptr;
}
+ auto type = LinkLoader::resourceTypeFromAsAttribute(as);
+ if (!type) {
+ document.addConsoleMessage(MessageSource::Other, MessageLevel::Error, String("<link rel=preload> must have a valid `as` value"));
+ if (client)
+ client->linkLoadingErrored();
+ return nullptr;
+ }
+
+ ResourceRequest resourceRequest(document.completeURL(href));
+ resourceRequest.setIgnoreForRequestCount(true);
+ CachedResourceRequest linkRequest(WTFMove(resourceRequest), CachedResourceLoader::defaultCachedResourceOptions(), CachedResource::defaultPriorityForResourceType(type.value()));
+ linkRequest.setInitiator("link");
+ linkRequest.setIsLinkPreload();
+
+ linkRequest.setAsPotentiallyCrossOrigin(crossOriginMode, document);
+ CachedResourceHandle<CachedResource> cachedLinkResource = document.cachedResourceLoader().preload(type.value(), WTFMove(linkRequest));
+
+ if (cachedLinkResource && loader)
+ return createLinkPreloadResourceClient(*cachedLinkResource, *loader, type.value());
+ return nullptr;
+}
+
+void LinkLoader::cancelLoad()
+{
+ if (m_preloadResourceClient)
+ m_preloadResourceClient->clear();
+}
- if (relAttribute.m_isDNSPrefetch) {
- Settings* settings = document->settings();
+bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const URL& href, const String& as, const String& crossOrigin, Document& document)
+{
+ if (relAttribute.isDNSPrefetch) {
// 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());
+ if (document.settings().dnsPrefetchingEnabled() && href.isValid() && !href.isEmpty() && document.frame())
+ document.frame()->loader().client().prefetchDNS(href.host());
+ }
+
+ if (m_client.shouldLoadLink()) {
+ auto resourceClient = preloadIfNeeded(relAttribute, href, document, as, crossOrigin, this, &m_client);
+ if (resourceClient)
+ m_preloadResourceClient = WTFMove(resourceClient);
+ else if (m_preloadResourceClient)
+ m_preloadResourceClient->clear();
}
#if ENABLE(LINK_PREFETCH)
- if ((relAttribute.m_isLinkPrefetch || relAttribute.m_isLinkSubresource) && href.isValid() && document->frame()) {
- if (!m_client->shouldLoadLink())
+ if ((relAttribute.isLinkPrefetch || relAttribute.isLinkSubresource) && href.isValid() && document.frame()) {
+ if (!m_client.shouldLoadLink())
return false;
- ResourceLoadPriority priority = ResourceLoadPriorityUnresolved;
+
+ std::optional<ResourceLoadPriority> priority;
CachedResource::Type type = CachedResource::LinkPrefetch;
- // We only make one request to the cachedresourcelodaer if multiple rel types are
- // specified,
- if (relAttribute.m_isLinkSubresource) {
- priority = ResourceLoadPriorityLow;
+ if (relAttribute.isLinkSubresource) {
+ // We only make one request to the cached resource loader if multiple rel types are specified;
+ // this is the higher priority, which should overwrite the lower priority.
+ priority = ResourceLoadPriority::Low;
type = CachedResource::LinkSubresource;
}
- CachedResourceRequest linkRequest(ResourceRequest(document->completeURL(href)), priority);
-
+
if (m_cachedLinkResource) {
- m_cachedLinkResource->removeClient(this);
- m_cachedLinkResource = 0;
+ m_cachedLinkResource->removeClient(*this);
+ m_cachedLinkResource = nullptr;
}
- m_cachedLinkResource = document->cachedResourceLoader()->requestLinkResource(type, linkRequest);
+ ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
+ options.contentSecurityPolicyImposition = ContentSecurityPolicyImposition::SkipPolicyCheck;
+ m_cachedLinkResource = document.cachedResourceLoader().requestLinkResource(type, CachedResourceRequest(ResourceRequest(document.completeURL(href)), options, priority));
if (m_cachedLinkResource)
- m_cachedLinkResource->addClient(this);
+ m_cachedLinkResource->addClient(*this);
}
#endif
return true;
}
-void LinkLoader::released()
-{
-}
-
}