Diff
Modified: trunk/LayoutTests/ChangeLog (244247 => 244248)
--- trunk/LayoutTests/ChangeLog 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/LayoutTests/ChangeLog 2019-04-14 20:52:46 UTC (rev 244248)
@@ -1,3 +1,23 @@
+2019-04-14 Rob Buis <[email protected]>
+
+ Link prefetch not useful for top-level navigation
+ https://bugs.webkit.org/show_bug.cgi?id=195623
+
+ Reviewed by Youenn Fablet.
+
+ Verify that prefetching a cross-domain top-level main resource
+ is cached in the prefetch cache and only loaded once, and that non
+ top-level prefetches keep the old behavior.
+
+ * http/tests/cache/link-prefetch-main-resource-expected.txt: Added.
+ * http/tests/cache/link-prefetch-main-resource-iframe-expected.txt: Added.
+ * http/tests/cache/link-prefetch-main-resource-iframe.html: Added.
+ * http/tests/cache/link-prefetch-main-resource.html: Added.
+ * http/tests/cache/resources/prefetched-main-resource-iframe.php: Added.
+ * http/tests/cache/resources/prefetched-main-resource.php: Added.
+ * platform/mac-wk1/TestExpectations:
+ * platform/win/TestExpectations:
+
2019-04-12 Ross Kirsling <[email protected]>
[WinCairo][WKL] Unreviewed test gardening.
Added: trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-expected.txt (0 => 244248)
--- trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-expected.txt 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1 @@
+PASS
Added: trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-iframe-expected.txt (0 => 244248)
--- trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-iframe-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-iframe-expected.txt 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1,2 @@
+PASS
+
Added: trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-iframe.html (0 => 244248)
--- trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-iframe.html (rev 0)
+++ trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource-iframe.html 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1,38 @@
+<html>
+<body>
+<div id="result"></div>
+<script>
+
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+
+function done()
+{
+ testRunner.notifyDone();
+}
+
+function iframeLoadFinished()
+{
+ if (window.testRunner)
+ setTimeout(done, 0);
+}
+
+function loadAfterPrefetch()
+{
+ var newIframe = document.createElement("iframe");
+ newIframe.src = ""
+ newIframe._onload_ = iframeLoadFinished;
+ document.body.appendChild(newIframe);
+}
+
+window._onmessage_ = function(message)
+{
+ document.getElementById('result').textContent = message.data;
+}
+
+</script>
+<link rel="prefetch" href="" _onload_="setTimeout(loadAfterPrefetch, 0);">
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource.html (0 => 244248)
--- trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource.html (rev 0)
+++ trunk/LayoutTests/http/tests/cache/link-prefetch-main-resource.html 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1,16 @@
+<html>
+<script>
+if (window.testRunner) {
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+}
+
+function loadAfterPrefetch()
+{
+ window.location.assign('http://localhost:8000/cache/resources/prefetched-main-resource.php');
+}
+</script>
+<body>
+<link rel="prefetch" href="" _onload_="loadAfterPrefetch();">
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource-iframe.php (0 => 244248)
--- trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource-iframe.php (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource-iframe.php 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1,18 @@
+<?php
+if ($_SERVER["HTTP_PURPOSE"] == "prefetch") {
+ header('Cache-Control: max-age=3600');
+ header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
+
+ echo "<script>";
+ echo "parent.window.postMessage('FAIL', '*');";
+ echo "</script>";
+
+ exit();
+}
+
+header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
+
+echo "<script>";
+echo "parent.window.postMessage('PASS', '*');";
+echo "</script>";
+?>
Added: trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource.php (0 => 244248)
--- trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource.php (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource.php 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1,21 @@
+<?php
+header('Cache-Control: max-age=3600');
+?>
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+
+if (window.testRunner)
+ testRunner.notifyDone();
+
+</script>
+<?php
+if ($_SERVER["HTTP_PURPOSE"] == "prefetch") {
+ print('PASS');
+} else {
+ print('FAIL');
+}
+?>
+</body>
+</html>
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (244247 => 244248)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-04-14 20:52:46 UTC (rev 244248)
@@ -707,3 +707,6 @@
webkit.org/b/196448 [ Debug ] inspector/audit/basic.html [ Pass Timeout ]
webkit.org/b/196502 media/video-background-tab-playback.html [ Pass Failure ]
+
+webkit.org/b/195623 http/tests/cache/link-prefetch-main-resource.html [ Skip ]
+webkit.org/b/195623 http/tests/cache/link-prefetch-main-resource-iframe.html [ Skip ]
Modified: trunk/LayoutTests/platform/win/TestExpectations (244247 => 244248)
--- trunk/LayoutTests/platform/win/TestExpectations 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/LayoutTests/platform/win/TestExpectations 2019-04-14 20:52:46 UTC (rev 244248)
@@ -4330,3 +4330,6 @@
webkit.org/b/196869 animations/animation-multiple-callbacks-timestamp.html [ Failure ]
webkit.org/b/196869 legacy-animation-engine/animations/animation-multiple-callbacks-timestamp.html [ Failure ]
webkit.org/b/196869 imported/mozilla/css-animations/test_animation-currenttime.html [ Failure ]
+
+webkit.org/b/195623 http/tests/cache/link-prefetch-main-resource.html [ Skip ]
+webkit.org/b/195623 http/tests/cache/link-prefetch-main-resource-iframe.html [ Skip ]
Modified: trunk/Source/WebCore/ChangeLog (244247 => 244248)
--- trunk/Source/WebCore/ChangeLog 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebCore/ChangeLog 2019-04-14 20:52:46 UTC (rev 244248)
@@ -1,3 +1,26 @@
+2019-04-14 Rob Buis <[email protected]>
+
+ Link prefetch not useful for top-level navigation
+ https://bugs.webkit.org/show_bug.cgi?id=195623
+
+ Reviewed by Youenn Fablet.
+
+ Cache cross-domain top-level prefetches in a dedicated cache and not in the
+ memory cache. Ignore prefetches for content extension checks.
+
+ Tests: http/tests/cache/link-prefetch-main-resource-iframe.html
+ http/tests/cache/link-prefetch-main-resource.html
+
+ * loader/LinkLoader.cpp:
+ (WebCore::LinkLoader::prefetchIfNeeded):
+ * loader/ResourceLoadInfo.cpp:
+ (WebCore::toResourceType):
+ * loader/ResourceLoadInfo.h:
+ * loader/ResourceLoader.cpp:
+ (WebCore::ResourceLoader::willSendRequestInternal):
+ * loader/cache/CachedResourceLoader.cpp:
+ (WebCore::CachedResourceLoader::requestResource):
+
2019-04-14 Dean Jackson <[email protected]>
Extract UTI mapping and allow for additions
Modified: trunk/Source/WebCore/loader/LinkLoader.cpp (244247 => 244248)
--- trunk/Source/WebCore/loader/LinkLoader.cpp 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebCore/loader/LinkLoader.cpp 2019-04-14 20:52:46 UTC (rev 244248)
@@ -276,8 +276,17 @@
m_cachedLinkResource->removeClient(*this);
m_cachedLinkResource = nullptr;
}
+ // FIXME: Add further prefetch restrictions/limitations:
+ // - third-party iframes cannot trigger prefetches
+ // - Number of prefetches of a given page is limited (to 1 maybe?)
ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
options.contentSecurityPolicyImposition = ContentSecurityPolicyImposition::SkipPolicyCheck;
+ options.certificateInfoPolicy = CertificateInfoPolicy::IncludeCertificateInfo;
+ options.credentials = FetchOptions::Credentials::SameOrigin;
+ options.redirect = FetchOptions::Redirect::Manual;
+ options.mode = FetchOptions::Mode::Navigate;
+ options.serviceWorkersMode = ServiceWorkersMode::None;
+ options.cachingPolicy = CachingPolicy::DisallowCaching;
m_cachedLinkResource = document.cachedResourceLoader().requestLinkResource(type, CachedResourceRequest(ResourceRequest(document.completeURL(href)), options, priority)).value_or(nullptr);
if (m_cachedLinkResource)
m_cachedLinkResource->addClient(*this);
Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.cpp (244247 => 244248)
--- trunk/Source/WebCore/loader/ResourceLoadInfo.cpp 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.cpp 2019-04-14 20:52:46 UTC (rev 244248)
@@ -68,8 +68,7 @@
return ResourceType::Media;
#endif
case CachedResource::Type::LinkPrefetch:
- ASSERT_NOT_REACHED();
- break;
+ return ResourceType::Prefetch;
#if ENABLE(APPLICATION_MANIFEST)
case CachedResource::Type::ApplicationManifest:
return ResourceType::Raw;
Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.h (244247 => 244248)
--- trunk/Source/WebCore/loader/ResourceLoadInfo.h 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.h 2019-04-14 20:52:46 UTC (rev 244248)
@@ -42,8 +42,9 @@
Media = 0x0080,
PlugInStream = 0x0100,
Popup = 0x0200,
+ Prefetch = 0x0400,
};
-const uint16_t ResourceTypeMask = 0x03FF;
+const uint16_t ResourceTypeMask = 0x07FF;
enum class LoadType : uint16_t {
Invalid = 0x0000,
Modified: trunk/Source/WebCore/loader/ResourceLoader.cpp (244247 => 244248)
--- trunk/Source/WebCore/loader/ResourceLoader.cpp 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebCore/loader/ResourceLoader.cpp 2019-04-14 20:52:46 UTC (rev 244248)
@@ -342,7 +342,7 @@
ASSERT(!m_reachedTerminalState);
#if ENABLE(CONTENT_EXTENSIONS)
- ASSERT(m_resourceType != ResourceType::Invalid);
+ ASSERT(m_resourceType != ResourceType::Invalid || m_resourceType == ResourceType::Prefetch);
#endif
// We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests).
@@ -353,7 +353,7 @@
}
#if ENABLE(CONTENT_EXTENSIONS)
- if (!redirectResponse.isNull() && frameLoader()) {
+ if (!redirectResponse.isNull() && frameLoader() && m_resourceType != ResourceType::Prefetch) {
Page* page = frameLoader()->frame().page();
if (page && m_documentLoader) {
auto results = page->userContentProvider().processContentRuleListsForLoad(request.url(), m_resourceType, *m_documentLoader);
Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (244247 => 244248)
--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp 2019-04-14 20:52:46 UTC (rev 244248)
@@ -806,7 +806,7 @@
}
#if ENABLE(CONTENT_EXTENSIONS)
- if (frame() && frame()->page() && m_documentLoader) {
+ if (frame() && frame()->page() && m_documentLoader && type != CachedResource::Type::LinkPrefetch) {
const auto& resourceRequest = request.resourceRequest();
auto* page = frame()->page();
auto results = page->userContentProvider().processContentRuleListsForLoad(resourceRequest.url(), toResourceType(type), *m_documentLoader);
Modified: trunk/Source/WebKit/ChangeLog (244247 => 244248)
--- trunk/Source/WebKit/ChangeLog 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/ChangeLog 2019-04-14 20:52:46 UTC (rev 244248)
@@ -1,3 +1,43 @@
+2019-04-14 Rob Buis <[email protected]>
+
+ Link prefetch not useful for top-level navigation
+ https://bugs.webkit.org/show_bug.cgi?id=195623
+
+ Reviewed by Youenn Fablet.
+
+ Cache cross-domain top-level prefetches in a dedicated cache. When a navigation
+ to the same url is done within a threshold (5 seconds), reuse the
+ prefetch cache entry, move it to the disk cache and navigate to
+ the url, meaning no extra network trip is needed. When not used within
+ the threshold period, the prefetch entry will be erased using a timer.
+
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::lowMemoryHandler):
+ * NetworkProcess/NetworkProcess.h:
+ (WebKit::NetworkProcess::prefetchCache):
+ * NetworkProcess/NetworkResourceLoader.cpp:
+ (WebKit::NetworkResourceLoader::retrieveCacheEntry):
+ (WebKit::NetworkResourceLoader::didReceiveResponse):
+ (WebKit::NetworkResourceLoader::didReceiveBuffer):
+ (WebKit::NetworkResourceLoader::tryStoreAsCacheEntry):
+ (WebKit::NetworkResourceLoader::isCrossOriginPrefetch const):
+ * NetworkProcess/NetworkResourceLoader.h:
+ * NetworkProcess/cache/PrefetchCache.cpp: Added.
+ (WebKit::PrefetchCache::Entry::Entry):
+ (WebKit::PrefetchCache::PrefetchCache):
+ (WebKit::PrefetchCache::~PrefetchCache):
+ (WebKit::PrefetchCache::clear):
+ (WebKit::PrefetchCache::take):
+ (WebKit::PrefetchCache::store):
+ (WebKit::PrefetchCache::sessionPrefetchMap const):
+ (WebKit::PrefetchCache::clearExpiredEntries):
+ * NetworkProcess/cache/PrefetchCache.h: Added.
+ (WebKit::PrefetchCache::Entry::response const):
+ (WebKit::PrefetchCache::Entry::releaseBuffer):
+ * Shared/WebPreferences.yaml:
+ * Sources.txt:
+ * WebKit.xcodeproj/project.pbxproj:
+
2019-04-14 Andy Estes <[email protected]>
[Cocoa] WKCustomProtocolLoader should store a WeakPtr to its LegacyCustomProtocolManagerProxy
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (244247 => 244248)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-04-14 20:52:46 UTC (rev 244248)
@@ -270,6 +270,8 @@
return;
WTF::releaseFastMallocFreeMemory();
+
+ m_prefetchCache.clear();
}
void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (244247 => 244248)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-04-14 20:52:46 UTC (rev 244248)
@@ -31,6 +31,7 @@
#include "NetworkBlobRegistry.h"
#include "NetworkContentRuleListManager.h"
#include "NetworkHTTPSUpgradeChecker.h"
+#include "PrefetchCache.h"
#include "SandboxExtension.h"
#include "WebResourceLoadStatisticsStore.h"
#include "WebsiteData.h"
@@ -330,6 +331,8 @@
WebCore::StorageQuotaManager& storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
+ PrefetchCache& prefetchCache() { return m_prefetchCache; }
+
private:
void platformInitializeNetworkProcess(const NetworkProcessCreationParameters&);
std::unique_ptr<WebCore::NetworkStorageSession> platformCreateDefaultStorageSession() const;
@@ -551,6 +554,8 @@
};
HashMap<PAL::SessionID, StorageQuotaManagers> m_storageQuotaManagers;
uint32_t m_downloadMonitorSpeedMultiplier { 1 };
+
+ PrefetchCache m_prefetchCache;
};
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (244247 => 244248)
--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp 2019-04-14 20:52:46 UTC (rev 244248)
@@ -212,6 +212,10 @@
ASSERT(canUseCache(request));
RefPtr<NetworkResourceLoader> loader(this);
+ if (isMainFrameLoad() && m_parameters.options.mode == FetchOptions::Mode::Navigate) {
+ if (auto entry = m_connection->networkProcess().prefetchCache().take(sessionID(), request.url()))
+ m_cache->store(request, entry->response, entry->releaseBuffer(), nullptr);
+ }
m_cache->retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [this, loader = WTFMove(loader), request = ResourceRequest { request }](auto entry, auto info) mutable {
if (loader->hasOneRef()) {
// The loader has been aborted and is only held alive by this lambda.
@@ -461,6 +465,10 @@
return completionHandler(PolicyAction::Use);
}
+ if (isCrossOriginPrefetch(originalRequest())) {
+ send(Messages::WebResourceLoader::DidReceiveResponse { ResourceResponse { }, false });
+ return completionHandler(PolicyAction::Use);
+ }
// We wait to receive message NetworkResourceLoader::ContinueDidReceiveResponse before continuing a load for
// a main resource because the embedding client must decide whether to allow the load.
bool willWaitForContinueDidReceiveResponse = isMainResource();
@@ -487,6 +495,8 @@
else
m_bufferedDataForCache = nullptr;
}
+ if (isCrossOriginPrefetch(originalRequest()))
+ return;
// FIXME: At least on OS X Yosemite we always get -1 from the resource handle.
unsigned encodedDataLength = reportedEncodedDataLength >= 0 ? reportedEncodedDataLength : buffer->size();
@@ -769,6 +779,10 @@
if (!m_bufferedDataForCache)
return;
+ if (isCrossOriginPrefetch(originalRequest())) {
+ m_connection->networkProcess().prefetchCache().store(sessionID(), m_networkLoad->currentRequest().url(), WTFMove(m_response), WTFMove(m_bufferedDataForCache));
+ return;
+ }
m_cache->store(m_networkLoad->currentRequest(), m_response, WTFMove(m_bufferedDataForCache), [loader = makeRef(*this)](auto& mappedBody) mutable {
#if ENABLE(SHAREABLE_RESOURCE)
if (mappedBody.shareableResourceHandle.isNull())
@@ -1099,6 +1113,11 @@
#endif
}
+bool NetworkResourceLoader::isCrossOriginPrefetch(const ResourceRequest& request) const
+{
+ return request.httpHeaderField(HTTPHeaderName::Purpose) == "prefetch" && !m_parameters.sourceOrigin->canRequest(request.url());
+}
+
} // namespace WebKit
#undef RELEASE_LOG_IF_ALLOWED
Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h (244247 => 244248)
--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h 2019-04-14 20:52:46 UTC (rev 244248)
@@ -103,6 +103,7 @@
bool isMainResource() const { return m_parameters.request.requester() == WebCore::ResourceRequest::Requester::Main; }
bool isMainFrameLoad() const { return isMainResource() && m_parameters.frameAncestorOrigins.isEmpty(); }
+ bool isCrossOriginPrefetch(const WebCore::ResourceRequest&) const;
bool isAlwaysOnLoggingAllowed() const;
Added: trunk/Source/WebKit/NetworkProcess/cache/PrefetchCache.cpp (0 => 244248)
--- trunk/Source/WebKit/NetworkProcess/cache/PrefetchCache.cpp (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/cache/PrefetchCache.cpp 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PrefetchCache.h"
+
+#include <WebCore/HTTPHeaderNames.h>
+#include <wtf/NeverDestroyed.h>
+
+namespace WebKit {
+
+PrefetchCache::Entry::Entry(WebCore::ResourceResponse&& response, RefPtr<WebCore::SharedBuffer>&& buffer)
+ : response(WTFMove(response)), buffer(WTFMove(buffer))
+{
+}
+
+PrefetchCache::PrefetchCache()
+ : m_expirationTimer(*this, &PrefetchCache::clearExpiredEntries)
+{
+}
+
+PrefetchCache::~PrefetchCache()
+{
+}
+
+void PrefetchCache::clear()
+{
+ m_expirationTimer.stop();
+ m_sessionExpirationList.clear();
+ m_sessionPrefetches.clear();
+}
+
+std::unique_ptr<PrefetchCache::Entry> PrefetchCache::take(PAL::SessionID sessionID, const URL& url)
+{
+ auto* resources = sessionPrefetchMap(sessionID);
+ if (!resources)
+ return nullptr;
+ return resources->take(url);
+}
+
+static const Seconds expirationTimeout { 5_s };
+
+void PrefetchCache::store(PAL::SessionID sessionID, const URL& requestUrl, WebCore::ResourceResponse&& response, RefPtr<WebCore::SharedBuffer>&& buffer)
+{
+ ASSERT(sessionID.isValid());
+ m_sessionPrefetches.ensure(sessionID, [&] {
+ return std::make_unique<PrefetchEntriesMap>();
+ }).iterator->value->set(requestUrl, std::make_unique<PrefetchCache::Entry>(WTFMove(response), WTFMove(buffer)));
+ m_sessionExpirationList.append(std::make_tuple(sessionID, requestUrl, WallTime::now()));
+ if (!m_expirationTimer.isActive())
+ m_expirationTimer.startOneShot(expirationTimeout);
+}
+
+auto PrefetchCache::sessionPrefetchMap(PAL::SessionID sessionID) const -> PrefetchEntriesMap*
+{
+ ASSERT(sessionID.isValid());
+ return m_sessionPrefetches.get(sessionID);
+}
+
+void PrefetchCache::clearExpiredEntries()
+{
+ PAL::SessionID sessionID;
+ URL requestUrl;
+ WallTime timestamp;
+ auto timeout = WallTime::now();
+ while (!m_sessionExpirationList.isEmpty()) {
+ std::tie(sessionID, requestUrl, timestamp) = m_sessionExpirationList.first();
+ auto* resources = sessionPrefetchMap(sessionID);
+ ASSERT(resources);
+ ASSERT(resources->contains(requestUrl));
+ auto elapsed = timeout - timestamp;
+ if (elapsed > expirationTimeout) {
+ resources->remove(requestUrl);
+ m_sessionExpirationList.removeFirst();
+ } else {
+ m_expirationTimer.startOneShot(expirationTimeout - elapsed);
+ break;
+ }
+ }
+}
+
+}
Added: trunk/Source/WebKit/NetworkProcess/cache/PrefetchCache.h (0 => 244248)
--- trunk/Source/WebKit/NetworkProcess/cache/PrefetchCache.h (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/cache/PrefetchCache.h 2019-04-14 20:52:46 UTC (rev 244248)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <WebCore/ResourceResponse.h>
+#include <WebCore/SharedBuffer.h>
+#include <WebCore/Timer.h>
+#include <wtf/Deque.h>
+#include <wtf/HashMap.h>
+#include <wtf/URLHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+class PrefetchCache {
+ WTF_MAKE_NONCOPYABLE(PrefetchCache);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ PrefetchCache();
+ ~PrefetchCache();
+
+ void clear();
+
+ struct Entry {
+ Entry(WebCore::ResourceResponse&&, RefPtr<WebCore::SharedBuffer>&&);
+
+ RefPtr<WebCore::SharedBuffer> releaseBuffer() { return buffer.releaseNonNull(); }
+
+ WebCore::ResourceResponse response;
+ RefPtr<WebCore::SharedBuffer> buffer;
+ };
+
+ std::unique_ptr<Entry> take(PAL::SessionID, const URL&);
+ void store(PAL::SessionID, const URL&, WebCore::ResourceResponse&&, RefPtr<WebCore::SharedBuffer>&&);
+
+private:
+ void clearExpiredEntries();
+
+ using PrefetchEntriesMap = HashMap<URL, std::unique_ptr<Entry>>;
+ PrefetchEntriesMap* sessionPrefetchMap(PAL::SessionID) const;
+
+ using SessionPrefetchResourceMap = HashMap<PAL::SessionID, std::unique_ptr<PrefetchEntriesMap>>;
+ SessionPrefetchResourceMap m_sessionPrefetches;
+
+ using SessionPrefetchExpirationList = Deque<std::tuple<PAL::SessionID, URL, WallTime>>;
+ SessionPrefetchExpirationList m_sessionExpirationList;
+
+ WebCore::Timer m_expirationTimer;
+};
+
+} // namespace WebKit
Modified: trunk/Source/WebKit/Shared/WebPreferences.yaml (244247 => 244248)
--- trunk/Source/WebKit/Shared/WebPreferences.yaml 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/Shared/WebPreferences.yaml 2019-04-14 20:52:46 UTC (rev 244248)
@@ -1644,6 +1644,14 @@
humanReadableName: "Apple Pay Remote UI"
type: bool
+LinkPrefetchEnabled:
+ type: bool
+ defaultValue: false
+ humanReadableName: "LinkPrefetch"
+ humanReadableDescription: "Enable LinkedPrefetch"
+ webcoreBinding: RuntimeEnabledFeatures
+ category: experimental
+
# Deprecated
ICECandidateFilteringEnabled:
Modified: trunk/Source/WebKit/Sources.txt (244247 => 244248)
--- trunk/Source/WebKit/Sources.txt 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/Sources.txt 2019-04-14 20:52:46 UTC (rev 244248)
@@ -80,6 +80,7 @@
NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp
NetworkProcess/cache/NetworkCacheStorage.cpp
NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp
+NetworkProcess/cache/PrefetchCache.cpp
NetworkProcess/webrtc/NetworkMDNSRegister.cpp
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (244247 => 244248)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-04-14 20:14:19 UTC (rev 244247)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-04-14 20:52:46 UTC (rev 244248)
@@ -1330,6 +1330,7 @@
A78CCDDB193AC9F8005ECC25 /* com.apple.WebKit.Networking.sb in CopyFiles */ = {isa = PBXBuildFile; fileRef = A78CCDD8193AC9E3005ECC25 /* com.apple.WebKit.Networking.sb */; };
A78CCDDC193AC9FB005ECC25 /* com.apple.WebKit.WebContent.sb in CopyFiles */ = {isa = PBXBuildFile; fileRef = A78CCDD9193AC9E3005ECC25 /* com.apple.WebKit.WebContent.sb */; };
A7D792D81767CCA300881CBE /* ActivityAssertion.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D792D41767CB0900881CBE /* ActivityAssertion.h */; };
+ AAB145E6223F931200E489D8 /* PrefetchCache.h in Headers */ = {isa = PBXBuildFile; fileRef = AAB145E4223F931200E489D8 /* PrefetchCache.h */; };
B62E7312143047B00069EC35 /* WKHitTestResult.h in Headers */ = {isa = PBXBuildFile; fileRef = B62E7311143047B00069EC35 /* WKHitTestResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
B878B615133428DC006888E9 /* CorrectionPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = B878B613133428DC006888E9 /* CorrectionPanel.h */; };
BC017D0716260FF4007054F5 /* WKDOMDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = BC017CFF16260FF4007054F5 /* WKDOMDocument.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3971,6 +3972,8 @@
A7D792D41767CB0900881CBE /* ActivityAssertion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActivityAssertion.h; sourceTree = "<group>"; };
A7D792D51767CB6E00881CBE /* ActivityAssertion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActivityAssertion.cpp; sourceTree = "<group>"; };
A7E93CEB192531AA00A1DC48 /* AuxiliaryProcessIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AuxiliaryProcessIOS.mm; path = ios/AuxiliaryProcessIOS.mm; sourceTree = "<group>"; };
+ AAB145E4223F931200E489D8 /* PrefetchCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrefetchCache.h; sourceTree = "<group>"; };
+ AAB145E5223F931200E489D8 /* PrefetchCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrefetchCache.cpp; sourceTree = "<group>"; };
B396EA5512E0ED2D00F4FEB7 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
B62E730F143047A60069EC35 /* WKHitTestResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKHitTestResult.cpp; sourceTree = "<group>"; };
B62E7311143047B00069EC35 /* WKHitTestResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHitTestResult.h; sourceTree = "<group>"; };
@@ -8929,6 +8932,8 @@
E4436EC21A0CFDB200EAD204 /* NetworkCacheStorage.h */,
8310428A1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.cpp */,
831042891BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.h */,
+ AAB145E5223F931200E489D8 /* PrefetchCache.cpp */,
+ AAB145E4223F931200E489D8 /* PrefetchCache.h */,
);
path = cache;
sourceTree = "<group>";
@@ -9406,6 +9411,7 @@
7CD622781739D863005BD7FF /* PluginSandboxProfile.h in Headers */,
1A6FB7AF11E64B6800DB1371 /* PluginView.h in Headers */,
83A0ED351F747CCF003299EB /* PreconnectTask.h in Headers */,
+ AAB145E6223F931200E489D8 /* PrefetchCache.h in Headers */,
E1CC1B9012D7EADF00625838 /* PrintInfo.h in Headers */,
86F9536518FF58F5001DB2EF /* ProcessAssertion.h in Headers */,
BC1A7C581136E19C00FB7167 /* ProcessLauncher.h in Headers */,