WebCore: https://bugs.webkit.org/show_bug.cgi?id=50758
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Dec 2010 19:49:35 +0000 (19:49 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Dec 2010 19:49:35 +0000 (19:49 +0000)
<rdar://problem/8722094>
Defer loading print stylesheets

Reviewed by Alexey Proskuryakov.

- Make preload scanner skip stylesheets with non-screen media types.
- Make it possible to specify non-default load priority from the client.
- Use this mechanism to load print stylesheets using very low priority so they get loaded after everything else.
- Move default priority code from Loader to CachedResource.
- Move ResourceLoadScheduler::Priority enum to a separate file (as ResourceLoadPriority).
- Add a way to make ResourceLoadScheduler load resources one at the time so the above functionality can be tested reliably.

Tests: http/tests/local/link-stylesheet-load-order-preload.html
       http/tests/local/link-stylesheet-load-order.html

* WebCore.exp.in:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSImageValue.cpp:
(WebCore::CSSImageValue::cachedImage):
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::process):
* html/parser/HTMLPreloadScanner.cpp:
(WebCore::HTMLNames::PreloadTask::PreloadTask):
(WebCore::HTMLNames::PreloadTask::processAttributes):
(WebCore::HTMLNames::PreloadTask::relAttributeIsStyleSheet):
(WebCore::HTMLNames::PreloadTask::linkMediaAttributeIsScreen):
(WebCore::HTMLNames::PreloadTask::preload):
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::loadRequest):
* loader/ResourceLoadPriority.h: Added.
* loader/ResourceLoadScheduler.cpp:
(WebCore::ResourceLoadScheduler::ResourceLoadScheduler):
(WebCore::ResourceLoadScheduler::scheduleSubresourceLoad):
(WebCore::ResourceLoadScheduler::schedulePluginStreamLoad):
(WebCore::ResourceLoadScheduler::scheduleLoad):
(WebCore::ResourceLoadScheduler::servePendingRequests):
(WebCore::ResourceLoadScheduler::HostInformation::~HostInformation):
(WebCore::ResourceLoadScheduler::HostInformation::schedule):
(WebCore::ResourceLoadScheduler::HostInformation::remove):
(WebCore::ResourceLoadScheduler::HostInformation::hasRequests):
(WebCore::ResourceLoadScheduler::HostInformation::limitRequests):
* loader/ResourceLoadScheduler.h:
(WebCore::ResourceLoadScheduler::isSerialLoadingEnabled):
(WebCore::ResourceLoadScheduler::setSerialLoadingEnabled):
(WebCore::ResourceLoadScheduler::HostInformation::requestsPending):
* loader/cache/CachedResource.cpp:
(WebCore::defaultPriorityForResourceType):
(WebCore::CachedResource::CachedResource):
* loader/cache/CachedResource.h:
(WebCore::CachedResource::loadPriority):
(WebCore::CachedResource::setLoadPriority):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::requestCSSStyleSheet):
(WebCore::CachedResourceLoader::requestResource):
(WebCore::CachedResourceLoader::requestPreload):
* loader/cache/CachedResourceLoader.h:
* loader/cache/MemoryCache.cpp:
(WebCore::MemoryCache::requestResource):
* loader/cache/MemoryCache.h:
* loader/loader.cpp:
(WebCore::Loader::load):

WebKit/mac: https://bugs.webkit.org/show_bug.cgi?id=50758
<rdar://problem/8722094>
Defer loading print stylesheets

Reviewed by Alexey Proskuryakov.

Expose SPI for DRT for making resources load serially. This is useful for testing resource load order.

* WebView/WebView.mm:
(+[WebView _setLoadResourcesSerially:forHost:]):
* WebView/WebViewPrivate.h:

WebKitTools: Add setSerializeHTTPLoads function to allow testing resource load order on OS X.
https://bugs.webkit.org/show_bug.cgi?id=50758

Reviewed by Alexey Proskuryakov.

* DumpRenderTree/LayoutTestController.cpp:
(setSerializeHTTPLoadsCallback):
(LayoutTestController::staticFunctions):
* DumpRenderTree/LayoutTestController.h:
* DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
(LayoutTestController::setSerializeHTTPLoads):
* DumpRenderTree/mac/DumpRenderTree.mm:
(resetDefaultsToConsistentValues):
* DumpRenderTree/mac/LayoutTestControllerMac.mm:
(LayoutTestController::setSerializeHTTPLoads):
* DumpRenderTree/win/LayoutTestControllerWin.cpp:
(LayoutTestController::setSerializeHTTPLoads):

LayoutTests: https://bugs.webkit.org/show_bug.cgi?id=50758
<rdar://problem/8722094>
Defer loading print stylesheets

Reviewed by Alexey Proskuryakov.

Test load ordering.

* http/tests/local/link-stylesheet-load-order-expected.txt: Added.
* http/tests/local/link-stylesheet-load-order-preload-expected.txt: Added.
* http/tests/local/link-stylesheet-load-order-preload.html: Added.
* http/tests/local/link-stylesheet-load-order.html: Added.

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

36 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/local/link-stylesheet-load-order-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/local/link-stylesheet-load-order-preload-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/local/link-stylesheet-load-order-preload.html [new file with mode: 0644]
LayoutTests/http/tests/local/link-stylesheet-load-order.html [new file with mode: 0644]
LayoutTests/platform/win/Skipped
WebCore/ChangeLog
WebCore/WebCore.exp.in
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/css/CSSImageValue.cpp
WebCore/html/HTMLLinkElement.cpp
WebCore/html/parser/HTMLPreloadScanner.cpp
WebCore/loader/DocumentThreadableLoader.cpp
WebCore/loader/ResourceLoadPriority.h [new file with mode: 0644]
WebCore/loader/ResourceLoadScheduler.cpp
WebCore/loader/ResourceLoadScheduler.h
WebCore/loader/cache/CachedResource.cpp
WebCore/loader/cache/CachedResource.h
WebCore/loader/cache/CachedResourceLoader.cpp
WebCore/loader/cache/CachedResourceLoader.h
WebCore/loader/cache/MemoryCache.cpp
WebCore/loader/cache/MemoryCache.h
WebCore/loader/loader.cpp
WebKit/mac/ChangeLog
WebKit/mac/WebView/WebView.mm
WebKit/mac/WebView/WebViewPrivate.h
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/LayoutTestController.cpp
WebKitTools/DumpRenderTree/LayoutTestController.h
WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp

index e045f40..84116f9 100644 (file)
@@ -1,3 +1,18 @@
+2010-12-09  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        https://bugs.webkit.org/show_bug.cgi?id=50758
+        <rdar://problem/8722094> 
+        Defer loading print stylesheets
+        
+        Test load ordering.
+
+        * http/tests/local/link-stylesheet-load-order-expected.txt: Added.
+        * http/tests/local/link-stylesheet-load-order-preload-expected.txt: Added.
+        * http/tests/local/link-stylesheet-load-order-preload.html: Added.
+        * http/tests/local/link-stylesheet-load-order.html: Added.
+
 2010-12-13  Justin Schuh  <jschuh@chromium.org>
 
         Reviewed by Dimitri Glazkov.
diff --git a/LayoutTests/http/tests/local/link-stylesheet-load-order-expected.txt b/LayoutTests/http/tests/local/link-stylesheet-load-order-expected.txt
new file mode 100644 (file)
index 0000000..67cfb6d
--- /dev/null
@@ -0,0 +1,28 @@
+ Test stylesheet load scheduling. Resource loads for screen stylesheets should be scheduled first, others should be scheduled last.
+Resource requests:
+
+
+no-media.css
+media-empty.css
+media-all.css
+media-screen.css
+media-screen-query-success.css
+media-braille-screen.css
+media-screen-query-fail.css
+no-media-2.css
+media-empty-2.css
+media-all-2.css
+media-screen-2.css
+media-screen-query-success-2.css
+media-braille-screen-2.css
+media-screen-query-fail-2.css
+script.js
+image.jpg
+media-print.css
+media-aural.css
+media-braille.css
+median-handheld.css
+media-projection.css
+media-tty.css
+media-tv.css
+media-print-2.css
diff --git a/LayoutTests/http/tests/local/link-stylesheet-load-order-preload-expected.txt b/LayoutTests/http/tests/local/link-stylesheet-load-order-preload-expected.txt
new file mode 100644 (file)
index 0000000..6a3df6a
--- /dev/null
@@ -0,0 +1,29 @@
+ Test stylesheet load scheduling with preload scanner. Resource loads for screen stylesheets should be scheduled first, others should be scheduled last.
+Resource requests:
+
+
+script.js
+no-media.css
+media-empty.css
+media-all.css
+media-screen.css
+media-braille-screen.css
+no-media-2.css
+media-empty-2.css
+media-all-2.css
+media-screen-2.css
+media-braille-screen-2.css
+media-screen-query-success.css
+media-screen-query-fail.css
+media-screen-query-success-2.css
+media-screen-query-fail-2.css
+script-2.js
+image.jpg
+media-print.css
+media-aural.css
+media-braille.css
+median-handheld.css
+media-projection.css
+media-tty.css
+media-tv.css
+media-print-2.css
diff --git a/LayoutTests/http/tests/local/link-stylesheet-load-order-preload.html b/LayoutTests/http/tests/local/link-stylesheet-load-order-preload.html
new file mode 100644 (file)
index 0000000..ff10f7a
--- /dev/null
@@ -0,0 +1,81 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <script>
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+        // Prevent networking layer from reordering loads.
+        if (layoutTestController.setSerializeHTTPLoads)
+            layoutTestController.setSerializeHTTPLoads();
+    }
+
+    function CallCommand(cmd)
+    {
+     try {
+         var req = new XMLHttpRequest;
+         req.open("GET", "http://127.0.0.1:8000/resources/network-simulator.php?command=" + cmd, false);
+         req.send(null);
+         return req.responseText;
+     } catch (ex) {
+         return "";
+     }
+    }
+
+    function endTest()
+    {
+        getResourceLog();
+        CallCommand("clear-resource-request-log");
+
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+    }
+
+    function getResourceLog()
+    {
+        var log = CallCommand("get-resource-request-log");
+        var logLines = log.split('\n');
+        document.getElementById('result').innerText = logLines.join('\n');
+    }
+
+    CallCommand("start-resource-request-log");
+    window.addEventListener('load', endTest, false);
+  </script>
+  
+  <!-- This will trigger the preload scanner -->
+  <script src="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=script.js"></script>
+
+  <link rel=stylesheet href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=no-media.css">
+  <link rel=stylesheet media="" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-empty.css">
+  <link rel=stylesheet media="all" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-all.css">
+  <link rel=stylesheet media="print" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-print.css">
+  <link rel=stylesheet media="screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen.css">
+  <link rel=stylesheet media="screen and (min-width: 1px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-success.css">
+  <link rel=stylesheet media="braille, screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-braille-screen.css">
+  <link rel=stylesheet media="screen and (min-width: 1000000px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-fail.css">
+  <link rel=stylesheet media="aural" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-aural.css">
+  <link rel=stylesheet media="braille" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-braille.css">
+  <link rel=stylesheet media="handheld" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=median-handheld.css">
+  <link rel=stylesheet media="projection" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-projection.css">
+  <link rel=stylesheet media="tty" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-tty.css">
+  <link rel=stylesheet media="tv" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-tv.css">
+  <link rel=stylesheet href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=no-media-2.css">
+  <link rel=stylesheet media="" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-empty-2.css">
+  <link rel=stylesheet media="all" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-all-2.css">
+  <link rel=stylesheet media="print" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-print-2.css">
+  <link rel=stylesheet media="screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-2.css">
+  <link rel=stylesheet media="screen and (min-width: 1px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-success-2.css">
+  <link rel=stylesheet media="braille, screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-braille-screen-2.css">
+  <link rel=stylesheet media="screen and (min-width: 1000000px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-fail-2.css">
+  
+</head>
+<body>
+  <img src="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=image.jpg">
+  <script src="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=script-2.js"></script>
+
+  Test stylesheet load scheduling with preload scanner. Resource loads for screen stylesheets should be scheduled first, others should be scheduled last.
+
+  <h2>Resource requests:</h2>
+  <pre id="result">Request log goes here in DRT</pre>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/local/link-stylesheet-load-order.html b/LayoutTests/http/tests/local/link-stylesheet-load-order.html
new file mode 100644 (file)
index 0000000..310c75b
--- /dev/null
@@ -0,0 +1,78 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <script>
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+        // Prevent networking layer from reordering loads.
+        if (layoutTestController.setSerializeHTTPLoads)
+            layoutTestController.setSerializeHTTPLoads();
+    }
+
+    function CallCommand(cmd)
+    {
+     try {
+         var req = new XMLHttpRequest;
+         req.open("GET", "http://127.0.0.1:8000/resources/network-simulator.php?command=" + cmd, false);
+         req.send(null);
+         return req.responseText;
+     } catch (ex) {
+         return "";
+     }
+    }
+
+    function endTest()
+    {
+        getResourceLog();
+        CallCommand("clear-resource-request-log");
+
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+    }
+
+    function getResourceLog()
+    {
+        var log = CallCommand("get-resource-request-log");
+        var logLines = log.split('\n');
+        document.getElementById('result').innerText = logLines.join('\n');
+    }
+
+    CallCommand("start-resource-request-log");
+    window.addEventListener('load', endTest, false);
+  </script>
+
+  <link rel=stylesheet href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=no-media.css">
+  <link rel=stylesheet media="" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-empty.css">
+  <link rel=stylesheet media="all" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-all.css">
+  <link rel=stylesheet media="print" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-print.css">
+  <link rel=stylesheet media="screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen.css">
+  <link rel=stylesheet media="screen and (min-width: 1px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-success.css">
+  <link rel=stylesheet media="braille, screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-braille-screen.css">
+  <link rel=stylesheet media="screen and (min-width: 1000000px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-fail.css">
+  <link rel=stylesheet media="aural" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-aural.css">
+  <link rel=stylesheet media="braille" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-braille.css">
+  <link rel=stylesheet media="handheld" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=median-handheld.css">
+  <link rel=stylesheet media="projection" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-projection.css">
+  <link rel=stylesheet media="tty" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-tty.css">
+  <link rel=stylesheet media="tv" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-tv.css">
+  <link rel=stylesheet href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=no-media-2.css">
+  <link rel=stylesheet media="" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-empty-2.css">
+  <link rel=stylesheet media="all" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-all-2.css">
+  <link rel=stylesheet media="print" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-print-2.css">
+  <link rel=stylesheet media="screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-2.css">
+  <link rel=stylesheet media="screen and (min-width: 1px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-success-2.css">
+  <link rel=stylesheet media="braille, screen" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-braille-screen-2.css">
+  <link rel=stylesheet media="screen and (min-width: 1000000px)" href="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=media-screen-query-fail-2.css">
+  
+</head>
+<body>
+  <img src="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=image.jpg">
+  <script src="http://127.0.0.1:8000/resources/network-simulator.php?command=log-resource-request&path=script.js"></script>
+
+  Test stylesheet load scheduling. Resource loads for screen stylesheets should be scheduled first, others should be scheduled last.
+
+  <h2>Resource requests:</h2>
+  <pre id="result">Request log goes here in DRT</pre>
+</body>
+</html>
index 9c0403a..c12d89a 100644 (file)
@@ -1093,3 +1093,8 @@ editing/text-iterator/findString.html
 # The relevant bugs are https://bugs.webkit.org/show_bug.cgi?id=47849/47817.
 fast/frames/location-redirect-user-gesture.html
 fast/frames/meta-refresh-user-gesture.html
+
+# For https://bugs.webkit.org/show_bug.cgi?id=50758
+# These require DRT setSerializeHTTPLoads implementation to be reliable.
+http/tests/local/link-stylesheet-load-order.html
+http/tests/local/link-stylesheet-load-order-preload.html
index b05c873..bdaa84c 100644 (file)
@@ -1,3 +1,71 @@
+2010-12-13  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        https://bugs.webkit.org/show_bug.cgi?id=50758
+        <rdar://problem/8722094> 
+        Defer loading print stylesheets
+        
+        - Make preload scanner skip stylesheets with non-screen media types.
+        - Make it possible to specify non-default load priority from the client.
+        - Use this mechanism to load print stylesheets using very low priority so they get loaded after everything else.
+        - Move default priority code from Loader to CachedResource.
+        - Move ResourceLoadScheduler::Priority enum to a separate file (as ResourceLoadPriority).
+        - Add a way to make ResourceLoadScheduler load resources one at the time so the above functionality can be tested reliably.
+
+        Tests: http/tests/local/link-stylesheet-load-order-preload.html
+               http/tests/local/link-stylesheet-load-order.html
+
+        * WebCore.exp.in:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSImageValue.cpp:
+        (WebCore::CSSImageValue::cachedImage):
+        * html/HTMLLinkElement.cpp:
+        (WebCore::HTMLLinkElement::process):
+        * html/parser/HTMLPreloadScanner.cpp:
+        (WebCore::HTMLNames::PreloadTask::PreloadTask):
+        (WebCore::HTMLNames::PreloadTask::processAttributes):
+        (WebCore::HTMLNames::PreloadTask::relAttributeIsStyleSheet):
+        (WebCore::HTMLNames::PreloadTask::linkMediaAttributeIsScreen):
+        (WebCore::HTMLNames::PreloadTask::preload):
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::loadRequest):
+        * loader/ResourceLoadPriority.h: Added.
+        * loader/ResourceLoadScheduler.cpp:
+        (WebCore::ResourceLoadScheduler::ResourceLoadScheduler):
+        (WebCore::ResourceLoadScheduler::scheduleSubresourceLoad):
+        (WebCore::ResourceLoadScheduler::schedulePluginStreamLoad):
+        (WebCore::ResourceLoadScheduler::scheduleLoad):
+        (WebCore::ResourceLoadScheduler::servePendingRequests):
+        (WebCore::ResourceLoadScheduler::HostInformation::~HostInformation):
+        (WebCore::ResourceLoadScheduler::HostInformation::schedule):
+        (WebCore::ResourceLoadScheduler::HostInformation::remove):
+        (WebCore::ResourceLoadScheduler::HostInformation::hasRequests):
+        (WebCore::ResourceLoadScheduler::HostInformation::limitRequests):
+        * loader/ResourceLoadScheduler.h:
+        (WebCore::ResourceLoadScheduler::isSerialLoadingEnabled):
+        (WebCore::ResourceLoadScheduler::setSerialLoadingEnabled):
+        (WebCore::ResourceLoadScheduler::HostInformation::requestsPending):
+        * loader/cache/CachedResource.cpp:
+        (WebCore::defaultPriorityForResourceType):
+        (WebCore::CachedResource::CachedResource):
+        * loader/cache/CachedResource.h:
+        (WebCore::CachedResource::loadPriority):
+        (WebCore::CachedResource::setLoadPriority):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::requestCSSStyleSheet):
+        (WebCore::CachedResourceLoader::requestResource):
+        (WebCore::CachedResourceLoader::requestPreload):
+        * loader/cache/CachedResourceLoader.h:
+        * loader/cache/MemoryCache.cpp:
+        (WebCore::MemoryCache::requestResource):
+        * loader/cache/MemoryCache.h:
+        * loader/loader.cpp:
+        (WebCore::Loader::load):
+
 2010-12-13  Justin Schuh  <jschuh@chromium.org>
 
         Reviewed by Dimitri Glazkov.
index 97a6803..4b1e663 100644 (file)
@@ -491,7 +491,7 @@ __ZN7WebCore20protocolIsJavaScriptERKN3WTF6StringE
 __ZN7WebCore21BackForwardController11itemAtIndexEi
 __ZN7WebCore21PlatformKeyboardEvent24disambiguateKeyDownEventENS0_4TypeEb
 __ZN7WebCore21PlatformKeyboardEventC1EP7NSEvent
-__ZN7WebCore21ResourceLoadScheduler20servePendingRequestsENS0_8PriorityE
+__ZN7WebCore21ResourceLoadScheduler20servePendingRequestsENS_20ResourceLoadPriorityE
 __ZN7WebCore21ResourceLoadScheduler24schedulePluginStreamLoadEPNS_5FrameEPNS_32NetscapePlugInStreamLoaderClientERKNS_15ResourceRequestE
 __ZN7WebCore21SVGDocumentExtensions21sampleAnimationAtTimeERKN3WTF6StringEPNS_14SVGSMILElementEd
 __ZN7WebCore21SerializedScriptValue11deserializeEPK15OpaqueJSContextPPK13OpaqueJSValue
index 425f084..237da0f 100644 (file)
             'loader/ResourceLoader.h',
             'loader/ResourceLoadNotifier.cpp',
             'loader/ResourceLoadNotifier.h',
+            'loader/ResourceLoadPriority.h',
             'loader/ResourceLoadScheduler.cpp',
             'loader/ResourceLoadScheduler.h',
             'loader/SinkDocument.cpp',
index aa15b7b..64dd94d 100644 (file)
@@ -1978,6 +1978,7 @@ HEADERS += \
     loader/PlaceholderDocument.h \
     loader/ProgressTracker.h \
     loader/ResourceLoader.h \
+    loader/ResourceLoadPriority.h \
     loader/SubresourceLoader.h \
     loader/TextResourceDecoder.h \
     loader/ThreadableLoader.h \
index c74410e..99ee999 100755 (executable)
                <Filter
                        Name="loader"
                        >
+            <File
+                               RelativePath="..\loader\ResourceLoadPriority.h"
+                               >
+                       </File>
                        <File
-                               RelativePath="..\loader\ ResourceLoadScheduler.h"
+                               RelativePath="..\loader\ResourceLoadScheduler.h"
                                >
                        </File>
                        <File
index 9d9992c..b2cda1e 100644 (file)
                E1FF57A60F01256B00891EBB /* ThreadGlobalData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1FF57A50F01256B00891EBB /* ThreadGlobalData.cpp */; };
                E415F1690D9A165D0033CE97 /* DOMElementTimeControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E415F1680D9A165D0033CE97 /* DOMElementTimeControl.h */; };
                E415F1840D9A1A830033CE97 /* ElementTimeControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E415F1830D9A1A830033CE97 /* ElementTimeControl.h */; };
+               E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E44613A10CD6331000FADA75 /* HTMLAudioElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E446138F0CD6331000FADA75 /* HTMLAudioElement.cpp */; };
                E44613A20CD6331000FADA75 /* HTMLAudioElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E44613900CD6331000FADA75 /* HTMLAudioElement.h */; };
                E44613A40CD6331000FADA75 /* HTMLMediaElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E44613920CD6331000FADA75 /* HTMLMediaElement.cpp */; };
                E415F1830D9A1A830033CE97 /* ElementTimeControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementTimeControl.h; sourceTree = "<group>"; };
                E41EA038119836DB00710BC5 /* CSSPropertyNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPropertyNames.cpp; sourceTree = "<group>"; };
                E41EA0391198374900710BC5 /* CSSValueKeywords.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSValueKeywords.cpp; sourceTree = "<group>"; };
+               E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadPriority.h; sourceTree = "<group>"; };
                E446138F0CD6331000FADA75 /* HTMLAudioElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLAudioElement.cpp; sourceTree = "<group>"; };
                E44613900CD6331000FADA75 /* HTMLAudioElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLAudioElement.h; sourceTree = "<group>"; };
                E44613910CD6331000FADA75 /* HTMLAudioElement.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLAudioElement.idl; sourceTree = "<group>"; };
                                656D37270ADBA5DE00A4554D /* ResourceLoader.h */,
                                973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */,
                                973E325510883B7C005BC493 /* ResourceLoadNotifier.h */,
+                               E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */,
                                D0CE58F6125E4CC200F3F199 /* ResourceLoadScheduler.cpp */,
                                D0CE58F7125E4CC200F3F199 /* ResourceLoadScheduler.h */,
                                51327D5F11A33A2B004F9D65 /* SinkDocument.cpp */,
                                499B3EC5128CCC4700E726C2 /* PlatformCALayer.h in Headers */,
                                499B3ED7128CD31400E726C2 /* GraphicsLayerCA.h in Headers */,
                                499B3EDD128DB50200E726C2 /* PlatformCAAnimation.h in Headers */,
+                               E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */,
                                FD315FF712B0267600C1A359 /* AudioBasicProcessorNode.h in Headers */,
                                FD315FF912B0267600C1A359 /* AudioBuffer.h in Headers */,
                                FD315FFC12B0267600C1A359 /* AudioBufferSourceNode.h in Headers */,
index f09a35f..2155eea 100644 (file)
@@ -74,7 +74,7 @@ StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader, const
             cachedImage = loader->requestImage(url);
         else {
             // FIXME: Should find a way to make these images sit in their own memory partition, since they are user agent images.
-            cachedImage = static_cast<CachedImage*>(cache()->requestResource(0, CachedResource::ImageResource, KURL(ParsedURLString, url), String()));
+            cachedImage = static_cast<CachedImage*>(cache()->requestResource(0, CachedResource::ImageResource, KURL(ParsedURLString, url), String(), ResourceLoadPriorityUnresolved));
         }
 
         if (cachedImage) {
index 319e759..a6e5b57 100644 (file)
@@ -224,10 +224,15 @@ void HTMLLinkElement::process()
 
     bool acceptIfTypeContainsTextCSS = document()->page() && document()->page()->settings() && document()->page()->settings()->treatsAnyTextCSSLinkAsStylesheet();
 
-    // Stylesheet
-    // This was buggy and would incorrectly match <link rel="alternate">, which has a different specified meaning. -dwh
-    if (m_disabledState != Disabled && (m_relAttribute.m_isStyleSheet || (acceptIfTypeContainsTextCSS && type.contains("text/css"))) && document()->frame() && m_url.isValid()) {
-        // also, don't load style sheets for standalone documents
+    bool mediaIsScreen = true;
+    if (!m_media.isEmpty()) {
+        RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(m_media);
+        MediaQueryEvaluator screenEvaluator("screen", true);
+        mediaIsScreen = screenEvaluator.eval(media.get());
+    }
+    
+    if (m_disabledState != Disabled && (m_relAttribute.m_isStyleSheet || (acceptIfTypeContainsTextCSS && type.contains("text/css"))) 
+        && document()->frame() && m_url.isValid()) {
         
         String charset = getAttribute(charsetAttr);
         if (charset.isEmpty() && document()->frame())
@@ -250,7 +255,9 @@ void HTMLLinkElement::process()
         if (!isAlternate())
             document()->addPendingSheet();
 
-        m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(m_url, charset);
+        // Load non-screen stylesheets with low priority so they don't affect normal page loading.
+        ResourceLoadPriority priority = mediaIsScreen ? ResourceLoadPriorityUnresolved : ResourceLoadPriorityVeryLow;
+        m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(m_url, charset, priority);
         
         if (m_cachedSheet)
             m_cachedSheet->addClient(this);
index 5c86579..d23542f 100644 (file)
@@ -35,6 +35,8 @@
 #include "HTMLLinkElement.h"
 #include "HTMLNames.h"
 #include "HTMLParserIdioms.h"
+#include "MediaList.h"
+#include "MediaQueryEvaluator.h"
 
 namespace WebCore {
 
@@ -47,6 +49,7 @@ public:
     PreloadTask(const HTMLToken& token)
         : m_tagName(token.name().data(), token.name().size())
         , m_linkIsStyleSheet(false)
+        , m_linkMediaAttributeIsScreen(true)
     {
         processAttributes(token.attributes());
     }
@@ -72,17 +75,31 @@ public:
                     setUrlToLoad(attributeValue);
                 else if (attributeName == relAttr)
                     m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue);
+                else if (attributeName == mediaAttr)
+                    m_linkMediaAttributeIsScreen = linkMediaAttributeIsScreen(attributeValue);
             }
         }
     }
 
-    bool relAttributeIsStyleSheet(const String& attributeValue)
+    static bool relAttributeIsStyleSheet(const String& attributeValue)
     {
-        ASSERT(m_tagName == linkTag);
         HTMLLinkElement::RelAttribute rel;
         HTMLLinkElement::tokenizeRelAttribute(attributeValue, rel);
         return rel.m_isStyleSheet && !rel.m_isAlternate && !rel.m_isIcon && !rel.m_isDNSPrefetch;
     }
+    
+    static bool linkMediaAttributeIsScreen(const String& attributeValue)
+    {
+        if (attributeValue.isEmpty())
+            return true;
+        RefPtr<MediaList> mediaList = MediaList::createAllowingDescriptionSyntax(attributeValue);
+    
+        // Only preload screen media stylesheets. Used this way, the evaluator evaluates to true for any 
+        // rules containing complex queries (full evaluation is possible but it requires a frame and a style selector which
+        // may be problematic here).
+        MediaQueryEvaluator mediaQueryEvaluator("screen");
+        return mediaQueryEvaluator.eval(mediaList.get());
+    }
 
     void setUrlToLoad(const String& attributeValue)
     {
@@ -103,7 +120,7 @@ public:
             cachedResourceLoader->preload(CachedResource::Script, m_urlToLoad, m_charset, scanningBody);
         else if (m_tagName == imgTag) 
             cachedResourceLoader->preload(CachedResource::ImageResource, m_urlToLoad, String(), scanningBody);
-        else if (m_tagName == linkTag && m_linkIsStyleSheet) 
+        else if (m_tagName == linkTag && m_linkIsStyleSheet && m_linkMediaAttributeIsScreen
             cachedResourceLoader->preload(CachedResource::CSSStyleSheet, m_urlToLoad, m_charset, scanningBody);
     }
 
@@ -114,6 +131,7 @@ private:
     String m_urlToLoad;
     String m_charset;
     bool m_linkIsStyleSheet;
+    bool m_linkMediaAttributeIsScreen;
 };
 
 } // namespace
index 03cea73..dee5001 100644 (file)
@@ -320,7 +320,7 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur
 
         // Clear the loader so that any callbacks from SubresourceLoader::create will not have the old loader.
         m_loader = 0;
-        m_loader = resourceLoadScheduler()->scheduleSubresourceLoad(m_document->frame(), this, request, ResourceLoadScheduler::Medium, securityCheck, sendLoadCallbacks, sniffContent);
+        m_loader = resourceLoadScheduler()->scheduleSubresourceLoad(m_document->frame(), this, request, ResourceLoadPriorityMedium, securityCheck, sendLoadCallbacks, sniffContent);
         return;
     }
     
diff --git a/WebCore/loader/ResourceLoadPriority.h b/WebCore/loader/ResourceLoadPriority.h
new file mode 100644 (file)
index 0000000..1c9d5d2
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are 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.
+ */
+
+#ifndef ResourceLoadPriority_h
+#define ResourceLoadPriority_h
+
+namespace WebCore {
+
+enum ResourceLoadPriority { 
+    ResourceLoadPriorityVeryLow, 
+    ResourceLoadPriorityLow, 
+    ResourceLoadPriorityMedium, 
+    ResourceLoadPriorityHigh, 
+    ResourceLoadPriorityLowest = ResourceLoadPriorityVeryLow, 
+    ResourceLoadPriorityHighest = ResourceLoadPriorityHigh, 
+    // The unresolved priority is here for the convenience of the clients. It should not be passed to the ResourceLoadScheduler.
+    ResourceLoadPriorityUnresolved,
+};
+
+}
+
+#endif
+
index 7c50dc1..8cf2c18 100644 (file)
@@ -76,13 +76,14 @@ ResourceLoadScheduler::ResourceLoadScheduler()
     : m_nonHTTPProtocolHost(new HostInformation(String(), maxRequestsInFlightForNonHTTPProtocols))
     , m_requestTimer(this, &ResourceLoadScheduler::requestTimerFired)
     , m_isSuspendingPendingRequests(false)
+    , m_isSerialLoadingEnabled(false)
 {
 #if REQUEST_MANAGEMENT_ENABLED
     maxRequestsInFlightPerHost = initializeMaximumHTTPConnectionCountPerHost();
 #endif
 }
 
-PassRefPtr<SubresourceLoader> ResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, Priority priority, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff)
+PassRefPtr<SubresourceLoader> ResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, ResourceLoadPriority priority, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff)
 {
     PassRefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, client, request, securityCheck, sendResourceLoadCallbacks, shouldContentSniff);
     if (loader)
@@ -94,7 +95,7 @@ PassRefPtr<NetscapePlugInStreamLoader> ResourceLoadScheduler::schedulePluginStre
 {
     PassRefPtr<NetscapePlugInStreamLoader> loader = NetscapePlugInStreamLoader::create(frame, client, request);
     if (loader)
-        scheduleLoad(loader.get(), Low);
+        scheduleLoad(loader.get(), ResourceLoadPriorityLow);
     return loader;
 }
 
@@ -103,11 +104,12 @@ void ResourceLoadScheduler::addMainResourceLoad(ResourceLoader* resourceLoader)
     hostForURL(resourceLoader->url(), CreateIfNotFound)->addLoadInProgress(resourceLoader);
 }
 
-void ResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, Priority priority)
+void ResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, ResourceLoadPriority priority)
 {
     ASSERT(resourceLoader);
+    ASSERT(priority != ResourceLoadPriorityUnresolved);
 #if !REQUEST_MANAGEMENT_ENABLED
-    priority = HighestPriority;
+    priority = ResourceLoadPriorityHighest;
 #endif
 
     LOG(ResourceLoading, "ResourceLoadScheduler::load resource %p '%s'", resourceLoader, resourceLoader->url().string().latin1().data());
@@ -115,7 +117,7 @@ void ResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, Priorit
     bool hadRequests = host->hasRequests();
     host->schedule(resourceLoader, priority);
 
-    if (priority > Low || !resourceLoader->url().protocolInHTTPFamily() || (priority == Low && !hadRequests)) {
+    if (priority > ResourceLoadPriorityLow || !resourceLoader->url().protocolInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) {
         // Try to request important resources immediately.
         servePendingRequests(host, priority);
     } else {
@@ -148,7 +150,7 @@ void ResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoader* resource
     oldHost->remove(resourceLoader);
 }
 
-void ResourceLoadScheduler::servePendingRequests(Priority minimumPriority)
+void ResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
 {
     LOG(ResourceLoading, "ResourceLoadScheduler::servePendingRequests. m_isSuspendingPendingRequests=%d", m_isSuspendingPendingRequests); 
     if (m_isSuspendingPendingRequests)
@@ -174,12 +176,12 @@ void ResourceLoadScheduler::servePendingRequests(Priority minimumPriority)
     }
 }
 
-void ResourceLoadScheduler::servePendingRequests(HostInformation* host, Priority minimumPriority)
+void ResourceLoadScheduler::servePendingRequests(HostInformation* host, ResourceLoadPriority minimumPriority)
 {
     LOG(ResourceLoading, "ResourceLoadScheduler::servePendingRequests HostInformation.m_name='%s'", host->name().latin1().data());
 
-    for (int priority = HighestPriority; priority >= minimumPriority; --priority) {
-        HostInformation::RequestQueue& requestsPending = host->requestsPending((Priority) priority);
+    for (int priority = ResourceLoadPriorityHighest; priority >= minimumPriority; --priority) {
+        HostInformation::RequestQueue& requestsPending = host->requestsPending((ResourceLoadPriority) priority);
 
         while (!requestsPending.isEmpty()) {
             RefPtr<ResourceLoader> resourceLoader = requestsPending.first();
@@ -235,11 +237,11 @@ ResourceLoadScheduler::HostInformation::HostInformation(const String& name, unsi
 ResourceLoadScheduler::HostInformation::~HostInformation()
 {
     ASSERT(m_requestsLoading.isEmpty());
-    for (unsigned p = 0; p <= HighestPriority; p++)
+    for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++)
         ASSERT(m_requestsPending[p].isEmpty());
 }
     
-void ResourceLoadScheduler::HostInformation::schedule(ResourceLoader* resourceLoader, Priority priority)
+void ResourceLoadScheduler::HostInformation::schedule(ResourceLoader* resourceLoader, ResourceLoadPriority priority)
 {
     m_requestsPending[priority].append(resourceLoader);
 }
@@ -257,7 +259,7 @@ void ResourceLoadScheduler::HostInformation::remove(ResourceLoader* resourceLoad
         return;
     }
     
-    for (int priority = HighestPriority; priority >= LowestPriority; --priority) {  
+    for (int priority = ResourceLoadPriorityHighest; priority >= ResourceLoadPriorityLowest; --priority) {  
         RequestQueue::iterator end = m_requestsPending[priority].end();
         for (RequestQueue::iterator it = m_requestsPending[priority].begin(); it != end; ++it) {
             if (*it == resourceLoader) {
@@ -272,11 +274,16 @@ bool ResourceLoadScheduler::HostInformation::hasRequests() const
 {
     if (!m_requestsLoading.isEmpty())
         return true;
-    for (unsigned p = 0; p <= HighestPriority; p++) {
+    for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) {
         if (!m_requestsPending[p].isEmpty())
             return true;
     }
     return false;
 }
 
+bool ResourceLoadScheduler::HostInformation::limitRequests() const 
+{ 
+    return m_requestsLoading.size() >= (resourceLoadScheduler()->isSerialLoadingEnabled() ? 1 : m_maxRequestsInFlight);
+}
+
 } // namespace WebCore
index 84f8845..163b67e 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "FrameLoaderTypes.h"
 #include "PlatformString.h"
+#include "ResourceLoadPriority.h"
 #include "Timer.h"
 #include <wtf/Deque.h>
 #include <wtf/HashMap.h>
@@ -47,22 +48,24 @@ class ResourceLoadScheduler : public Noncopyable {
 public:
     friend ResourceLoadScheduler* resourceLoadScheduler();
 
-    enum Priority { VeryLow, Low, Medium, High, LowestPriority = VeryLow, HighestPriority = High };
-    PassRefPtr<SubresourceLoader> scheduleSubresourceLoad(Frame*, SubresourceLoaderClient*, const ResourceRequest&, Priority = Low, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true);
+    PassRefPtr<SubresourceLoader> scheduleSubresourceLoad(Frame*, SubresourceLoaderClient*, const ResourceRequest&, ResourceLoadPriority = ResourceLoadPriorityLow, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true);
     PassRefPtr<NetscapePlugInStreamLoader> schedulePluginStreamLoad(Frame*, NetscapePlugInStreamLoaderClient*, const ResourceRequest&);
     void addMainResourceLoad(ResourceLoader*);
     void remove(ResourceLoader*);
     void crossOriginRedirectReceived(ResourceLoader*, const KURL& redirectURL);
     
-    void servePendingRequests(Priority minimumPriority = VeryLow);
+    void servePendingRequests(ResourceLoadPriority minimumPriority = ResourceLoadPriorityVeryLow);
     void suspendPendingRequests();
     void resumePendingRequests();
+    
+    bool isSerialLoadingEnabled() const { return m_isSerialLoadingEnabled; }
+    void setSerialLoadingEnabled(bool b) { m_isSerialLoadingEnabled = b; }
 
 private:
     ResourceLoadScheduler();
     ~ResourceLoadScheduler();
 
-    void scheduleLoad(ResourceLoader*, Priority);
+    void scheduleLoad(ResourceLoader*, ResourceLoadPriority);
     void scheduleServePendingRequests();
     void requestTimerFired(Timer<ResourceLoadScheduler>*);
 
@@ -72,17 +75,17 @@ private:
         ~HostInformation();
         
         const String& name() const { return m_name; }
-        void schedule(ResourceLoader*, Priority = VeryLow);
+        void schedule(ResourceLoader*, ResourceLoadPriority = ResourceLoadPriorityVeryLow);
         void addLoadInProgress(ResourceLoader*);
         void remove(ResourceLoader*);
         bool hasRequests() const;
-        bool limitRequests() const { return m_requestsLoading.size() >= m_maxRequestsInFlight; }
+        bool limitRequests() const;
 
         typedef Deque<RefPtr<ResourceLoader> > RequestQueue;
-        RequestQueue& requestsPending(Priority priority) { return m_requestsPending[priority]; }
+        RequestQueue& requestsPending(ResourceLoadPriority priority) { return m_requestsPending[priority]; }
 
     private:                    
-        RequestQueue m_requestsPending[HighestPriority + 1];
+        RequestQueue m_requestsPending[ResourceLoadPriorityHighest + 1];
         typedef HashSet<RefPtr<ResourceLoader> > RequestMap;
         RequestMap m_requestsLoading;
         const String m_name;
@@ -95,7 +98,7 @@ private:
     };
     
     HostInformation* hostForURL(const KURL&, CreateHostPolicy = FindOnly);
-    void servePendingRequests(HostInformation*, Priority);
+    void servePendingRequests(HostInformation*, ResourceLoadPriority);
 
     typedef HashMap<String, HostInformation*, StringHash> HostMap;
     HostMap m_hosts;
@@ -104,6 +107,7 @@ private:
     Timer<ResourceLoadScheduler> m_requestTimer;
 
     bool m_isSuspendingPendingRequests;
+    bool m_isSerialLoadingEnabled;
 };
 
 ResourceLoadScheduler* resourceLoadScheduler();
index 09d0fbe..1b9ed0b 100644 (file)
 using namespace WTF;
 
 namespace WebCore {
+    
+static ResourceLoadPriority defaultPriorityForResourceType(CachedResource::Type type)
+{
+    switch (type) {
+        case CachedResource::CSSStyleSheet:
+#if ENABLE(XSLT)
+        case CachedResource::XSLStyleSheet:
+#endif
+            return ResourceLoadPriorityHigh;
+        case CachedResource::Script:
+        case CachedResource::FontResource:
+            return ResourceLoadPriorityMedium;
+        case CachedResource::ImageResource:
+            return ResourceLoadPriorityLow;
+#if ENABLE(LINK_PREFETCH)
+        case CachedResource::LinkPrefetch:
+            return ResourceLoadPriorityVeryLow;
+#endif
+    }
+    ASSERT_NOT_REACHED();
+    return ResourceLoadPriorityLow;
+}
 
 #ifndef NDEBUG
 static RefCountedLeakCounter cachedResourceLeakCounter("CachedResource");
@@ -55,6 +77,7 @@ static RefCountedLeakCounter cachedResourceLeakCounter("CachedResource");
 CachedResource::CachedResource(const String& url, Type type)
     : m_url(url)
     , m_request(0)
+    , m_loadPriority(defaultPriorityForResourceType(type))
     , m_responseTimestamp(currentTime())
     , m_lastDecodedAccessTime(0)
     , m_encodedSize(0)
index b6681bc..e380b6e 100644 (file)
@@ -27,6 +27,7 @@
 #include "FrameLoaderTypes.h"
 #include "PlatformString.h"
 #include "PurgePriority.h"
+#include "ResourceLoadPriority.h"
 #include "ResourceResponse.h"
 #include <wtf/HashCountedSet.h>
 #include <wtf/HashSet.h>
@@ -90,6 +91,8 @@ public:
 
     const String &url() const { return m_url; }
     Type type() const { return static_cast<Type>(m_type); }
+    
+    ResourceLoadPriority loadPriority() const { return m_loadPriority; }
 
     void addClient(CachedResourceClient*);
     void removeClient(CachedResourceClient*);
@@ -217,6 +220,7 @@ protected:
     String m_url;
     String m_accept;
     Loader* m_request;
+    ResourceLoadPriority m_loadPriority;
 
     ResourceResponse m_response;
     double m_responseTimestamp;
@@ -233,6 +237,7 @@ private:
     void clearResourceToRevalidate();
     void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse);
     virtual PurgePriority purgePriority() const { return PurgeDefault; }
+    void setLoadPriority(ResourceLoadPriority loadPriority) { m_loadPriority = loadPriority; }
 
     double currentAge() const;
     double freshnessLifetime() const;
index 421640a..66f0b2f 100644 (file)
@@ -145,9 +145,9 @@ CachedFont* CachedResourceLoader::requestFont(const String& url)
     return static_cast<CachedFont*>(requestResource(CachedResource::FontResource, url, String()));
 }
 
-CachedCSSStyleSheet* CachedResourceLoader::requestCSSStyleSheet(const String& url, const String& charset)
+CachedCSSStyleSheet* CachedResourceLoader::requestCSSStyleSheet(const String& url, const String& charset, ResourceLoadPriority priority)
 {
-    return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, url, charset));
+    return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, url, charset, priority));
 }
 
 CachedCSSStyleSheet* CachedResourceLoader::requestUserCSSStyleSheet(const String& url, const String& charset)
@@ -243,7 +243,7 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url
     return true;
 }
 
-CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& url, const String& charset, bool isPreload)
+CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& url, const String& charset, ResourceLoadPriority priority, bool isPreload)
 {
     KURL fullURL = m_document->completeURL(url);
 
@@ -262,7 +262,7 @@ CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type,
     checkForReload(fullURL);
 
     bool allowForHistoryOnlyResources = cachePolicy() == CachePolicyHistoryBuffer;
-    CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, isPreload, allowForHistoryOnlyResources);
+    CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, priority, isPreload, allowForHistoryOnlyResources);
     if (resource) {
         // Check final URL of resource to catch redirects.
         // See <https://bugs.webkit.org/show_bug.cgi?id=21963>.
@@ -431,7 +431,7 @@ void CachedResourceLoader::requestPreload(CachedResource::Type type, const Strin
     if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet)
         encoding = charset.isEmpty() ? m_document->frame()->loader()->writer()->encoding() : charset;
 
-    CachedResource* resource = requestResource(type, url, encoding, true);
+    CachedResource* resource = requestResource(type, url, encoding, ResourceLoadPriorityUnresolved, true);
     if (!resource || (m_preloads && m_preloads->contains(resource)))
         return;
     resource->increasePreloadCount();
index 0e20b5a..2deb7d4 100644 (file)
@@ -29,6 +29,7 @@
 #include "CachedResource.h"
 #include "CachedResourceHandle.h"
 #include "CachePolicy.h"
+#include "ResourceLoadPriority.h"
 #include "loader.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -57,7 +58,7 @@ public:
     ~CachedResourceLoader();
 
     CachedImage* requestImage(const String& url);
-    CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset);
+    CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset, ResourceLoadPriority priority = ResourceLoadPriorityUnresolved);
     CachedCSSStyleSheet* requestUserCSSStyleSheet(const String& url, const String& charset);
     CachedScript* requestScript(const String& url, const String& charset);
     CachedFont* requestFont(const String& url);
@@ -105,7 +106,7 @@ public:
     void printPreloadStats();
     
 private:
-    CachedResource* requestResource(CachedResource::Type, const String& url, const String& charset, bool isPreload = false);
+    CachedResource* requestResource(CachedResource::Type, const String& url, const String& charset, ResourceLoadPriority priority = ResourceLoadPriorityUnresolved, bool isPreload = false);
     void requestPreload(CachedResource::Type, const String& url, const String& charset);
 
     void checkForReload(const KURL&);
index ae8e53a..7b46fca 100644 (file)
@@ -95,10 +95,10 @@ static CachedResource* createResource(CachedResource::Type type, const KURL& url
     return 0;
 }
 
-CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourceLoader, CachedResource::Type type, const KURL& url, const String& charset, bool requestIsPreload, bool forHistory)
+CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourceLoader, CachedResource::Type type, const KURL& url, const String& charset, ResourceLoadPriority priority, bool requestIsPreload, bool forHistory)
 {
-    LOG(ResourceLoading, "MemoryCache::requestResource '%s', charset '%s', preload=%u, forHistory=%u", url.string().latin1().data(), charset.latin1().data(), requestIsPreload, forHistory);
-
+    LOG(ResourceLoading, "MemoryCache::requestResource '%s', charset '%s', priority=%d, preload=%u, forHistory=%u", url.string().latin1().data(), charset.latin1().data(), priority, requestIsPreload, forHistory);
+    
     // FIXME: Do we really need to special-case an empty URL?
     // Would it be better to just go on with the cache code and let it fail later?
     if (url.isEmpty())
@@ -144,6 +144,10 @@ CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourc
         // FIXME: CachedResource should just use normal refcounting instead.
         resource->setInCache(true);
         
+        // Default priority based on resource type is used if the request did not specify one.
+        if (priority != ResourceLoadPriorityUnresolved)
+            resource->setLoadPriority(priority);
+
         resource->load(cachedResourceLoader);
         
         if (resource->errorOccurred()) {
@@ -162,6 +166,12 @@ CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourc
             resource->setInCache(false);
             resource->setCachedResourceLoader(cachedResourceLoader);
         }
+    } else {
+        // FIXME: Upgrading the priority doesn't really do much since the ResourceLoadScheduler does not currently
+        // allow changing priorities. This might become important if we make scheduling priorities
+        // more dynamic.
+        if (priority != ResourceLoadPriorityUnresolved && resource->loadPriority() < priority)
+            resource->setLoadPriority(priority);
     }
 
     if (!disabled()) {
index 7439ee8..b9564b3 100644 (file)
@@ -105,7 +105,7 @@ public:
 
     // Request resources from the cache.  A load will be initiated and a cache object created if the object is not
     // found in the cache.
-    CachedResource* requestResource(CachedResourceLoader*, CachedResource::Type, const KURL& url, const String& charset, bool isPreload = false, bool forHistory = false);
+    CachedResource* requestResource(CachedResourceLoader*, CachedResource::Type, const KURL& url, const String& charset, ResourceLoadPriority, bool isPreload = false, bool forHistory = false);
 
     CachedCSSStyleSheet* requestUserCSSStyleSheet(CachedResourceLoader*, const String& url, const String& charset);
     
index cf51d9a..4df2854 100644 (file)
@@ -65,28 +65,6 @@ static ResourceRequest::TargetType cachedResourceTypeToTargetType(CachedResource
     return ResourceRequest::TargetIsSubresource;
 }
 
-static ResourceLoadScheduler::Priority determinePriority(const CachedResource* resource)
-{
-    switch (resource->type()) {
-        case CachedResource::CSSStyleSheet:
-#if ENABLE(XSLT)
-        case CachedResource::XSLStyleSheet:
-#endif
-            return ResourceLoadScheduler::High;
-        case CachedResource::Script:
-        case CachedResource::FontResource:
-            return ResourceLoadScheduler::Medium;
-        case CachedResource::ImageResource:
-            return ResourceLoadScheduler::Low;
-#if ENABLE(LINK_PREFETCH)
-        case CachedResource::LinkPrefetch:
-            return ResourceLoadScheduler::VeryLow;
-#endif
-    }
-    ASSERT_NOT_REACHED();
-    return ResourceLoadScheduler::Low;
-}
-
 Loader::Loader(CachedResourceLoader* cachedResourceLoader, CachedResource* resource, bool incremental)
     : m_cachedResourceLoader(cachedResourceLoader)
     , m_resource(resource)
@@ -133,9 +111,11 @@ PassRefPtr<Loader> Loader::load(CachedResourceLoader* cachedResourceLoader, Cach
     if (resource->type() == CachedResource::LinkPrefetch)
         resourceRequest.setHTTPHeaderField("X-Purpose", "prefetch");
 #endif
+    
+    ResourceLoadPriority priority = resource->loadPriority();
 
     RefPtr<SubresourceLoader> loader = resourceLoadScheduler()->scheduleSubresourceLoad(cachedResourceLoader->document()->frame(),
-        request.get(), resourceRequest, determinePriority(resource), securityCheck, sendResourceLoadCallbacks);
+        request.get(), resourceRequest, priority, securityCheck, sendResourceLoadCallbacks);
     if (!loader || loader->reachedTerminalState()) {
         // FIXME: What if resources in other frames were waiting for this revalidation?
         LOG(ResourceLoading, "Cannot start loading '%s'", resource->url().latin1().data());
index cb74a38..b580d3d 100644 (file)
@@ -1,3 +1,17 @@
+2010-12-13  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        https://bugs.webkit.org/show_bug.cgi?id=50758
+        <rdar://problem/8722094> 
+        Defer loading print stylesheets
+        
+        Expose SPI for DRT for making resources load serially. This is useful for testing resource load order.
+
+        * WebView/WebView.mm:
+        (+[WebView _setLoadResourcesSerially:forHost:]):
+        * WebView/WebViewPrivate.h:
+
 2010-12-09  Matthew Delaney  <mdelaney@apple.com>
 
         Reviewed by Simon Fraser.
index ee62f61..bd13ff0 100644 (file)
@@ -2668,6 +2668,11 @@ static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns)
     return [self findString:string options:((forward ? 0 : WebFindOptionsBackwards) | (caseFlag ? 0 : WebFindOptionsCaseInsensitive) | (wrapFlag ? WebFindOptionsWrapAround : 0) | (startInSelection ? WebFindOptionsStartInSelection : 0))];
 }
 
++ (void)_setLoadResourcesSerially:(BOOL)serialize 
+{
+    resourceLoadScheduler()->setSerialLoadingEnabled(serialize);
+}
+
 @end
 
 @implementation _WebSafeForwarder
index 340ac53..67ee63a 100644 (file)
@@ -524,6 +524,9 @@ Could be worth adding to the API.
 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world;
 + (void)_removeAllUserContentFromGroup:(NSString *)groupName;
 
+// SPI for DumpRenderTree
++ (void)_setLoadResourcesSerially:(BOOL)serialize;
+
 /*!
     @method cssAnimationsSuspended
     @abstract Returns whether or not CSS Animations are suspended.
index db35415..da25330 100644 (file)
@@ -1,3 +1,23 @@
+2010-12-13  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Add setSerializeHTTPLoads function to allow testing resource load order on OS X.
+        https://bugs.webkit.org/show_bug.cgi?id=50758
+
+        * DumpRenderTree/LayoutTestController.cpp:
+        (setSerializeHTTPLoadsCallback):
+        (LayoutTestController::staticFunctions):
+        * DumpRenderTree/LayoutTestController.h:
+        * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+        (LayoutTestController::setSerializeHTTPLoads):
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (resetDefaultsToConsistentValues):
+        * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+        (LayoutTestController::setSerializeHTTPLoads):
+        * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+        (LayoutTestController::setSerializeHTTPLoads):
+
 2010-12-13  Dimitri Glazkov  <dglazkov@chromium.org>
 
         Reviewed by Ojan Vafai.
index 2270160..16a3149 100644 (file)
@@ -1845,6 +1845,16 @@ static JSValueRef setEditingBehaviorCallback(JSContextRef context, JSObjectRef f
     return JSValueMakeUndefined(context);
 }
 
+static JSValueRef setSerializeHTTPLoadsCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    bool serialize = true;
+    if (argumentCount == 1)
+        serialize = JSValueToBoolean(context, arguments[0]);
+
+    LayoutTestController::setSerializeHTTPLoads(serialize);
+    return JSValueMakeUndefined(context);
+}
+
 // Static Values
 
 static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
@@ -2029,6 +2039,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
         { "setPrinting", setPrintingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setPrivateBrowsingEnabled", setPrivateBrowsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setSelectTrailingWhitespaceEnabled", setSelectTrailingWhitespaceEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "setSerializeHTTPLoads", setSerializeHTTPLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setSmartInsertDeleteEnabled", setSmartInsertDeleteEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setSpatialNavigationEnabled", setSpatialNavigationEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setStopProvisionalFrameLoads", setStopProvisionalFrameLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
index 21d6add..026de13 100644 (file)
@@ -287,6 +287,8 @@ public:
     bool hasSpellingMarker(int from, int length);
 
     void dumpConfigurationForViewport(int availableWidth, int availableHeight);
+    
+    static void setSerializeHTTPLoads(bool serialize);
 
     // The following API test functions should probably be moved to platform-specific 
     // unit tests outside of DRT once they exist.
index 33a3727..1527811 100644 (file)
@@ -835,3 +835,8 @@ void LayoutTestController::dumpConfigurationForViewport(int availableWidth, int
     ASSERT(webView);
     DumpRenderTreeSupportGtk::dumpConfigurationForViewport(webView, availableWidth, availableHeight);
 }
+
+void LayoutTestController::setSerializeHTTPLoads(bool)
+{
+    // FIXME: Implement if needed for https://bugs.webkit.org/show_bug.cgi?id=50758.
+}
index 5cf60ef..ed09cf6 100644 (file)
@@ -464,6 +464,8 @@ static void resetDefaultsToConsistentValues()
     [preferences setAsynchronousSpellCheckingEnabled:NO];
 
     [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain];
+    
+    LayoutTestController::setSerializeHTTPLoads(false);
 
     setlocale(LC_ALL, "");
 }
index b0be44f..a691951 100644 (file)
@@ -998,3 +998,8 @@ void LayoutTestController::dumpConfigurationForViewport(int /*availableWidth*/,
 {
 
 }
+
+void LayoutTestController::setSerializeHTTPLoads(bool serialize)
+{
+    [WebView _setLoadResourcesSerially:serialize];
+}
index 2c4a52d..1dabf03 100644 (file)
@@ -1425,3 +1425,8 @@ void LayoutTestController::dumpConfigurationForViewport(int /*availableWidth*/,
 {
     // FIXME: Implement this.
 }
+
+void LayoutTestController::setSerializeHTTPLoads(bool)
+{
+    // FIXME: Implement.
+}