Changeset 247860 in webkit


Ignore:
Timestamp:
Jul 26, 2019 12:29:55 AM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Make storing cross-origin top-level prefetches in HTTP cache optional
https://bugs.webkit.org/show_bug.cgi?id=199499

Patch by Rob Buis <rbuis@igalia.com> on 2019-07-26
Reviewed by Youenn Fablet.

Source/WebCore:

Add Internals API for adding an event listener to prefetch load.

Test: http/wpt/prefetch/link-prefetch-skip-disk-cache.html

  • bindings/js/JSEventListener.h:
  • dom/EventTarget.h:

(WebCore::EventTarget::addEventListener):

  • dom/Node.h:
  • html/HTMLLinkElement.h:
  • testing/Internals.cpp:

(WebCore::Internals::addPrefetchLoadEventListener):

  • testing/Internals.h:
  • testing/Internals.idl:

Source/WebKit:

Currently when we navigate we check if there is a cross-origin top-level
prefetch we can use for the navigation. The current solution uses the
HTTP cache as a way to store the prefetch and to immediately use it for
the navigation load. However this solution fails in case the prefetch is
not cacheable.

Instead of this, simulate a HTTP Cache entry to process the load and
afterwards try to store the navigation load into the HTTP cache, where
normal store decisions will be applied.

Test: http/wpt/prefetch/link-prefetch-skip-disk-cache.html

  • NetworkProcess/NetworkResourceLoader.cpp:

(WebKit::NetworkResourceLoader::retrieveCacheEntry):
(WebKit::NetworkResourceLoader::retrieveCacheEntryInternal):

  • NetworkProcess/NetworkResourceLoader.h:

LayoutTests:

Remove unneeded Cache-Control headers and verify that Cache-Control
effects whether the navigation gets stored in the disk cache or not.

  • http/tests/cache/resources/prefetched-main-resource-iframe.php:
  • http/tests/cache/resources/prefetched-main-resource.php:
  • http/wpt/prefetch/link-prefetch-skip-disk-cache-expected.txt: Added.
  • http/wpt/prefetch/link-prefetch-skip-disk-cache.html: Added.
  • http/wpt/prefetch/resources/main-resource-skip-disk-cache.py: Added.

(main):

  • http/wpt/prefetch/resources/navigate-skip-disk-cache.html: Added.
  • platform/mac-wk1/TestExpectations:
  • platform/win/TestExpectations:
Location:
trunk
Files:
4 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r247842 r247860  
     12019-07-26  Rob Buis  <rbuis@igalia.com>
     2
     3        Make storing cross-origin top-level prefetches in HTTP cache optional
     4        https://bugs.webkit.org/show_bug.cgi?id=199499
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Remove unneeded Cache-Control headers and verify that Cache-Control
     9        effects whether the navigation gets stored in the disk cache or not.
     10
     11        * http/tests/cache/resources/prefetched-main-resource-iframe.php:
     12        * http/tests/cache/resources/prefetched-main-resource.php:
     13        * http/wpt/prefetch/link-prefetch-skip-disk-cache-expected.txt: Added.
     14        * http/wpt/prefetch/link-prefetch-skip-disk-cache.html: Added.
     15        * http/wpt/prefetch/resources/main-resource-skip-disk-cache.py: Added.
     16        (main):
     17        * http/wpt/prefetch/resources/navigate-skip-disk-cache.html: Added.
     18        * platform/mac-wk1/TestExpectations:
     19        * platform/win/TestExpectations:
     20
    1212019-07-25  Commit Queue  <commit-queue@webkit.org>
    222
  • trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource-iframe.php

    r247825 r247860  
    11<?php
    22if ($_SERVER["HTTP_PURPOSE"] == "prefetch") {
    3     header('Cache-Control: max-age=3600');
    4     header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
    5 
    63    echo "<script>";
    74    echo "parent.window.postMessage('FAIL', '*');";
     
    118}
    129
    13 header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
    14 
    1510echo "<script>";
    1611echo "parent.window.postMessage('PASS', '*');";
  • trunk/LayoutTests/http/tests/cache/resources/prefetched-main-resource.php

    r247825 r247860  
    77<script>
    88
    9 if (window.testRunner)
    10    testRunner.notifyDone();
     9if (window.testRunner) {
     10  fetch('http://localhost:8000/cache/resources/prefetched-main-resource.php').then(function(response) {
     11    if (internals.fetchResponseSource(response) != "Disk cache") {
     12      document.getElementById('log').innerText = 'FAIL: resource is not in the disk cache.';
     13    }
     14    testRunner.notifyDone();
     15  });
     16}
    1117
    1218</script>
    13 <?php
    14 if ($_SERVER["HTTP_PURPOSE"] == "prefetch") {
    15     print('PASS');
    16 } else {
    17     print('FAIL');
    18 }
    19 ?>
     19<div id="log"><?php if ($_SERVER["HTTP_PURPOSE"] == "prefetch") echo 'PASS'; else echo 'FAIL'; ?></div>
    2020</body>
    2121</html>
  • trunk/LayoutTests/platform/mac-wk1/TestExpectations

    r247825 r247860  
    737737
    738738webkit.org/b/197371 http/wpt/prefetch/link-prefetch-main-resource-redirect.html [ Skip ]
     739webkit.org/b/199499 http/wpt/prefetch/link-prefetch-skip-disk-cache.html [ Skip ]
    739740
    740741webkit.org/b/199632 http/wpt/prefetch/beforeload.html [ Skip ]
  • trunk/LayoutTests/platform/win/TestExpectations

    r247825 r247860  
    44254425
    44264426webkit.org/b/197371 http/wpt/prefetch/link-prefetch-main-resource-redirect.html [ Skip ]
     4427webkit.org/b/199499 http/wpt/prefetch/link-prefetch-skip-disk-cache.html [ Skip ]
    44274428
    44284429webkit.org/b/199632 http/wpt/prefetch/beforeload.html [ Skip ]
  • trunk/Source/WebCore/ChangeLog

    r247846 r247860  
     12019-07-26  Rob Buis  <rbuis@igalia.com>
     2
     3        Make storing cross-origin top-level prefetches in HTTP cache optional
     4        https://bugs.webkit.org/show_bug.cgi?id=199499
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Add Internals API for adding an event listener to prefetch load.
     9
     10        Test: http/wpt/prefetch/link-prefetch-skip-disk-cache.html
     11
     12        * bindings/js/JSEventListener.h:
     13        * dom/EventTarget.h:
     14        (WebCore::EventTarget::addEventListener):
     15        * dom/Node.h:
     16        * html/HTMLLinkElement.h:
     17        * testing/Internals.cpp:
     18        (WebCore::Internals::addPrefetchLoadEventListener):
     19        * testing/Internals.h:
     20        * testing/Internals.idl:
     21
    1222019-07-25  Tim Horton  <timothy_horton@apple.com>
    223
  • trunk/Source/WebCore/bindings/js/JSEventListener.h

    r247825 r247860  
    3939class JSEventListener : public EventListener {
    4040public:
    41     static Ref<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&);
    42     static RefPtr<JSEventListener> create(JSC::JSValue listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&);
     41    WEBCORE_EXPORT static Ref<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&);
     42    WEBCORE_EXPORT static RefPtr<JSEventListener> create(JSC::JSValue listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&);
    4343
    4444    virtual ~JSEventListener();
  • trunk/Source/WebCore/dom/EventTarget.h

    r247825 r247860  
    8989    WEBCORE_EXPORT ExceptionOr<bool> dispatchEventForBindings(Event&);
    9090
    91     virtual bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions& = { });
     91    WEBCORE_EXPORT virtual bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions& = { });
    9292    virtual bool removeEventListener(const AtomString& eventType, EventListener&, const ListenerOptions&);
    9393
  • trunk/Source/WebCore/dom/Node.h

    r247825 r247860  
    473473    ScriptExecutionContext* scriptExecutionContext() const final; // Implemented in Document.h
    474474
    475     bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
     475    WEBCORE_EXPORT bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
    476476    bool removeEventListener(const AtomString& eventType, EventListener&, const ListenerOptions&) override;
    477477
  • trunk/Source/WebCore/html/HTMLLinkElement.h

    r247825 r247860  
    4949
    5050    URL href() const;
    51     const AtomString& rel() const;
     51    WEBCORE_EXPORT const AtomString& rel() const;
    5252
    5353    String target() const final;
  • trunk/Source/WebCore/testing/Internals.cpp

    r247835 r247860  
    6969#include "Element.h"
    7070#include "EventHandler.h"
     71#include "EventListener.h"
     72#include "EventNames.h"
    7173#include "ExtendableEvent.h"
    7274#include "ExtensionStyleSheets.h"
     
    51455147}
    51465148
     5149void Internals::addPrefetchLoadEventListener(HTMLLinkElement& link, RefPtr<EventListener>&& listener)
     5150{
     5151    if (RuntimeEnabledFeatures::sharedFeatures().linkPrefetchEnabled() && equalLettersIgnoringASCIICase(link.rel(), "prefetch"))
     5152        link.addEventListener(eventNames().loadEvent, listener.releaseNonNull(), false);
     5153}
     5154
    51475155} // namespace WebCore
  • trunk/Source/WebCore/testing/Internals.h

    r247825 r247860  
    6060class Document;
    6161class Element;
     62class EventListener;
    6263class ExtendableEvent;
    6364class FetchResponse;
     
    867868    TextIndicatorInfo textIndicatorForRange(const Range&, TextIndicatorOptions);
    868869
     870    void addPrefetchLoadEventListener(HTMLLinkElement&, RefPtr<EventListener>&&);
     871
    869872private:
    870873    explicit Internals(Document&);
  • trunk/Source/WebCore/testing/Internals.idl

    r247825 r247860  
    782782
    783783    TextIndicatorInfo textIndicatorForRange(Range range, TextIndicatorOptions options);
    784 };
     784
     785    void addPrefetchLoadEventListener(HTMLLinkElement link, EventListener? callback);
     786};
  • trunk/Source/WebKit/ChangeLog

    r247856 r247860  
     12019-07-26  Rob Buis  <rbuis@igalia.com>
     2
     3        Make storing cross-origin top-level prefetches in HTTP cache optional
     4        https://bugs.webkit.org/show_bug.cgi?id=199499
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Currently when we navigate we check if there is a cross-origin top-level
     9        prefetch we can use for the navigation. The current solution uses the
     10        HTTP cache as a way to store the prefetch and to immediately use it for
     11        the navigation load. However this solution fails in case the prefetch is
     12        not cacheable.
     13
     14        Instead of this, simulate a HTTP Cache entry to process the load and
     15        afterwards try to store the navigation load into the HTTP cache, where
     16        normal store decisions will be applied.
     17
     18        Test: http/wpt/prefetch/link-prefetch-skip-disk-cache.html
     19
     20        * NetworkProcess/NetworkResourceLoader.cpp:
     21        (WebKit::NetworkResourceLoader::retrieveCacheEntry):
     22        (WebKit::NetworkResourceLoader::retrieveCacheEntryInternal):
     23        * NetworkProcess/NetworkResourceLoader.h:
     24
    1252019-07-25  Zan Dobersek  <zdobersek@igalia.com>
    226
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

    r247825 r247860  
    219219        if (auto* session = m_connection->networkProcess().networkSession(sessionID())) {
    220220            if (auto entry = session->prefetchCache().take(request.url())) {
     221                // FIXME: Deal with credentials (https://bugs.webkit.org/show_bug.cgi?id=200000)
    221222                if (!entry->redirectRequest.isNull()) {
     223                    auto cacheEntry = m_cache->makeRedirectEntry(request, entry->response, entry->redirectRequest);
     224                    loader->retrieveCacheEntryInternal(WTFMove(cacheEntry), ResourceRequest { request });
    222225                    auto maxAgeCap = validateCacheEntryForMaxAgeCapValidation(request, entry->redirectRequest, entry->response);
    223226                    m_cache->storeRedirect(request, entry->response, entry->redirectRequest, maxAgeCap);
    224                 } else
    225                     m_cache->store(request, entry->response, entry->releaseBuffer(), nullptr);
     227                    return;
     228                }
     229                auto buffer = entry->releaseBuffer();
     230                auto cacheEntry = m_cache->makeEntry(request, entry->response, buffer.copyRef());
     231                loader->retrieveCacheEntryInternal(WTFMove(cacheEntry), ResourceRequest { request });
     232                m_cache->store(request, entry->response, WTFMove(buffer), nullptr);
     233                return;
    226234            }
    227235        }
     
    240248            return;
    241249        }
     250        loader->retrieveCacheEntryInternal(WTFMove(entry), WTFMove(request));
     251    });
     252}
     253
     254void NetworkResourceLoader::retrieveCacheEntryInternal(std::unique_ptr<NetworkCache::Entry>&& entry, WebCore::ResourceRequest&& request)
     255{
    242256#if ENABLE(RESOURCE_LOAD_STATISTICS)
    243         if (entry->hasReachedPrevalentResourceAgeCap()) {
    244             RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Resource has reached prevalent resource age cap (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
    245             m_cacheEntryForMaxAgeCapValidation = WTFMove(entry);
    246             ResourceRequest revalidationRequest = originalRequest();
    247             loader->startNetworkLoad(WTFMove(revalidationRequest), FirstLoad::Yes);
    248             return;
    249         }
     257    if (entry->hasReachedPrevalentResourceAgeCap()) {
     258        RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Resource has reached prevalent resource age cap (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
     259        m_cacheEntryForMaxAgeCapValidation = WTFMove(entry);
     260        ResourceRequest revalidationRequest = originalRequest();
     261        startNetworkLoad(WTFMove(revalidationRequest), FirstLoad::Yes);
     262        return;
     263    }
    250264#endif
    251         if (entry->redirectRequest()) {
    252             RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Handling redirect (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
    253             loader->dispatchWillSendRequestForCacheEntry(WTFMove(request), WTFMove(entry));
    254             return;
    255         }
    256         if (loader->m_parameters.needsCertificateInfo && !entry->response().certificateInfo()) {
    257             RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Resource does not have required certificate (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
    258             loader->startNetworkLoad(WTFMove(request), FirstLoad::Yes);
    259             return;
    260         }
    261         if (entry->needsValidation() || request.cachePolicy() == WebCore::ResourceRequestCachePolicy::RefreshAnyCacheData) {
    262             RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Validating cache entry (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
    263             loader->validateCacheEntry(WTFMove(entry));
    264             return;
    265         }
    266         RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Retrieved resource from cache (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
    267         loader->didRetrieveCacheEntry(WTFMove(entry));
    268     });
     265    if (entry->redirectRequest()) {
     266        RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Handling redirect (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
     267        dispatchWillSendRequestForCacheEntry(WTFMove(request), WTFMove(entry));
     268        return;
     269    }
     270    if (m_parameters.needsCertificateInfo && !entry->response().certificateInfo()) {
     271        RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Resource does not have required certificate (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
     272        startNetworkLoad(WTFMove(request), FirstLoad::Yes);
     273        return;
     274    }
     275    if (entry->needsValidation() || request.cachePolicy() == WebCore::ResourceRequestCachePolicy::RefreshAnyCacheData) {
     276        RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Validating cache entry (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
     277        validateCacheEntry(WTFMove(entry));
     278        return;
     279    }
     280    RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Retrieved resource from cache (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
     281    didRetrieveCacheEntry(WTFMove(entry));
    269282}
    270283
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h

    r247825 r247860  
    130130    void tryStoreAsCacheEntry();
    131131    void retrieveCacheEntry(const WebCore::ResourceRequest&);
     132    void retrieveCacheEntryInternal(std::unique_ptr<NetworkCache::Entry>&&, WebCore::ResourceRequest&&);
    132133    void didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry>);
    133134    void sendResultForCacheEntry(std::unique_ptr<NetworkCache::Entry>);
Note: See TracChangeset for help on using the changeset viewer.