Add event support for link preload.
authoryoav@yoav.ws <yoav@yoav.ws@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 31 Aug 2016 22:41:44 +0000 (22:41 +0000)
committeryoav@yoav.ws <yoav@yoav.ws@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 31 Aug 2016 22:41:44 +0000 (22:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=158466

Reviewed by Alex Christensen.

Source/WebCore:

Add onload/onerror support for link rel preload to align it with the spec
and enable various resource loading use-cases.
This patch also fixes XHR matching issues by replacing LinkPreload with RawResource.

Tests: http/tests/misc/script_onload_delays_window_onload.html
       http/tests/preload/delaying_onload_link_preload_after_discovery.html
       http/tests/preload/delaying_onload_link_preload_after_discovery_image.html
       http/tests/preload/not_delaying_window_onload_before_discovery.html
       http/tests/preload/onerror_event.html
       http/tests/preload/onload_event.html

* CMakeLists.txt: Add LinkPreloadResourceClients.{h,cpp}
* WebCore.xcodeproj/project.pbxproj: Add LinkPreloadResourceClients.{h,cpp}.
* html/HTMlLinkElement.cpp:
(WebCore::linkErrorEventSender): Add an eventSender for the error event.
(WebCore::HTMLLinkElement::HTMLLinkElement): s/m_loadedSheet/m_loadedResource/
(WebCore::HTMLLinkElement::~HTMLLinkElement): Cancel the error event when the element gets destructed.
(WebCore::HTMLLinkElement::linkLoaded): dispatch the event in an async manner.
(WebCore::HTMLLinkElement::linkLoadingErrored): dispatch the event in an async manner.
(WebCore::HTMLLinkElement::dispatchPendingEvent): Call dispatchEvent directly.
(WebCore::HTMLLinkElement::notifyLoadedSheetAndAllCriticalSubresources): s/m_loadedSheet/m_loadedResource/
* html/HTMLLinkElement.h: s/m_loadedSheet/m_loadedResource/
* html/parser/HTMLResourcePreloader.cpp:
(WebCore::HTMLResourcePreloader::preload): Call preload as ImplicitPreload, to distinguish it from declarative preload.
* loader/LinkLoader.cpp:
(WebCore::LinkLoader::LinkLoader): Get rid of unnecessary event timers and add a weakPtrFactory.
(WebCore::LinkLoader::triggerEvents): Add a triggerEvents function that can be called from notifyFinished as well as the
LinkPreloadResourceClients.
(WebCore::LinkLoader::notifyFinished): Call the triggerEvents function.
(WebCore::LinkLoader::resourceTypeFromAsAttribute): Replace LinkPreload with RawResource to avoid XHR resource matching issues.
(WebCore::createLinkPreloadResourceClient): Create a resource client for link preload.
(WebCore::LinkLoader::preloadIfNeeded): Trigger an error when `as` is unknown. Make sure that preload resources don't delay window.onload
before discovery. Get the resource back from calling preload and create a client for that resource.
(WebCore::LinkLoader::linkLoadTimerFired): Deleted.
(WebCore::LinkLoader::linkLoadingErrorTimerFired): Deleted.
(WebCore::preloadIfNeeded): Deleted.
* loader/LinkLoader.h:
(WebCore::LinkLoader::createWeakPtr):
* loader/LinkPreloadResourceClients.cpp: Added.
(WebCore::LinkPreloadResourceClient::LinkPreloadResourceClient): Create a LinkPreloadResourceClient and assign with with a weakPtr of
LinkLoader.
(WebCore::LinkPreloadResourceClient::triggerEvents): Call LinkLoader's triggerEvents.
* loader/LinkPreloadResourceClients.h: Added.
(WebCore::LinkPreloadResourceClient::~LinkPreloadResourceClient):
(WebCore::LinkPreloadResourceClient::addResource): Add as resource's client.
(WebCore::LinkPreloadResourceClient::clearResource): Remove as resource's client and clear ref to resource.
(WebCore::LinkPreloadResourceClient::ownedResource): Return ref to resource.
* loader/ResourceLoadInfo.cpp:
(WebCore::toResourceType): Removed LinkPreload.
* loader/SubresourceLoader.cpp:
(WebCore::logResourceLoaded): Removed LinkPreload.
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::defaultPriorityForResourceType): Removed LinkPreload.
* loader/cache/CachedResource.h: Removed LinkPreload.
(WebCore::CachedResource::ignoreForRequestCount): Don't delay window.onload for requests that opted out of that.
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::checkInsecureContent): Removed LinkPreload.
(WebCore::CachedResourceLoader::requestResource): Make sure that discovered preload resources do block window.onload.
(WebCore::CachedResourceLoader::preload): Make sure that explicitly preloaded subresources can be fetched even if there are parser
blocking resources still in flight. Return the preloaded resource.
(WebCore::CachedResourceLoader::requestPreload): Make sure that preloaded fonts get requested. Return preloaded resource.
(WebCore::createResource): Removed LinkPreload.
(WebCore::contentTypeFromResourceType): Removed LinkPreload.
(WebCore::CachedResourceLoader::canRequest): Removed LinkPreload.
* loader/cache/CachedResourceLoader.h:
* platform/network/ResourceRequestBase.h:
(WebCore::ResourceRequestBase::ignoreForRequestCount): Get the flag saying if a resource should block window.onload.
(WebCore::ResourceRequestBase::setIgnoreForRequestCount): Set the flag saying if a resource should block window.onload.

Source/WebKit2:

* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::maximumBufferingTime): Removed LinkPreload.

LayoutTests:

Add tests that make sure that event handling with regarding to link preload
is working as it should.

* http/tests/misc/script_onload_delays_window_onload-expected.txt: Added.
* http/tests/misc/script_onload_delays_window_onload.html: Added.
* http/tests/preload/delaying_onload_link_preload_after_discovery-expected.txt: Added.
* http/tests/preload/delaying_onload_link_preload_after_discovery.html: Added.
* http/tests/preload/delaying_onload_link_preload_after_discovery_image-expected.txt: Added.
* http/tests/preload/delaying_onload_link_preload_after_discovery_image.html: Added.
* http/tests/preload/dynamic_remove_preload_href-expected.txt:
* http/tests/preload/dynamic_remove_preload_href.html:
* http/tests/preload/not_delaying_window_onload_before_discovery-expected.txt: Added.
* http/tests/preload/not_delaying_window_onload_before_discovery.html: Added.
* http/tests/preload/onerror_event-expected.txt: Added.
* http/tests/preload/onerror_event.html: Added.
* http/tests/preload/onload_event-expected.txt: Added.
* http/tests/preload/onload_event.html: Added.
* http/tests/preload/resources/single_download_preload.html:
* http/tests/resources/dummy.css: Added.
* http/tests/resources/dummy.js: Added.
* http/tests/resources/dummy.xml: Added.
* http/tests/resources/slow-image.php: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@205269 268f45cc-cd09-0410-ab3c-d52691b4dbfc

38 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/misc/script_onload_delays_window_onload-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/misc/script_onload_delays_window_onload.html [new file with mode: 0644]
LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery.html [new file with mode: 0644]
LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery_image-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery_image.html [new file with mode: 0644]
LayoutTests/http/tests/preload/dynamic_remove_preload_href-expected.txt
LayoutTests/http/tests/preload/dynamic_remove_preload_href.html
LayoutTests/http/tests/preload/not_delaying_window_onload_before_discovery-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/preload/not_delaying_window_onload_before_discovery.html [new file with mode: 0644]
LayoutTests/http/tests/preload/onerror_event-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/preload/onerror_event.html [new file with mode: 0644]
LayoutTests/http/tests/preload/onload_event-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/preload/onload_event.html [new file with mode: 0644]
LayoutTests/http/tests/preload/resources/single_download_preload.html
LayoutTests/http/tests/resources/dummy.css [new file with mode: 0644]
LayoutTests/http/tests/resources/dummy.js [new file with mode: 0644]
LayoutTests/http/tests/resources/slow-image.php [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/html/HTMLLinkElement.cpp
Source/WebCore/html/HTMLLinkElement.h
Source/WebCore/html/parser/HTMLResourcePreloader.cpp
Source/WebCore/loader/LinkLoader.cpp
Source/WebCore/loader/LinkLoader.h
Source/WebCore/loader/LinkPreloadResourceClients.cpp [new file with mode: 0644]
Source/WebCore/loader/LinkPreloadResourceClients.h [new file with mode: 0644]
Source/WebCore/loader/ResourceLoadInfo.cpp
Source/WebCore/loader/SubresourceLoader.cpp
Source/WebCore/loader/cache/CachedResource.cpp
Source/WebCore/loader/cache/CachedResource.h
Source/WebCore/loader/cache/CachedResourceLoader.cpp
Source/WebCore/loader/cache/CachedResourceLoader.h
Source/WebCore/platform/network/ResourceRequestBase.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Network/WebLoaderStrategy.cpp

index f37f385..c96fa8c 100644 (file)
@@ -1,3 +1,33 @@
+2016-08-31  Yoav Weiss  <yoav@yoav.ws>
+
+        Add event support for link preload.
+        https://bugs.webkit.org/show_bug.cgi?id=158466
+
+        Reviewed by Alex Christensen.
+
+        Add tests that make sure that event handling with regarding to link preload
+        is working as it should.
+
+        * http/tests/misc/script_onload_delays_window_onload-expected.txt: Added.
+        * http/tests/misc/script_onload_delays_window_onload.html: Added.
+        * http/tests/preload/delaying_onload_link_preload_after_discovery-expected.txt: Added.
+        * http/tests/preload/delaying_onload_link_preload_after_discovery.html: Added.
+        * http/tests/preload/delaying_onload_link_preload_after_discovery_image-expected.txt: Added.
+        * http/tests/preload/delaying_onload_link_preload_after_discovery_image.html: Added.
+        * http/tests/preload/dynamic_remove_preload_href-expected.txt:
+        * http/tests/preload/dynamic_remove_preload_href.html:
+        * http/tests/preload/not_delaying_window_onload_before_discovery-expected.txt: Added.
+        * http/tests/preload/not_delaying_window_onload_before_discovery.html: Added.
+        * http/tests/preload/onerror_event-expected.txt: Added.
+        * http/tests/preload/onerror_event.html: Added.
+        * http/tests/preload/onload_event-expected.txt: Added.
+        * http/tests/preload/onload_event.html: Added.
+        * http/tests/preload/resources/single_download_preload.html:
+        * http/tests/resources/dummy.css: Added.
+        * http/tests/resources/dummy.js: Added.
+        * http/tests/resources/dummy.xml: Added.
+        * http/tests/resources/slow-image.php: Added.
+
 2016-08-31  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: XHR with text but responseType = "blob" shows blank content
diff --git a/LayoutTests/http/tests/misc/script_onload_delays_window_onload-expected.txt b/LayoutTests/http/tests/misc/script_onload_delays_window_onload-expected.txt
new file mode 100644 (file)
index 0000000..c8fad01
--- /dev/null
@@ -0,0 +1,5 @@
+PASS scriptLoaded is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/misc/script_onload_delays_window_onload.html b/LayoutTests/http/tests/misc/script_onload_delays_window_onload.html
new file mode 100644 (file)
index 0000000..1c21917
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script src="/js-test-resources/js-test.js"></script>
+<script>
+    var scriptLoaded = false;
+</script>
+<script src="../resources/slow-script.pl?delay=200" onload="scriptLoaded = true;"></script>
+<script>
+     addEventListener("load", function() {
+         shouldBeTrue("scriptLoaded");
+     });
+</script>
+
diff --git a/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery-expected.txt b/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery-expected.txt
new file mode 100644 (file)
index 0000000..9089b45
--- /dev/null
@@ -0,0 +1,5 @@
+PASS finishedScript is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery.html b/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery.html
new file mode 100644 (file)
index 0000000..d1e4c17
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script>
+    if (window.internals)
+        window.internals.setLinkPreloadSupport(true);
+    if (window.testRunner) {
+        testRunner.dumpAsText()
+        testRunner.waitUntilDone();
+    }
+    var finishedScript = false;
+</script>
+<script src="/js-test-resources/js-test.js"></script>
+<link rel=preload href="../resources/slow-script.pl?delay=400" as=script onload="finishedScript = true;">
+<body>
+<script>
+    window.addEventListener("load", function() {
+        shouldBeTrue("finishedScript");
+        if (window.internals)
+            window.internals.setLinkPreloadSupport(false);
+        setTimeout(function() { testRunner.notifyDone(); }, 0);
+    });
+    var scr = document.createElement("script");
+    scr.src = "../resources/slow-script.pl?delay=400";
+    document.body.appendChild(scr);
+</script>
+</body>
diff --git a/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery_image-expected.txt b/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery_image-expected.txt
new file mode 100644 (file)
index 0000000..c87adf1
--- /dev/null
@@ -0,0 +1,5 @@
+PASS finishedImage is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery_image.html b/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery_image.html
new file mode 100644 (file)
index 0000000..912666c
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script>
+    if (window.internals)
+        window.internals.setLinkPreloadSupport(true);
+    if (window.testRunner) {
+        testRunner.dumpAsText()
+        testRunner.waitUntilDone();
+    }
+    var finishedImage = false;
+</script>
+<script src="/js-test-resources/js-test.js"></script>
+<link rel=preload href="../resources/slow-image.php" as=image onload="finishedImage = true;">
+<body>
+<script>
+    window.addEventListener("load", function() {
+        shouldBeTrue("finishedImage");
+        if (window.internals)
+            window.internals.setLinkPreloadSupport(false);
+        testRunner.notifyDone();
+    });
+    var img = new Image();
+    img.src = "../resources/slow-image.php";
+    document.body.appendChild(img);
+</script>
+</body>
index 9521a40..6ec1848 100644 (file)
@@ -1,5 +1,5 @@
-CONSOLE MESSAGE: line 16: <link rel=preload> has an invalid `href` value
-PASS internals.isPreloaded('../resources/dummy.js'); is false
+CONSOLE MESSAGE: line 19: <link rel=preload> has an invalid `href` value
+PASS downloadedImage is false
 PASS successfullyParsed is true
 
 TEST COMPLETE
index fe3bc90..09f15f9 100644 (file)
@@ -2,22 +2,32 @@
 <html>
 <head>
 <script>
-    if (window.internals)
+    if (window.internals) {
         window.internals.setLinkPreloadSupport(true);
+        window.internals.setResourceTimingSupport(true);
+    }
 </script>
 <script src="/js-test-resources/js-test.js"></script>
 <body>
 <script>
     var link = document.createElement("link");
-    link.as = "script";
+    link.as = "image";
     link.rel = "preload";
-    link.href = "../resources/dummy.js";
+    link.href = "../resources/slow-image.php";
+    var downloadedImage = false;
     document.body.appendChild(link);
     link.href = "";
     window.addEventListener("load", function() {
-        shouldBeFalse("internals.isPreloaded('../resources/dummy.js');");
-        if (window.internals)
+        var entries = performance.getEntriesByType("resource");
+        for (var i = 0; i < entries.length; ++i) {
+            if (entries[i].name.indexOf("slow-image.php") != -1)
+                downloadedImage = true;
+        }
+        shouldBeFalse("downloadedImage");
+        if (window.internals) {
             window.internals.setLinkPreloadSupport(false);
+            window.internals.setResourceTimingSupport(false);
+        }
     });
 </script>
 </body>
diff --git a/LayoutTests/http/tests/preload/not_delaying_window_onload_before_discovery-expected.txt b/LayoutTests/http/tests/preload/not_delaying_window_onload_before_discovery-expected.txt
new file mode 100644 (file)
index 0000000..ae020b1
--- /dev/null
@@ -0,0 +1,8 @@
+PASS finishedScript is false
+PASS finishedImage is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS windowOnLoad is true
+PASS windowOnLoad is true
+
diff --git a/LayoutTests/http/tests/preload/not_delaying_window_onload_before_discovery.html b/LayoutTests/http/tests/preload/not_delaying_window_onload_before_discovery.html
new file mode 100644 (file)
index 0000000..a19cec7
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<script>
+    if (window.internals)
+        window.internals.setLinkPreloadSupport(true);
+    if (window.testRunner) {
+        testRunner.dumpAsText()
+        testRunner.waitUntilDone();
+    }
+</script>
+<script src="/js-test-resources/js-test.js"></script>
+<script>
+    finishedScript = false;
+    finishedImage = false;
+    windowOnLoad = false;
+    function test() {
+        shouldBeTrue("windowOnLoad");
+        if (finishedImage && finishedScript) {
+            if (window.internals)
+                window.internals.setLinkPreloadSupport(false);
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+    };
+
+</script>
+<link rel=preload href="../resources/slow-script.pl?delay=200" as=script onload="window.finishedScript = true; test();">
+<link rel=preload href="../resources/slow-image.php" as=image onload="window.finishedImage = true; test();">
+<body>
+<script>
+    window.addEventListener("load", function() {
+        shouldBeFalse("finishedScript");
+        shouldBeFalse("finishedImage");
+        windowOnLoad = true;
+    });
+</script>
+</body>
diff --git a/LayoutTests/http/tests/preload/onerror_event-expected.txt b/LayoutTests/http/tests/preload/onerror_event-expected.txt
new file mode 100644 (file)
index 0000000..5bcd26e
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: line 29: <link rel=preload> must have a valid `as` value
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS styleFailed is true
+PASS scriptFailed is true
+PASS imageFailed is true
+PASS fontFailed is true
+PASS trackFailed is true
+PASS gibrishFailed is true
+PASS noTypeFailed is true
+
diff --git a/LayoutTests/http/tests/preload/onerror_event.html b/LayoutTests/http/tests/preload/onerror_event.html
new file mode 100644 (file)
index 0000000..e338a58
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<script>
+    if (window.internals)
+        window.internals.setLinkPreloadSupport(true);
+    if (window.testRunner) {
+        testRunner.dumpAsText()
+        testRunner.waitUntilDone();
+    }
+</script>
+<script src="/js-test-resources/js-test.js"></script>
+<script>
+    var scriptFailed = false;
+    var styleFailed = false;
+    var imageFailed = false;
+    var fontFailed = false;
+    var trackFailed = false;
+    var gibrishFailed = false;
+    var noTypeFailed = false;
+    var counter = 0;
+    function count() {
+        ++window.counter;
+    };
+</script>
+<link rel=preload href="../non-existent/dummy.js" as=script onerror="count();scriptFailed = true;" onload="count();">
+<link rel=preload href="../non-existent/dummy.css" as=style onerror="count();styleFailed = true;" onload="count();">
+<link rel=preload href="../non-existent/square.png" as=image onerror="count();imageFailed = true;" onload="count();">
+<link rel=preload href="../non-existent/Ahem.ttf" as=font crossorigin onerror="count();fontFailed = true;" onload="count();">
+<link rel=preload href="../non-existent/security/captions.vtt" as=track onerror="count();trackFailed = true;" onload="count();">
+<link rel=preload href="../non-existent/dummy.xml" as=foobarxmlthing onerror="count();gibrishFailed = true;" onload="count();">
+<link rel=preload href="http://127.0.0.1:9999/non-existent/dummy.xml" onerror="count();noTypeFailed = true;" onload="count();">
+<script>
+    function test() {
+        shouldBeTrue("styleFailed");
+        shouldBeTrue("scriptFailed");
+        shouldBeTrue("imageFailed");
+        shouldBeTrue("fontFailed");
+        shouldBeTrue("trackFailed");
+        shouldBeTrue("gibrishFailed");
+        shouldBeTrue("noTypeFailed");
+        if (window.internals)
+            window.internals.setLinkPreloadSupport(false);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    };
+    setInterval(function() {
+        if (window.counter >= 7)
+            test();
+    }, 100);
+</script>
+
diff --git a/LayoutTests/http/tests/preload/onload_event-expected.txt b/LayoutTests/http/tests/preload/onload_event-expected.txt
new file mode 100644 (file)
index 0000000..7b232ce
--- /dev/null
@@ -0,0 +1,18 @@
+CONSOLE MESSAGE: line 35: <link rel=preload> must have a valid `as` value
+CONSOLE MESSAGE: line 36: <link rel=preload> must have a valid `as` value
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS styleLoaded is true
+PASS scriptLoaded is true
+PASS imageLoaded is true
+PASS fontLoaded is true
+PASS mediaLoaded is true
+PASS trackLoaded is true
+PASS gibberishLoaded is false
+PASS gibberishErrored is true
+PASS xsltLoaded is false
+PASS xsltErrored is true
+PASS noTypeLoaded is true
+PASS emptyTypeLoaded is true
+
diff --git a/LayoutTests/http/tests/preload/onload_event.html b/LayoutTests/http/tests/preload/onload_event.html
new file mode 100644 (file)
index 0000000..670b393
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<script>
+    if (window.internals)
+        window.internals.setLinkPreloadSupport(true);
+    if (window.testRunner) {
+        testRunner.dumpAsText()
+        testRunner.waitUntilDone();
+    }
+</script>
+<script src="/js-test-resources/js-test.js"></script>
+<script>
+    var scriptLoaded = false;
+    var styleLoaded = false;
+    var imageLoaded = false;
+    var fontLoaded = false;
+    var mediaLoaded = false;
+    var trackLoaded = false;
+    var gibberishLoaded = false;
+    var gibberishErrored = false;
+    var xsltLoaded = false;
+    var xsltErrored = false;
+    var noTypeLoaded = false;
+    var emptyTypeLoaded = false;
+    var counter = 0;
+    function count() {
+        ++window.counter;
+    };
+</script>
+<link rel=preload href="../resources/dummy.js" as=script onload="count(); scriptLoaded = true;" onerror="count()">
+<link rel=preload href="../resources/dummy.css" as=style onload="count(); styleLoaded = true;" onerror="count()">
+<link rel=preload href="../resources/square100.png" as=image onload="count(); imageLoaded = true;" onerror="count()">
+<link rel=preload href="../resources/Ahem.woff" as=font crossorigin onload="count(); fontLoaded = true;" onerror="count()">
+<link rel=preload href="../resources/test.ogv" as=media onload="count(); mediaLoaded = true;" onerror="count()">
+<link rel=preload href="../security/resources/captions.vtt" as=track onload="count(); trackLoaded = true;" onerror="count()">
+<link rel=preload href="../resources/dummy.xml" as=foobarxmlthing onload="count(); gibberishLoaded = true;" onerror="count(); gibberishErrored = true;">
+<link rel=preload href="../resources/dummy.xslt" as=xslt onload="count(); xsltLoaded = true;" onerror="count(); xsltErrored = true;">
+<link rel=preload href="../resources/dummy.xml" onload="count(); noTypeLoaded = true;" onerror="count()">
+<link rel=preload href="../resources/dummy.xml?empty" as onload="count(); emptyTypeLoaded = true;" onerror="count()">
+<script>
+    function test() {
+        shouldBeTrue("styleLoaded");
+        shouldBeTrue("scriptLoaded");
+        shouldBeTrue("imageLoaded");
+        shouldBeTrue("fontLoaded");
+        shouldBeTrue("mediaLoaded");
+        shouldBeTrue("trackLoaded");
+        shouldBeFalse("gibberishLoaded");
+        shouldBeTrue("gibberishErrored");
+        shouldBeFalse("xsltLoaded");
+        shouldBeTrue("xsltErrored");
+        shouldBeTrue("noTypeLoaded");
+        shouldBeTrue("emptyTypeLoaded");
+        if (window.internals)
+            window.internals.setLinkPreloadSupport(false);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+     addEventListener("load", function(){
+        setInterval(function() {
+            if (window.counter >= 10)
+                test();
+        }, 100);
+    });
+</script>
+
index 5aa47d5..0b62957 100644 (file)
@@ -7,7 +7,7 @@
 <link rel=preload href="../../resources/test.mp4" as=media>
 <link rel=preload href="../../resources/test.oga" as=media>
 <link rel=preload href="../../security/resources/captions.vtt" as=track>
-<link rel=preload href="../../resources/dummy.xml" as=foobarxmlthing>
+<link rel=preload href="../../resources/dummy.xml?foobar" as=foobarxmlthing>
 <link rel=preload href="../../resources/dummy.xml">
 <script src="../../resources/slow-script.pl?delay=200"></script>
 <style>
diff --git a/LayoutTests/http/tests/resources/dummy.css b/LayoutTests/http/tests/resources/dummy.css
new file mode 100644 (file)
index 0000000..d9294e7
--- /dev/null
@@ -0,0 +1 @@
+body { line-height: 16px; }
diff --git a/LayoutTests/http/tests/resources/dummy.js b/LayoutTests/http/tests/resources/dummy.js
new file mode 100644 (file)
index 0000000..71f1a5a
--- /dev/null
@@ -0,0 +1 @@
+var x = 5;
diff --git a/LayoutTests/http/tests/resources/slow-image.php b/LayoutTests/http/tests/resources/slow-image.php
new file mode 100644 (file)
index 0000000..4a1ce0d
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+usleep(400000);
+header("Content-Type: image/png");
+@readfile("square100.png");
+?>
+
+
index 6f4d08c..c2b9217 100644 (file)
@@ -1944,6 +1944,7 @@ set(WebCore_SOURCES
     loader/HistoryController.cpp
     loader/ImageLoader.cpp
     loader/LinkLoader.cpp
+    loader/LinkPreloadResourceClients.cpp
     loader/LoadTiming.cpp
     loader/LoaderStrategy.cpp
     loader/MediaResourceLoader.cpp
index 547f3d3..293ab24 100644 (file)
@@ -1,3 +1,79 @@
+2016-08-31  Yoav Weiss  <yoav@yoav.ws>
+
+        Add event support for link preload.
+        https://bugs.webkit.org/show_bug.cgi?id=158466
+
+        Reviewed by Alex Christensen.
+
+        Add onload/onerror support for link rel preload to align it with the spec
+        and enable various resource loading use-cases.
+        This patch also fixes XHR matching issues by replacing LinkPreload with RawResource.
+
+        Tests: http/tests/misc/script_onload_delays_window_onload.html
+               http/tests/preload/delaying_onload_link_preload_after_discovery.html
+               http/tests/preload/delaying_onload_link_preload_after_discovery_image.html
+               http/tests/preload/not_delaying_window_onload_before_discovery.html
+               http/tests/preload/onerror_event.html
+               http/tests/preload/onload_event.html
+
+        * CMakeLists.txt: Add LinkPreloadResourceClients.{h,cpp}
+        * WebCore.xcodeproj/project.pbxproj: Add LinkPreloadResourceClients.{h,cpp}.
+        * html/HTMlLinkElement.cpp:
+        (WebCore::linkErrorEventSender): Add an eventSender for the error event.
+        (WebCore::HTMLLinkElement::HTMLLinkElement): s/m_loadedSheet/m_loadedResource/
+        (WebCore::HTMLLinkElement::~HTMLLinkElement): Cancel the error event when the element gets destructed.
+        (WebCore::HTMLLinkElement::linkLoaded): dispatch the event in an async manner.
+        (WebCore::HTMLLinkElement::linkLoadingErrored): dispatch the event in an async manner.
+        (WebCore::HTMLLinkElement::dispatchPendingEvent): Call dispatchEvent directly.
+        (WebCore::HTMLLinkElement::notifyLoadedSheetAndAllCriticalSubresources): s/m_loadedSheet/m_loadedResource/
+        * html/HTMLLinkElement.h: s/m_loadedSheet/m_loadedResource/
+        * html/parser/HTMLResourcePreloader.cpp:
+        (WebCore::HTMLResourcePreloader::preload): Call preload as ImplicitPreload, to distinguish it from declarative preload.
+        * loader/LinkLoader.cpp:
+        (WebCore::LinkLoader::LinkLoader): Get rid of unnecessary event timers and add a weakPtrFactory.
+        (WebCore::LinkLoader::triggerEvents): Add a triggerEvents function that can be called from notifyFinished as well as the
+        LinkPreloadResourceClients.
+        (WebCore::LinkLoader::notifyFinished): Call the triggerEvents function.
+        (WebCore::LinkLoader::resourceTypeFromAsAttribute): Replace LinkPreload with RawResource to avoid XHR resource matching issues.
+        (WebCore::createLinkPreloadResourceClient): Create a resource client for link preload.
+        (WebCore::LinkLoader::preloadIfNeeded): Trigger an error when `as` is unknown. Make sure that preload resources don't delay window.onload
+        before discovery. Get the resource back from calling preload and create a client for that resource.
+        (WebCore::LinkLoader::linkLoadTimerFired): Deleted.
+        (WebCore::LinkLoader::linkLoadingErrorTimerFired): Deleted.
+        (WebCore::preloadIfNeeded): Deleted.
+        * loader/LinkLoader.h:
+        (WebCore::LinkLoader::createWeakPtr):
+        * loader/LinkPreloadResourceClients.cpp: Added.
+        (WebCore::LinkPreloadResourceClient::LinkPreloadResourceClient): Create a LinkPreloadResourceClient and assign with with a weakPtr of
+        LinkLoader.
+        (WebCore::LinkPreloadResourceClient::triggerEvents): Call LinkLoader's triggerEvents.
+        * loader/LinkPreloadResourceClients.h: Added.
+        (WebCore::LinkPreloadResourceClient::~LinkPreloadResourceClient):
+        (WebCore::LinkPreloadResourceClient::addResource): Add as resource's client.
+        (WebCore::LinkPreloadResourceClient::clearResource): Remove as resource's client and clear ref to resource.
+        (WebCore::LinkPreloadResourceClient::ownedResource): Return ref to resource.
+        * loader/ResourceLoadInfo.cpp:
+        (WebCore::toResourceType): Removed LinkPreload.
+        * loader/SubresourceLoader.cpp:
+        (WebCore::logResourceLoaded): Removed LinkPreload.
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::defaultPriorityForResourceType): Removed LinkPreload.
+        * loader/cache/CachedResource.h: Removed LinkPreload.
+        (WebCore::CachedResource::ignoreForRequestCount): Don't delay window.onload for requests that opted out of that.
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::checkInsecureContent): Removed LinkPreload.
+        (WebCore::CachedResourceLoader::requestResource): Make sure that discovered preload resources do block window.onload.
+        (WebCore::CachedResourceLoader::preload): Make sure that explicitly preloaded subresources can be fetched even if there are parser
+        blocking resources still in flight. Return the preloaded resource.
+        (WebCore::CachedResourceLoader::requestPreload): Make sure that preloaded fonts get requested. Return preloaded resource.
+        (WebCore::createResource): Removed LinkPreload.
+        (WebCore::contentTypeFromResourceType): Removed LinkPreload.
+        (WebCore::CachedResourceLoader::canRequest): Removed LinkPreload.
+        * loader/cache/CachedResourceLoader.h:
+        * platform/network/ResourceRequestBase.h:
+        (WebCore::ResourceRequestBase::ignoreForRequestCount): Get the flag saying if a resource should block window.onload.
+        (WebCore::ResourceRequestBase::setIgnoreForRequestCount): Set the flag saying if a resource should block window.onload.
+
 2016-08-31  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: XHR with text but responseType = "blob" shows blank content
index 73a5341..329aa5b 100644 (file)
                CB38FD571CD21E2A00592A3F /* JSPerformanceEntryCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB38FD551CD21D5B00592A3F /* JSPerformanceEntryCustom.cpp */; };
                CB38FD5A1CD2325800592A3F /* JSPerformanceResourceTiming.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB38FD581CD2314500592A3F /* JSPerformanceResourceTiming.cpp */; };
                CB38FD5B1CD2325B00592A3F /* JSPerformanceResourceTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = CB38FD591CD2314500592A3F /* JSPerformanceResourceTiming.h */; };
+               CB61C7931D755207001ADC7D /* LinkPreloadResourceClients.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBB6B2D11CB7ADC6009EDE1A /* LinkPreloadResourceClients.cpp */; };
                CB8CF0181A9358D4000D510B /* Microtasks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB8CF0151A934B43000D510B /* Microtasks.cpp */; };
+               CBB6B2D41CB7AE51009EDE1A /* LinkPreloadResourceClients.h in Headers */ = {isa = PBXBuildFile; fileRef = CBB6B2D21CB7ADD0009EDE1A /* LinkPreloadResourceClients.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CBC2D22F1CE5B89D00D1880B /* ResourceTimingInformation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBC2D22D1CE5B77400D1880B /* ResourceTimingInformation.cpp */; };
                CBC2D2301CE5B8A100D1880B /* ResourceTimingInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = CBC2D22E1CE5B77D00D1880B /* ResourceTimingInformation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CCC2B51415F613060048CDD6 /* DeviceClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CCC2B51015F613060048CDD6 /* DeviceClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CB38FD581CD2314500592A3F /* JSPerformanceResourceTiming.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPerformanceResourceTiming.cpp; sourceTree = "<group>"; };
                CB38FD591CD2314500592A3F /* JSPerformanceResourceTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPerformanceResourceTiming.h; sourceTree = "<group>"; };
                CB8CF0151A934B43000D510B /* Microtasks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Microtasks.cpp; sourceTree = "<group>"; };
+               CBB6B2D11CB7ADC6009EDE1A /* LinkPreloadResourceClients.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkPreloadResourceClients.cpp; sourceTree = "<group>"; };
+               CBB6B2D21CB7ADD0009EDE1A /* LinkPreloadResourceClients.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkPreloadResourceClients.h; sourceTree = "<group>"; };
                CBC2D22D1CE5B77400D1880B /* ResourceTimingInformation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceTimingInformation.cpp; sourceTree = "<group>"; };
                CBC2D22E1CE5B77D00D1880B /* ResourceTimingInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceTimingInformation.h; sourceTree = "<group>"; };
                CCC2B51015F613060048CDD6 /* DeviceClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceClient.h; sourceTree = "<group>"; };
                                089582540E857A7E00F82C83 /* ImageLoader.h */,
                                98CE4325129E00BD005821DC /* LinkLoader.cpp */,
                                98CE4329129E00E5005821DC /* LinkLoader.h */,
+                               CBB6B2D11CB7ADC6009EDE1A /* LinkPreloadResourceClients.cpp */,
+                               CBB6B2D21CB7ADD0009EDE1A /* LinkPreloadResourceClients.h */,
                                984264EF12D5280A000D88A4 /* LinkLoaderClient.h */,
                                51ABF64C16392E2800132A7A /* LoaderStrategy.cpp */,
                                51E6820F16387302003BBF3C /* LoaderStrategy.h */,
                                1A22464A0CC98DDB00C05240 /* SQLiteDatabase.h in Headers */,
                                7E474E1F12494DC900235364 /* SQLiteDatabaseTracker.h in Headers */,
                                7E474E1E12494DC900235364 /* SQLiteDatabaseTrackerClient.h in Headers */,
+                               CBB6B2D41CB7AE51009EDE1A /* LinkPreloadResourceClients.h in Headers */,
                                B5A684220FFABE9800D24689 /* SQLiteFileSystem.h in Headers */,
                                512BDB4B1C456FFA006494DF /* SQLiteIDBBackingStore.h in Headers */,
                                511EC1301C50ABF50032F983 /* SQLiteIDBCursor.h in Headers */,
                                FE8A674716CDD19E00930BF8 /* SQLStatement.cpp in Sources */,
                                97BC6A4F1505F081001B74AC /* SQLTransaction.cpp in Sources */,
                                FEE1811316C319E800084849 /* SQLTransactionBackend.cpp in Sources */,
+                               CB61C7931D755207001ADC7D /* LinkPreloadResourceClients.cpp in Sources */,
                                97BC6A541505F081001B74AC /* SQLTransactionClient.cpp in Sources */,
                                97BC6A561505F081001B74AC /* SQLTransactionCoordinator.cpp in Sources */,
                                FE36FD1616C7826500F887C1 /* SQLTransactionStateMachine.cpp in Sources */,
index 9bfa908..312f66f 100644 (file)
@@ -68,6 +68,12 @@ static LinkEventSender& linkLoadEventSender()
     return sharedLoadEventSender;
 }
 
+static LinkEventSender& linkErrorEventSender()
+{
+    static NeverDestroyed<LinkEventSender> sharedErrorEventSender(eventNames().errorEvent);
+    return sharedErrorEventSender;
+}
+
 inline HTMLLinkElement::HTMLLinkElement(const QualifiedName& tagName, Document& document, bool createdByParser)
     : HTMLElement(tagName, document)
     , m_linkLoader(*this)
@@ -76,7 +82,7 @@ inline HTMLLinkElement::HTMLLinkElement(const QualifiedName& tagName, Document&
     , m_createdByParser(createdByParser)
     , m_isInShadowTree(false)
     , m_firedLoad(false)
-    , m_loadedSheet(false)
+    , m_loadedResource(false)
     , m_pendingSheetType(Unknown)
 {
     ASSERT(hasTagName(linkTag));
@@ -99,6 +105,7 @@ HTMLLinkElement::~HTMLLinkElement()
         document().authorStyleSheets().removeStyleSheetCandidateNode(*this);
 
     linkLoadEventSender().cancelEvent(*this);
+    linkErrorEventSender().cancelEvent(*this);
 }
 
 void HTMLLinkElement::setDisabledState(bool disabled)
@@ -395,12 +402,13 @@ DOMTokenList& HTMLLinkElement::sizes()
 
 void HTMLLinkElement::linkLoaded()
 {
-    dispatchEvent(Event::create(eventNames().loadEvent, false, false));
+    m_loadedResource = true;
+    linkLoadEventSender().dispatchEventSoon(*this);
 }
 
 void HTMLLinkElement::linkLoadingErrored()
 {
-    dispatchEvent(Event::create(eventNames().errorEvent, false, false));
+    linkErrorEventSender().dispatchEventSoon(*this);
 }
 
 bool HTMLLinkElement::sheetLoaded()
@@ -419,11 +427,11 @@ void HTMLLinkElement::dispatchPendingLoadEvents()
 
 void HTMLLinkElement::dispatchPendingEvent(LinkEventSender* eventSender)
 {
-    ASSERT_UNUSED(eventSender, eventSender == &linkLoadEventSender());
-    if (m_loadedSheet)
-        linkLoaded();
+    ASSERT_UNUSED(eventSender, eventSender == &linkLoadEventSender() || eventSender == &linkErrorEventSender());
+    if (m_loadedResource)
+        dispatchEvent(Event::create(eventNames().loadEvent, false, false));
     else
-        linkLoadingErrored();
+        dispatchEvent(Event::create(eventNames().errorEvent, false, false));
 }
 
 DOMTokenList& HTMLLinkElement::relList()
@@ -437,7 +445,7 @@ void HTMLLinkElement::notifyLoadedSheetAndAllCriticalSubresources(bool errorOccu
 {
     if (m_firedLoad)
         return;
-    m_loadedSheet = !errorOccurred;
+    m_loadedResource = !errorOccurred;
     linkLoadEventSender().dispatchEventSoon(*this);
     m_firedLoad = true;
 }
index 9ee81c2..9b0f694 100644 (file)
@@ -134,7 +134,7 @@ private:
     bool m_createdByParser;
     bool m_isInShadowTree;
     bool m_firedLoad;
-    bool m_loadedSheet;
+    bool m_loadedResource;
 
     PendingSheetType m_pendingSheetType;
 
index f2cba00..4d4ba84 100644 (file)
@@ -69,7 +69,7 @@ void HTMLResourcePreloader::preload(std::unique_ptr<PreloadRequest> preload)
         return;
 
     CachedResourceRequest request = preload->resourceRequest(m_document);
-    m_document.cachedResourceLoader().preload(preload->resourceType(), request, preload->charset());
+    m_document.cachedResourceLoader().preload(preload->resourceType(), request, preload->charset(), CachedResourceLoader::ImplicitPreload);
 }
 
 
index 84818eb..6bd3891 100644 (file)
@@ -43,6 +43,7 @@
 #include "Frame.h"
 #include "FrameLoaderClient.h"
 #include "FrameView.h"
+#include "LinkPreloadResourceClients.h"
 #include "LinkRelAttribute.h"
 #include "RuntimeEnabledFeatures.h"
 #include "Settings.h"
@@ -52,8 +53,7 @@ namespace WebCore {
 
 LinkLoader::LinkLoader(LinkLoaderClient& client)
     : m_client(client)
-    , m_linkLoadTimer(*this, &LinkLoader::linkLoadTimerFired)
-    , m_linkLoadingErrorTimer(*this, &LinkLoader::linkLoadingErrorTimerFired)
+    , m_weakPtrFactory(this)
 {
 }
 
@@ -61,26 +61,23 @@ LinkLoader::~LinkLoader()
 {
     if (m_cachedLinkResource)
         m_cachedLinkResource->removeClient(this);
+    if (m_preloadResourceClient)
+        m_preloadResourceClient->clear();
 }
 
-void LinkLoader::linkLoadTimerFired()
+void LinkLoader::triggerEvents(const CachedResource* resource)
 {
-    m_client.linkLoaded();
-}
-
-void LinkLoader::linkLoadingErrorTimerFired()
-{
-    m_client.linkLoadingErrored();
+    if (resource->errorOccurred())
+        m_client.linkLoadingErrored();
+    else
+        m_client.linkLoaded();
 }
 
 void LinkLoader::notifyFinished(CachedResource* resource)
 {
     ASSERT_UNUSED(resource, m_cachedLinkResource.get() == resource);
 
-    if (m_cachedLinkResource->errorOccurred())
-        m_linkLoadingErrorTimer.startOneShot(0);
-    else 
-        m_linkLoadTimer.startOneShot(0);
+    triggerEvents(m_cachedLinkResource.get());
 
     m_cachedLinkResource->removeClient(this);
     m_cachedLinkResource = nullptr;
@@ -89,7 +86,7 @@ void LinkLoader::notifyFinished(CachedResource* resource)
 Optional<CachedResource::Type> LinkLoader::resourceTypeFromAsAttribute(const String& as)
 {
     if (as.isEmpty())
-        return CachedResource::LinkPreload;
+        return CachedResource::RawResource;
     if (equalLettersIgnoringASCIICase(as, "image"))
         return CachedResource::ImageResource;
     if (equalLettersIgnoringASCIICase(as, "script"))
@@ -107,7 +104,38 @@ Optional<CachedResource::Type> LinkLoader::resourceTypeFromAsAttribute(const Str
     return Nullopt;
 }
 
-static void preloadIfNeeded(const LinkRelAttribute& relAttribute, const URL& href, Document& document, const String& as, const String& crossOriginMode)
+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:
+    case CachedResource::SVGFontResource:
+    case CachedResource::SVGDocumentResource:
+    case CachedResource::XSLStyleSheet:
+#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;
+}
+
+void LinkLoader::preloadIfNeeded(const LinkRelAttribute& relAttribute, const URL& href, Document& document, const String& as, const String& crossOriginMode)
 {
     if (!document.loader() || !relAttribute.isLinkPreload)
         return;
@@ -120,10 +148,12 @@ static void preloadIfNeeded(const LinkRelAttribute& relAttribute, const URL& hre
     auto type = LinkLoader::resourceTypeFromAsAttribute(as);
     if (!type) {
         document.addConsoleMessage(MessageSource::Other, MessageLevel::Error, String("<link rel=preload> must have a valid `as` value"));
+        m_client.linkLoadingErrored();
         return;
     }
 
     ResourceRequest resourceRequest(document.completeURL(href));
+    resourceRequest.setIgnoreForRequestCount(true);
     CachedResourceRequest linkRequest(resourceRequest, CachedResource::defaultPriorityForResourceType(type.value()));
     linkRequest.setInitiator("link");
 
@@ -133,7 +163,10 @@ static void preloadIfNeeded(const LinkRelAttribute& relAttribute, const URL& hre
         updateRequestForAccessControl(linkRequest.mutableResourceRequest(), *document.securityOrigin(), allowCredentials);
     }
     linkRequest.setForPreload(true);
-    document.cachedResourceLoader().preload(type.value(), linkRequest, emptyString());
+    CachedResourceHandle<CachedResource> cachedLinkResource = document.cachedResourceLoader().preload(type.value(), linkRequest, emptyString(), CachedResourceLoader::ExplicitPreload);
+
+    if (cachedLinkResource)
+        m_preloadResourceClient = createLinkPreloadResourceClient(*cachedLinkResource, *this, type.value());
 }
 
 bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const URL& href, const String& as, const String& crossOrigin, Document& document)
index eb05121..fe70d1e 100644 (file)
 #include "CachedResourceClient.h"
 #include "CachedResourceHandle.h"
 #include "LinkLoaderClient.h"
-#include "Timer.h"
+
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 
 class Document;
 class URL;
+class LinkPreloadResourceClient;
 
 struct LinkRelAttribute;
 
@@ -53,16 +55,17 @@ public:
     bool loadLink(const LinkRelAttribute&, const URL&, const String& as, const String& crossOrigin, Document&);
     static Optional<CachedResource::Type> resourceTypeFromAsAttribute(const String& as);
 
+    WeakPtr<LinkLoader> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+    void triggerEvents(const CachedResource*);
+
 private:
     void notifyFinished(CachedResource*) override;
-
-    void linkLoadTimerFired();
-    void linkLoadingErrorTimerFired();
+    void preloadIfNeeded(const LinkRelAttribute&, const URL& href, Document&, const String& as, const String& crossOriginMode);
 
     LinkLoaderClient& m_client;
     CachedResourceHandle<CachedResource> m_cachedLinkResource;
-    Timer m_linkLoadTimer;
-    Timer m_linkLoadingErrorTimer;
+    std::unique_ptr<LinkPreloadResourceClient> m_preloadResourceClient;
+    WeakPtrFactory<LinkLoader> m_weakPtrFactory;
 };
     
 }
diff --git a/Source/WebCore/loader/LinkPreloadResourceClients.cpp b/Source/WebCore/loader/LinkPreloadResourceClients.cpp
new file mode 100644 (file)
index 0000000..fe7ecb5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 The Chromium Authors. All rights reserved.
+ * Copyright (C) 2016 Akamai Technologies Inc. All rights reserved.
+ *
+ * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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 "LinkPreloadResourceClients.h"
+
+#include "LinkLoader.h"
+
+namespace WebCore {
+
+LinkPreloadResourceClient::LinkPreloadResourceClient(LinkLoader& loader, CachedResource& resource)
+{
+    m_loader = loader.createWeakPtr();
+    m_resource = &resource;
+}
+
+void LinkPreloadResourceClient::triggerEvents(const CachedResource* resource)
+{
+    if (m_loader)
+        m_loader->triggerEvents(resource);
+}
+
+}
diff --git a/Source/WebCore/loader/LinkPreloadResourceClients.h b/Source/WebCore/loader/LinkPreloadResourceClients.h
new file mode 100644 (file)
index 0000000..9273d69
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2016 The Chromium Authors. All rights reserved.
+ * Copyright (C) 2016 Akamai Technologies Inc. All rights reserved.
+ *
+ * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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 "CachedCSSStyleSheet.h"
+#include "CachedFont.h"
+#include "CachedFontClient.h"
+#include "CachedImage.h"
+#include "CachedImageClient.h"
+#include "CachedRawResource.h"
+#include "CachedResourceLoader.h"
+#include "CachedScript.h"
+#include "CachedStyleSheetClient.h"
+
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class LinkLoader;
+
+class LinkPreloadResourceClient {
+public:
+    virtual ~LinkPreloadResourceClient() { }
+
+    void triggerEvents(const CachedResource*);
+
+    virtual void clear() = 0;
+
+protected:
+
+    LinkPreloadResourceClient(LinkLoader&, CachedResource&);
+
+    void addResource(CachedResourceClient* client)
+    {
+        m_resource->addClient(client);
+    }
+
+    void clearResource(CachedResourceClient* client)
+    {
+        if (m_resource)
+            m_resource->removeClient(client);
+        m_resource = nullptr;
+    }
+
+    CachedResource* ownedResource() { return m_resource.get(); }
+
+private:
+    WeakPtr<LinkLoader> m_loader;
+    CachedResourceHandle<CachedResource> m_resource;
+};
+
+class LinkPreloadScriptResourceClient: public LinkPreloadResourceClient, CachedResourceClient {
+public:
+    static std::unique_ptr<LinkPreloadScriptResourceClient> create(LinkLoader& loader, CachedScript& resource)
+    {
+        return std::unique_ptr<LinkPreloadScriptResourceClient>(new LinkPreloadScriptResourceClient(loader, resource));
+    }
+
+    virtual ~LinkPreloadScriptResourceClient() { }
+
+
+    void notifyFinished(CachedResource* resource) override
+    {
+        ASSERT(ownedResource() == resource);
+        triggerEvents(resource);
+    }
+
+    void clear() override { clearResource(this); }
+
+private:
+    LinkPreloadScriptResourceClient(LinkLoader& loader, CachedScript& resource)
+        : LinkPreloadResourceClient(loader, resource)
+    {
+        addResource(this);
+    }
+};
+
+class LinkPreloadStyleResourceClient: public LinkPreloadResourceClient, public CachedStyleSheetClient {
+public:
+    static std::unique_ptr<LinkPreloadStyleResourceClient> create(LinkLoader& loader, CachedCSSStyleSheet& resource)
+    {
+        return std::unique_ptr<LinkPreloadStyleResourceClient>(new LinkPreloadStyleResourceClient(loader, resource));
+    }
+
+    virtual ~LinkPreloadStyleResourceClient() { }
+
+    void setCSSStyleSheet(const String&, const URL&, const String&, const CachedCSSStyleSheet* resource) override
+    {
+        ASSERT(ownedResource() == resource);
+        triggerEvents(resource);
+    }
+
+    void clear() override { clearResource(this); }
+
+private:
+    LinkPreloadStyleResourceClient(LinkLoader& loader, CachedCSSStyleSheet& resource)
+        : LinkPreloadResourceClient(loader, resource)
+    {
+        addResource(this);
+    }
+};
+
+class LinkPreloadImageResourceClient: public LinkPreloadResourceClient, public CachedImageClient {
+public:
+    static std::unique_ptr<LinkPreloadImageResourceClient> create(LinkLoader& loader, CachedImage& resource)
+    {
+        return std::unique_ptr<LinkPreloadImageResourceClient>(new LinkPreloadImageResourceClient(loader, resource));
+    }
+
+    virtual ~LinkPreloadImageResourceClient() { }
+
+    void notifyFinished(CachedResource* resource) override
+    {
+        ASSERT(ownedResource() == resource);
+        triggerEvents(resource);
+    }
+
+    void clear() override { clearResource(this); }
+
+private:
+    LinkPreloadImageResourceClient(LinkLoader& loader, CachedImage& resource)
+        : LinkPreloadResourceClient(loader, dynamic_cast<CachedResource&>(resource))
+    {
+        addResource(this);
+    }
+};
+
+class LinkPreloadFontResourceClient: public LinkPreloadResourceClient, public CachedFontClient {
+public:
+    static std::unique_ptr<LinkPreloadFontResourceClient> create(LinkLoader& loader, CachedFont& resource)
+    {
+        return std::unique_ptr<LinkPreloadFontResourceClient>(new LinkPreloadFontResourceClient(loader, resource));
+    }
+
+    virtual ~LinkPreloadFontResourceClient() { }
+
+    void fontLoaded(CachedFont& resource) override
+    {
+        ASSERT(ownedResource() == &resource);
+        triggerEvents(&resource);
+    }
+
+    void clear() override { clearResource(this); }
+
+private:
+    LinkPreloadFontResourceClient(LinkLoader& loader, CachedFont& resource)
+        : LinkPreloadResourceClient(loader, resource)
+    {
+        addResource(this);
+    }
+};
+
+class LinkPreloadRawResourceClient: public LinkPreloadResourceClient, public CachedRawResourceClient {
+public:
+    static std::unique_ptr<LinkPreloadRawResourceClient> create(LinkLoader& loader, CachedRawResource& resource)
+    {
+        return std::unique_ptr<LinkPreloadRawResourceClient>(new LinkPreloadRawResourceClient(loader, resource));
+    }
+
+    virtual ~LinkPreloadRawResourceClient() { }
+
+    void notifyFinished(CachedResource* resource) override
+    {
+        ASSERT(ownedResource() == resource);
+        triggerEvents(resource);
+    }
+
+    void clear() override { clearResource(this); }
+
+private:
+    LinkPreloadRawResourceClient(LinkLoader& loader, CachedRawResource& resource)
+        : LinkPreloadResourceClient(loader, resource)
+    {
+        addResource(this);
+    }
+};
+
+}
index 8348b64..a8beca5 100644 (file)
@@ -56,7 +56,6 @@ ResourceType toResourceType(CachedResource::Type type)
         return ResourceType::Font;
 
     case CachedResource::MediaResource:
-    case CachedResource::LinkPreload:
     case CachedResource::RawResource:
         return ResourceType::Raw;
 
index 2bc577c..50b7444 100644 (file)
@@ -390,7 +390,6 @@ static void logResourceLoaded(Frame* frame, CachedResource::Type type)
     case CachedResource::SVGDocumentResource:
         resourceType = DiagnosticLoggingKeys::svgDocumentKey();
         break;
-    case CachedResource::LinkPreload:
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkPrefetch:
     case CachedResource::LinkSubresource:
index 820347c..9de41f2 100644 (file)
@@ -87,8 +87,6 @@ ResourceLoadPriority CachedResource::defaultPriorityForResourceType(Type type)
 #endif
     case CachedResource::SVGDocumentResource:
         return ResourceLoadPriority::Low;
-    case CachedResource::LinkPreload:
-        return ResourceLoadPriority::Low;
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkPrefetch:
         return ResourceLoadPriority::VeryLow;
index a58197d..764916d 100644 (file)
@@ -76,7 +76,6 @@ public:
 #if ENABLE(XSLT)
         , XSLStyleSheet
 #endif
-        , LinkPreload
 #if ENABLE(LINK_PREFETCH)
         , LinkPrefetch
         , LinkSubresource
@@ -167,7 +166,8 @@ public:
     bool isMainOrMediaOrRawResource() const { return type() == MainResource || type() == MediaResource || type() == RawResource; }
     bool ignoreForRequestCount() const
     {
-        return type() == MainResource
+        return m_resourceRequest.ignoreForRequestCount()
+            || type() == MainResource
 #if ENABLE(LINK_PREFETCH)
             || type() == LinkPrefetch
             || type() == LinkSubresource
index 552e6fe..6104886 100644 (file)
@@ -107,8 +107,6 @@ static CachedResource* createResource(CachedResource::Type type, ResourceRequest
     case CachedResource::XSLStyleSheet:
         return new CachedXSLStyleSheet(request, sessionID);
 #endif
-    case CachedResource::LinkPreload:
-        return new CachedResource(request, CachedResource::LinkPreload, sessionID);
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkPrefetch:
         return new CachedResource(request, CachedResource::LinkPrefetch, sessionID);
@@ -316,7 +314,6 @@ static MixedContentChecker::ContentType contentTypeFromResourceType(CachedResour
         return MixedContentChecker::ContentType::Active;
 #endif
 
-    case CachedResource::LinkPreload:
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkPrefetch:
     case CachedResource::LinkSubresource:
@@ -361,8 +358,7 @@ bool CachedResourceLoader::checkInsecureContent(CachedResource::Type type, const
 #if ENABLE(SVG_FONTS)
     case CachedResource::SVGFontResource:
 #endif
-    case CachedResource::FontResource:
-    case CachedResource::LinkPreload: {
+    case CachedResource::FontResource: {
         // These resources can corrupt only the frame's pixels.
         if (Frame* f = frame()) {
             Frame& topFrame = f->tree().top();
@@ -412,7 +408,6 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const URL& url,
     case CachedResource::MediaResource:
     case CachedResource::FontResource:
     case CachedResource::RawResource:
-    case CachedResource::LinkPreload:
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkPrefetch:
     case CachedResource::LinkSubresource:
@@ -468,8 +463,6 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const URL& url,
     }
     case CachedResource::MainResource:
     case CachedResource::RawResource:
-    // FIXME: Preload should be subject to connect-src.
-    case CachedResource::LinkPreload:
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkPrefetch:
     case CachedResource::LinkSubresource:
@@ -664,6 +657,11 @@ CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(Cache
     if (!request.forPreload() || policy != Use)
         resource->setLoadPriority(request.priority());
 
+    if (!request.forPreload() && resource->loader() && resource->resourceRequest().ignoreForRequestCount()) {
+        resource->resourceRequest().setIgnoreForRequestCount(false);
+        incrementRequestCount(*resource);
+    }
+
     if ((policy != Use || resource->stillNeedsLoad()) && CachedResourceRequest::NoDefer == request.defer()) {
         resource->load(*this, request.options());
 
@@ -1063,7 +1061,7 @@ void CachedResourceLoader::decrementRequestCount(const CachedResource& resource)
     ASSERT(m_requestCount > -1);
 }
 
-void CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest& request, const String& charset)
+CachedResourceHandle<CachedResource> CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest& request, const String& charset, PreloadType preloadType)
 {
     // We always preload resources on iOS. See <https://bugs.webkit.org/show_bug.cgi?id=91276>.
     // FIXME: We should consider adding a setting to toggle aggressive preloading behavior as opposed
@@ -1071,15 +1069,17 @@ void CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequ
 #if !PLATFORM(IOS)
     bool hasRendering = m_document->bodyOrFrameset() && m_document->renderView();
     bool canBlockParser = type == CachedResource::Script || type == CachedResource::CSSStyleSheet;
-    if (!hasRendering && !canBlockParser) {
+    if (!hasRendering && !canBlockParser && preloadType == ImplicitPreload) {
         // Don't preload subresources that can't block the parser before we have something to draw.
         // This helps prevent preloads from delaying first display when bandwidth is limited.
         PendingPreload pendingPreload = { type, request, charset };
         m_pendingPreloads.append(pendingPreload);
-        return;
+        return nullptr;
     }
+#else
+    UNUSED_PARAM(preloadType);
 #endif
-    requestPreload(type, request, charset);
+    return requestPreload(type, request, charset);
 }
 
 void CachedResourceLoader::checkForPendingPreloads() 
@@ -1104,7 +1104,7 @@ void CachedResourceLoader::checkForPendingPreloads()
     m_pendingPreloads.clear();
 }
 
-void CachedResourceLoader::requestPreload(CachedResource::Type type, CachedResourceRequest& request, const String& charset)
+CachedResourceHandle<CachedResource> CachedResourceLoader::requestPreload(CachedResource::Type type, CachedResourceRequest& request, const String& charset)
 {
     String encoding;
     if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet)
@@ -1115,7 +1115,10 @@ void CachedResourceLoader::requestPreload(CachedResource::Type type, CachedResou
 
     CachedResourceHandle<CachedResource> resource = requestResource(type, request);
     if (!resource || (m_preloads && m_preloads->contains(resource.get())))
-        return;
+        return nullptr;
+    // Fonts need special treatment since just creating the resource doesn't trigger a load.
+    if (type == CachedResource::FontResource)
+        downcast<CachedFont>(resource.get())->beginLoadIfNeeded(*this);
     resource->increasePreloadCount();
 
     if (!m_preloads)
@@ -1125,6 +1128,7 @@ void CachedResourceLoader::requestPreload(CachedResource::Type type, CachedResou
 #if PRELOAD_DEBUG
     printf("PRELOADING %s\n",  resource->url().latin1().data());
 #endif
+    return resource;
 }
 
 bool CachedResourceLoader::isPreloaded(const String& urlString) const
index 017744d..7660f4f 100644 (file)
@@ -130,7 +130,8 @@ public:
     WEBCORE_EXPORT bool isPreloaded(const String& urlString) const;
     void clearPreloads();
     void clearPendingPreloads();
-    void preload(CachedResource::Type, CachedResourceRequest&, const String& charset);
+    enum PreloadType { ImplicitPreload, ExplicitPreload };
+    CachedResourceHandle<CachedResource> preload(CachedResource::Type, CachedResourceRequest&, const String& charset, PreloadType);
     void checkForPendingPreloads();
     void printPreloadStats();
 
@@ -150,7 +151,7 @@ private:
     CachedResourceHandle<CachedResource> requestResource(CachedResource::Type, CachedResourceRequest&);
     CachedResourceHandle<CachedResource> revalidateResource(const CachedResourceRequest&, CachedResource*);
     CachedResourceHandle<CachedResource> loadResource(CachedResource::Type, CachedResourceRequest&);
-    void requestPreload(CachedResource::Type, CachedResourceRequest&, const String& charset);
+    CachedResourceHandle<CachedResource> requestPreload(CachedResource::Type, CachedResourceRequest&, const String& charset);
 
     enum RevalidationPolicy { Use, Revalidate, Reload, Load };
     RevalidationPolicy determineRevalidationPolicy(CachedResource::Type, CachedResourceRequest&, CachedResource* existingResource) const;
index d3ac391..6ff6f0c 100644 (file)
@@ -148,6 +148,10 @@ public:
     bool hiddenFromInspector() const { return m_hiddenFromInspector; }
     void setHiddenFromInspector(bool hiddenFromInspector) { m_hiddenFromInspector = hiddenFromInspector; }
 
+    // Whether this request should impact request counting and delay window.onload.
+    bool ignoreForRequestCount() const { return m_ignoreForRequestCount; }
+    void setIgnoreForRequestCount(bool ignoreForRequestCount) { m_ignoreForRequestCount = ignoreForRequestCount; }
+
     enum class Requester { Unspecified, Main, XHR, Media };
     Requester requester() const { return m_requester; }
     void setRequester(Requester requester) { m_requester = requester; }
@@ -214,6 +218,7 @@ protected:
     bool m_reportLoadTiming { false };
     bool m_reportRawHeaders { false };
     bool m_hiddenFromInspector { false };
+    bool m_ignoreForRequestCount { false };
     ResourceLoadPriority m_priority { ResourceLoadPriority::Low };
     Requester m_requester { Requester::Unspecified };
 
index ceac203..ad8bcc8 100644 (file)
@@ -1,3 +1,13 @@
+2016-08-31  Yoav Weiss  <yoav@yoav.ws>
+
+        Add event support for link preload.
+        https://bugs.webkit.org/show_bug.cgi?id=158466
+
+        Reviewed by Alex Christensen.
+
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+        (WebKit::maximumBufferingTime): Removed LinkPreload.
+
 2016-08-31  Alex Christensen  <achristensen@webkit.org>
 
         Add runtime flag for using URLParser
index afccd1e..e204e63 100644 (file)
@@ -110,7 +110,6 @@ static std::chrono::milliseconds maximumBufferingTime(CachedResource* resource)
     case CachedResource::MainResource:
     case CachedResource::RawResource:
     case CachedResource::SVGDocumentResource:
-    case CachedResource::LinkPreload:
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkPrefetch:
     case CachedResource::LinkSubresource: