Title: [244248] trunk
Revision
244248
Author
[email protected]
Date
2019-04-14 13:52:46 -0700 (Sun, 14 Apr 2019)

Log Message

Link prefetch not useful for top-level navigation
https://bugs.webkit.org/show_bug.cgi?id=195623

Patch by Rob Buis <[email protected]> on 2019-04-14
Reviewed by Youenn Fablet.

Source/WebCore:

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):

Source/WebKit:

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:

LayoutTests:

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:

Modified Paths

Added Paths

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 */,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to