[preload] Add media and type attribute support.
authoryoav@yoav.ws <yoav@yoav.ws@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 May 2017 22:03:18 +0000 (22:03 +0000)
committeryoav@yoav.ws <yoav@yoav.ws@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 May 2017 22:03:18 +0000 (22:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171720

Reviewed by Youenn Fablet.

Source/WebCore:

Tests: http/wpt/preload/media-attribute.html
       http/wpt/preload/type-attribute.html
       http/tests/preload/viewport/meta-viewport-link-headers.php

* css/MediaQueryEvaluator.cpp: Move the mediaAttributeMatches code from HTMLResourcePreloader to a central location.
(WebCore::MediaQueryEvaluator::mediaAttributeMatches):
* css/MediaQueryEvaluator.h:
* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::bestFitSourceFromPictureElement): Use isSupportedImageOrSVGMIMEType() instead of checking SVG MIME type specifically.
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::process): Call loadLink() with the media and type attributes.
* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::pumpTokenizer): Trigger Link header based preload for links that have the media attribute.
* html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::StartTagScanner::createPreloadRequest): Avoid preloading link resources with non-matching type.
(WebCore::TokenPreloadScanner::StartTagScanner::processAttribute): Collect the type attribute for link resources.
* html/parser/HTMLResourcePreloader.cpp:
(WebCore::HTMLResourcePreloader::preload): Use MediaQueryEvaluator::mediaAttributeMatches instead of the local one.
(WebCore::mediaAttributeMatches): Deleted.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::receivedFirstData): Indicate that only link preloads with no media attribute should be loaded here.
* loader/LinkLoader.cpp:
(WebCore::LinkLoader::loadLinksFromHeader): Load only links with or without media attributes, according to mode. Also send media and
type attributes to preloadIfNeeded().
(WebCore::LinkLoader::isSupportedType): Check if the MIME type is supported for the CachedResource::Type.
(WebCore::LinkLoader::preloadIfNeeded): Get the media and type attributes and only trigger a preload if media matches and type is supported.
(WebCore::LinkLoader::loadLink): Pass along the media and type attributes.
* loader/LinkLoader.h:
* platform/MIMETypeRegistry.cpp:
(WebCore::MIMETypeRegistry::isSupportedImageOrSVGMIMEType): Check if MIME type is supported for an image, or is an SVG mime type.
(WebCore::MIMETypeRegistry::isSupportedStyleSheetMIMEType): Check if MIME type is supported for a stylesheet.
(WebCore::MIMETypeRegistry::isSupportedFontMIMEType): Check if MIME type is supported for a font.
(WebCore::MIMETypeRegistry::isSupportedTextTrackMIMEType): Check if MIME type is supported for a text track.
* platform/MIMETypeRegistry.h:

LayoutTests:

* TestExpectations: Skip http/tests/preload/viewport as meta viewport is turned off in most platforms.
* http/wpt/preload/media-attribute-expected.txt: Added.
* http/wpt/preload/media-attribute.html: Added.
* http/wpt/preload/type-attribute-expected.txt: Added.
* http/wpt/preload/type-attribute.html: Added.
* http/wpt/preload/resources/square.png: Added.
* http/wpt/preload/resources/dummy.js: Added.
* http/tests/preload/viewport/meta-viewport-link-headers-expected.txt: Added.
* http/tests/preload/viewport/meta-viewport-link-headers.php: Added.
* platform/ios-simulator/TestExpectations: Turn on http/tests/preload/viewport for ios-simulator.
* platform/ios/TestExpectations: Turn on http/tests/preload/viewport for ios.

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/http/tests/preload/viewport/meta-viewport-link-headers-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/preload/viewport/meta-viewport-link-headers.php [new file with mode: 0644]
LayoutTests/http/wpt/preload/media-attribute-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/preload/media-attribute.html [new file with mode: 0644]
LayoutTests/http/wpt/preload/resources/square.png [new file with mode: 0644]
LayoutTests/http/wpt/preload/type-attribute-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/preload/type-attribute.html [new file with mode: 0644]
LayoutTests/platform/ios-simulator/TestExpectations
LayoutTests/platform/ios/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/css/MediaQueryEvaluator.cpp
Source/WebCore/css/MediaQueryEvaluator.h
Source/WebCore/html/HTMLImageElement.cpp
Source/WebCore/html/HTMLLinkElement.cpp
Source/WebCore/html/parser/HTMLDocumentParser.cpp
Source/WebCore/html/parser/HTMLPreloadScanner.cpp
Source/WebCore/html/parser/HTMLResourcePreloader.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/LinkLoader.cpp
Source/WebCore/loader/LinkLoader.h
Source/WebCore/platform/MIMETypeRegistry.cpp
Source/WebCore/platform/MIMETypeRegistry.h

index c5dd3a5..6335537 100644 (file)
@@ -1,3 +1,22 @@
+2017-05-22  Yoav Weiss  <yoav@yoav.ws>
+
+        [preload] Add media and type attribute support.
+        https://bugs.webkit.org/show_bug.cgi?id=171720
+
+        Reviewed by Youenn Fablet.
+
+        * TestExpectations: Skip http/tests/preload/viewport as meta viewport is turned off in most platforms.
+        * http/wpt/preload/media-attribute-expected.txt: Added.
+        * http/wpt/preload/media-attribute.html: Added.
+        * http/wpt/preload/type-attribute-expected.txt: Added.
+        * http/wpt/preload/type-attribute.html: Added.
+        * http/wpt/preload/resources/square.png: Added.
+        * http/wpt/preload/resources/dummy.js: Added.
+        * http/tests/preload/viewport/meta-viewport-link-headers-expected.txt: Added.
+        * http/tests/preload/viewport/meta-viewport-link-headers.php: Added.
+        * platform/ios-simulator/TestExpectations: Turn on http/tests/preload/viewport for ios-simulator.
+        * platform/ios/TestExpectations: Turn on http/tests/preload/viewport for ios.
+
 2017-05-22  Ryan Haddad  <ryanhaddad@apple.com>
 
         Mark imported/w3c/web-platform-tests/WebCryptoAPI/import_export/test_rsa_importKey.https.html as a timeout on El Capitan.
index f8ee6bf..83e6219 100644 (file)
@@ -35,6 +35,7 @@ media/ios [ Skip ]
 media/controls/ipad [ Skip ]
 fast/text-autosizing [ Skip ]
 fast/css/variables/constants/ios [ Skip ]
+http/tests/preload/viewport [ Skip ]
 
 # window.showModalDialog is only tested in DumpRenderTree on Mac.
 editing/execCommand/show-modal-dialog-during-execCommand.html [ Skip ]
diff --git a/LayoutTests/http/tests/preload/viewport/meta-viewport-link-headers-expected.txt b/LayoutTests/http/tests/preload/viewport/meta-viewport-link-headers-expected.txt
new file mode 100644 (file)
index 0000000..394fcf7
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS Makes sure that Link headers support the media attribute and respond to <meta content=viewport> 
+
diff --git a/LayoutTests/http/tests/preload/viewport/meta-viewport-link-headers.php b/LayoutTests/http/tests/preload/viewport/meta-viewport-link-headers.php
new file mode 100644 (file)
index 0000000..73a5b88
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+header("Link: <http://127.0.0.1:8000/resources/square100.png?control>;rel=preload;as=image;\"", false);
+header("Link: <http://127.0.0.1:8000/resources/square100.png?large>;rel=preload;as=image;media=\"(min-width: 300px)\"", false);
+header("Link: <http://127.0.0.1:8000/resources/square100.png?small>;rel=preload;as=image;media=\"(max-width: 299px)\"", false);
+?>
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<meta name="viewport" content="width=160">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+    var t = async_test('Makes sure that Link headers support the media attribute and respond to <meta content=viewport>');
+    window.addEventListener("load", t.step_func(function() {
+        var entries = performance.getEntriesByType("resource");
+        var controlLoaded = false;
+        var smallLoaded = false;
+        var largeLoaded = false;
+        for (var i = 0; i < entries.length; ++i) {
+            if (entries[i].name.indexOf("control") != -1)
+                controlLoaded = true;
+            else if (entries[i].name.indexOf("large") != -1)
+                largeLoaded = true;
+            else if (entries[i].name.indexOf("small") != -1)
+                smallLoaded = true;
+        }
+        assert_true(controlLoaded);
+        assert_false(largeLoaded);
+        assert_true(smallLoaded);
+        t.done();
+    }));
+</script>
+<script src="../resources/slow-script.pl?delay=200"></script>
+
diff --git a/LayoutTests/http/wpt/preload/media-attribute-expected.txt b/LayoutTests/http/wpt/preload/media-attribute-expected.txt
new file mode 100644 (file)
index 0000000..1d0e6e8
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+PASS Makes sure that preloaded resources are not downloaded when the media attribute is a mismatch. 
+
diff --git a/LayoutTests/http/wpt/preload/media-attribute.html b/LayoutTests/http/wpt/preload/media-attribute.html
new file mode 100644 (file)
index 0000000..adb309d
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+    var loaded = 0;
+    var expectedToLoad = 1;
+</script>
+<link rel=preload href="/WebKit/preload/resources/square.png?media_all" as=image media="all" onload="++loaded;">
+<link rel=preload href="/WebKit/preload/resources/square.png?media_not_all" as=image media="not all">
+<script>
+    var t = async_test('Makes sure that preloaded resources are not downloaded when the media attribute is a mismatch.');
+    window.setInterval(t.step_func(function() {
+        function verifyDownloadNumber(url, number) {
+            var absolute_url = new URL(url, window.location.href);
+            assert_equals(performance.getEntriesByName(absolute_url).length, number, url);
+        }
+        if (loaded == expectedToLoad) {
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?media_all", 1);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?media_not_all", 0);
+            document.write('<img src="/WebKit/preload/resources/square.png?media_all">');
+            document.write('<img src="/WebKit/preload/resources/square.png?media_not_all">');
+            t.done();
+        }
+    }), 200);
+</script>
diff --git a/LayoutTests/http/wpt/preload/resources/square.png b/LayoutTests/http/wpt/preload/resources/square.png
new file mode 100644 (file)
index 0000000..567babb
Binary files /dev/null and b/LayoutTests/http/wpt/preload/resources/square.png differ
diff --git a/LayoutTests/http/wpt/preload/type-attribute-expected.txt b/LayoutTests/http/wpt/preload/type-attribute-expected.txt
new file mode 100644 (file)
index 0000000..eee54e6
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+PASS Makes sure that preloaded resources are not downloaded when the type is not supported. 
+
diff --git a/LayoutTests/http/wpt/preload/type-attribute.html b/LayoutTests/http/wpt/preload/type-attribute.html
new file mode 100644 (file)
index 0000000..c0ffd9f
--- /dev/null
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+    var loaded = 0;
+    var expectedToLoad = 6;
+</script>
+<link rel=preload href="/WebKit/preload/resources/square.png?img_good_type" as=image type="image/jpeg" onload="++loaded;">
+<link rel=preload href="/WebKit/preload/resources/square.png?img_svg_type" as=image type="image/jpeg" onload="++loaded;">
+<link rel=preload href="/WebKit/preload/resources/square.png?img_bad_type" as=image type="image/bla">
+<link rel=preload href="/WebKit/preload/resources/square.png?script_good_type" as=script type="text/javascript" onload="++loaded;">
+<link rel=preload href="/WebKit/preload/resources/square.png?script_bad_type" as=script type="text/fooscript">
+<link rel=preload href="/WebKit/preload/resources/square.png?style_good_type" as=style type="text/css" onload="++loaded;">
+<link rel=preload href="/WebKit/preload/resources/square.png?style_bad_type" as=style type="text/stylefoo">
+<link rel=preload href="/WebKit/preload/resources/square.png?font_good_type" as=font type="font/woff2" onload="++loaded;">
+<link rel=preload href="/WebKit/preload/resources/square.png?font_bad_type" as=font type="font/woffff">
+<link rel=preload href="/WebKit/preload/resources/square.png?track_good_type" as=track type="text/vtt" onload="++loaded;">
+<link rel=preload href="/WebKit/preload/resources/square.png?track_bad_type" as=track type="text/bar">
+<script src="/WebKit/preload/resources/dummy.js?pipe=trickle(d0.5)"></script>
+<script>
+    var t = async_test('Makes sure that preloaded resources are not downloaded when the type is not supported.');
+    window.setInterval(t.step_func(function() {
+        function verifyDownloadNumber(url, number) {
+            var absolute_url = new URL(url, window.location.href);
+            assert_equals(performance.getEntriesByName(absolute_url).length, number, url);
+        }
+        if (loaded == expectedToLoad) {
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?img_good_type", 1);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?img_svg_type", 1);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?img_bad_type", 0);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?script_good_type", 1);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?script_bad_type", 0);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?style_good_type", 1);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?style_bad_type", 0);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?font_good_type", 1);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?font_bad_type", 0);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?track_good_type", 1);
+            verifyDownloadNumber("/WebKit/preload/resources/square.png?track_bad_type", 0);
+            document.write('<img src="/WebKit/preload/resources/square.png?img_good_type">');
+            document.write('<img src="/WebKit/preload/resources/square.png?img_svg_type">');
+            document.write('<script src="/WebKit/preload/resources/square.png?script_good_type">');
+            document.write('<link href="/WebKit/preload/resources/square.png?script_good_type" rel=stylesheet>');
+            document.write('<style>@font-face { font-family:ahem; src: url(/WebKit/preload/resources/square.png?font_good_type); } span { font-family: ahem, Arial; } </style>');
+            document.write('<video><track kind=subtitles src="/WebKit/preload/resources/square.png?track_good_type" srclang=en></video>');
+            t.done();
+        }
+    }), 200);
+</script>
+<span>foo</span>
index c5e3148..0bf71fc 100644 (file)
@@ -5,3 +5,5 @@
 
 fast/multicol/flexbox-rows.html [ Skip ]
 workers/wasm-mem-post-message.html [ Failure ]
+
+http/tests/preload/viewport [ Pass ]
index 1a28159..f891bda 100644 (file)
@@ -15,6 +15,7 @@ quicklook [ Pass ]
 
 fast/text-autosizing/ios [ Pass ]
 fast/zooming/ios [ Pass ]
+http/tests/preload/viewport [ Pass ]
 
 #//////////////////////////////////////////////////////////////////////////////////////////
 # End platform-specific directories.
index 4f4a40e..a87cc4e 100644 (file)
@@ -1,3 +1,45 @@
+2017-05-22  Yoav Weiss  <yoav@yoav.ws>
+
+        [preload] Add media and type attribute support.
+        https://bugs.webkit.org/show_bug.cgi?id=171720
+
+        Reviewed by Youenn Fablet.
+
+        Tests: http/wpt/preload/media-attribute.html
+               http/wpt/preload/type-attribute.html
+               http/tests/preload/viewport/meta-viewport-link-headers.php
+
+        * css/MediaQueryEvaluator.cpp: Move the mediaAttributeMatches code from HTMLResourcePreloader to a central location.
+        (WebCore::MediaQueryEvaluator::mediaAttributeMatches):
+        * css/MediaQueryEvaluator.h:
+        * html/HTMLImageElement.cpp:
+        (WebCore::HTMLImageElement::bestFitSourceFromPictureElement): Use isSupportedImageOrSVGMIMEType() instead of checking SVG MIME type specifically.
+        * html/HTMLLinkElement.cpp:
+        (WebCore::HTMLLinkElement::process): Call loadLink() with the media and type attributes.
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::pumpTokenizer): Trigger Link header based preload for links that have the media attribute.
+        * html/parser/HTMLPreloadScanner.cpp:
+        (WebCore::TokenPreloadScanner::StartTagScanner::createPreloadRequest): Avoid preloading link resources with non-matching type.
+        (WebCore::TokenPreloadScanner::StartTagScanner::processAttribute): Collect the type attribute for link resources.
+        * html/parser/HTMLResourcePreloader.cpp:
+        (WebCore::HTMLResourcePreloader::preload): Use MediaQueryEvaluator::mediaAttributeMatches instead of the local one.
+        (WebCore::mediaAttributeMatches): Deleted.
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::receivedFirstData): Indicate that only link preloads with no media attribute should be loaded here.
+        * loader/LinkLoader.cpp:
+        (WebCore::LinkLoader::loadLinksFromHeader): Load only links with or without media attributes, according to mode. Also send media and
+        type attributes to preloadIfNeeded().
+        (WebCore::LinkLoader::isSupportedType): Check if the MIME type is supported for the CachedResource::Type.
+        (WebCore::LinkLoader::preloadIfNeeded): Get the media and type attributes and only trigger a preload if media matches and type is supported.
+        (WebCore::LinkLoader::loadLink): Pass along the media and type attributes.
+        * loader/LinkLoader.h:
+        * platform/MIMETypeRegistry.cpp:
+        (WebCore::MIMETypeRegistry::isSupportedImageOrSVGMIMEType): Check if MIME type is supported for an image, or is an SVG mime type.
+        (WebCore::MIMETypeRegistry::isSupportedStyleSheetMIMEType): Check if MIME type is supported for a stylesheet.
+        (WebCore::MIMETypeRegistry::isSupportedFontMIMEType): Check if MIME type is supported for a font.
+        (WebCore::MIMETypeRegistry::isSupportedTextTrackMIMEType): Check if MIME type is supported for a text track.
+        * platform/MIMETypeRegistry.h:
+
 2017-05-22  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         [CG] Use the SPI CGImageSourceGetTypeWithData() to get the typeIdentifierHint of an image
index f7027d2..3a4f9e4 100644 (file)
@@ -734,4 +734,11 @@ bool MediaQueryEvaluator::evaluate(const MediaQueryExpression& expression) const
     return function(expression.value(), { m_style, document.documentElement()->renderStyle(), document.renderView(), 1, false }, *m_frame, NoPrefix);
 }
 
+bool MediaQueryEvaluator::mediaAttributeMatches(Document& document, const String& attributeValue)
+{
+    ASSERT(document.renderView());
+    auto mediaQueries = MediaQuerySet::create(attributeValue);
+    return MediaQueryEvaluator { "screen", document, &document.renderView()->style() }.evaluate(mediaQueries.get());
+}
+
 } // namespace
index eae5e94..7ce2561 100644 (file)
@@ -70,6 +70,8 @@ public:
     // Evaluates a list of media queries and fills in a vector with any viewport-dependent results found.
     bool evaluate(const MediaQuerySet&, Vector<MediaQueryResult>&) const;
 
+    static bool mediaAttributeMatches(Document&, const String& attributeValue);
+
 private:
     String m_mediaType;
     Frame* m_frame { nullptr }; // not owned
index 80360e9..519ecff 100644 (file)
@@ -162,7 +162,7 @@ ImageCandidate HTMLImageElement::bestFitSourceFromPictureElement()
             String type = typeAttribute.string();
             type.truncate(type.find(';'));
             type = stripLeadingAndTrailingHTMLSpaces(type);
-            if (!type.isEmpty() && !MIMETypeRegistry::isSupportedImageMIMEType(type) && !equalLettersIgnoringASCIICase(type, "image/svg+xml"))
+            if (!type.isEmpty() && !MIMETypeRegistry::isSupportedImageOrSVGMIMEType(type))
                 continue;
         }
 
index a7d5e73..22e4c92 100644 (file)
@@ -232,7 +232,7 @@ void HTMLLinkElement::process()
 
     URL url = getNonEmptyURLAttribute(hrefAttr);
 
-    if (!m_linkLoader.loadLink(m_relAttribute, url, attributeWithoutSynchronization(asAttr), attributeWithoutSynchronization(crossoriginAttr), document()))
+    if (!m_linkLoader.loadLink(m_relAttribute, url, attributeWithoutSynchronization(asAttr), attributeWithoutSynchronization(mediaAttr), attributeWithoutSynchronization(typeAttr), attributeWithoutSynchronization(crossoriginAttr), document()))
         return;
 
     bool treatAsStyleSheet = m_relAttribute.isStyleSheet
index c3846db..caa6165 100644 (file)
@@ -36,6 +36,7 @@
 #include "HTMLTreeBuilder.h"
 #include "HTMLUnknownElement.h"
 #include "JSCustomElementInterface.h"
+#include "LinkLoader.h"
 #include "ScriptElement.h"
 
 namespace WebCore {
@@ -295,6 +296,9 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
         }
         m_preloadScanner->scan(*m_preloader, *document());
     }
+    // The viewport definition is known here, so we can load link preloads with media attributes.
+    if (document()->loader())
+        LinkLoader::loadLinksFromHeader(document()->loader()->response().httpHeaderField(HTTPHeaderName::Link), document()->url(), *document(), LinkLoader::MediaAttributeCheck::MediaAttributeNotEmpty);
 }
 
 void HTMLDocumentParser::constructTreeFromHTMLToken(HTMLTokenizer::TokenPtr& rawToken)
index 91968dc..46b91df 100644 (file)
@@ -149,6 +149,10 @@ public:
         auto type = resourceType();
         if (!type)
             return nullptr;
+
+        if (!LinkLoader::isSupportedType(type.value(), m_typeAttribute))
+            return nullptr;
+
         auto request = std::make_unique<PreloadRequest>(initiatorFor(m_tagId), m_urlToLoad, predictedBaseURL, type.value(), m_mediaAttribute, m_moduleScript);
         request->setCrossOriginMode(m_crossOriginMode);
         request->setNonce(m_nonceAttribute);
@@ -239,6 +243,8 @@ private:
                 m_nonceAttribute = attributeValue;
             else if (match(attributeName, asAttr))
                 m_asAttribute = attributeValue;
+            else if (match(attributeName, typeAttr))
+                m_typeAttribute = attributeValue;
             break;
         case TagId::Input:
             if (match(attributeName, srcAttr))
@@ -341,6 +347,7 @@ private:
     String m_nonceAttribute;
     String m_metaContent;
     String m_asAttribute;
+    String m_typeAttribute;
     bool m_metaIsViewport;
     bool m_inputIsImage;
     float m_deviceScaleFactor;
index 6236624..c9e3bb5 100644 (file)
@@ -29,7 +29,6 @@
 #include "CachedResourceLoader.h"
 #include "Document.h"
 
-#include "MediaList.h"
 #include "MediaQueryEvaluator.h"
 #include "RenderView.h"
 
@@ -71,17 +70,11 @@ void HTMLResourcePreloader::preload(PreloadRequestStream requests)
         preload(WTFMove(request));
 }
 
-static bool mediaAttributeMatches(Document& document, const RenderStyle* renderStyle, const String& attributeValue)
-{
-    auto mediaQueries = MediaQuerySet::create(attributeValue);
-    return MediaQueryEvaluator { "screen", document, renderStyle }.evaluate(mediaQueries.get());
-}
-
 void HTMLResourcePreloader::preload(std::unique_ptr<PreloadRequest> preload)
 {
     ASSERT(m_document.frame());
     ASSERT(m_document.renderView());
-    if (!preload->media().isEmpty() && !mediaAttributeMatches(m_document, &m_document.renderView()->style(), preload->media()))
+    if (!preload->media().isEmpty() && !MediaQueryEvaluator::mediaAttributeMatches(m_document, preload->media()))
         return;
 
     m_document.cachedResourceLoader().preload(preload->resourceType(), preload->resourceRequest(m_document));
index 933a383..690c4a7 100644 (file)
@@ -674,7 +674,7 @@ void FrameLoader::receivedFirstData()
     auto& document = *m_frame.document();
 
     ASSERT(m_frame.document());
-    LinkLoader::loadLinksFromHeader(m_documentLoader->response().httpHeaderField(HTTPHeaderName::Link), m_frame.document()->url(), *m_frame.document());
+    LinkLoader::loadLinksFromHeader(m_documentLoader->response().httpHeaderField(HTTPHeaderName::Link), m_frame.document()->url(), *m_frame.document(), LinkLoader::MediaAttributeCheck::MediaAttributeEmpty);
 
     double delay;
     String urlString;
index 9b53ce8..cb1a469 100644 (file)
@@ -46,6 +46,8 @@
 #include "LinkHeader.h"
 #include "LinkPreloadResourceClients.h"
 #include "LinkRelAttribute.h"
+#include "MIMETypeRegistry.h"
+#include "MediaQueryEvaluator.h"
 #include "RuntimeEnabledFeatures.h"
 #include "Settings.h"
 #include "StyleResolver.h"
@@ -84,7 +86,7 @@ void LinkLoader::notifyFinished(CachedResource& resource)
     m_cachedLinkResource = nullptr;
 }
 
-void LinkLoader::loadLinksFromHeader(const String& headerValue, const URL& baseURL, Document& document)
+void LinkLoader::loadLinksFromHeader(const String& headerValue, const URL& baseURL, Document& document, MediaAttributeCheck mediaAttributeCheck)
 {
     if (headerValue.isEmpty())
         return;
@@ -92,13 +94,20 @@ void LinkLoader::loadLinksFromHeader(const String& headerValue, const URL& baseU
     for (auto& header : headerSet) {
         if (!header.valid() || header.url().isEmpty() || header.rel().isEmpty())
             continue;
+        if (mediaAttributeCheck == MediaAttributeCheck::MediaAttributeNotEmpty) {
+            if (header.media().isEmpty())
+                continue;
+        } else {
+            if (!header.media().isEmpty())
+                continue;
+        }
 
         LinkRelAttribute relAttribute(header.rel());
         URL url(baseURL, header.url());
         // Sanity check to avoid re-entrancy here.
         if (equalIgnoringFragmentIdentifier(url, baseURL))
             continue;
-        preloadIfNeeded(relAttribute, url, document, header.as(), header.crossOrigin(), nullptr, nullptr);
+        preloadIfNeeded(relAttribute, url, document, header.as(), header.media(), header.mimeType(), header.crossOrigin(), nullptr, nullptr);
     }
 }
 
@@ -158,7 +167,34 @@ static std::unique_ptr<LinkPreloadResourceClient> createLinkPreloadResourceClien
     return nullptr;
 }
 
-std::unique_ptr<LinkPreloadResourceClient> LinkLoader::preloadIfNeeded(const LinkRelAttribute& relAttribute, const URL& href, Document& document, const String& as, const String& crossOriginMode, LinkLoader* loader, LinkLoaderClient* client)
+bool LinkLoader::isSupportedType(CachedResource::Type resourceType, const String& mimeType)
+{
+    if (mimeType.isEmpty())
+        return true;
+    switch (resourceType) {
+    case CachedResource::ImageResource:
+        return MIMETypeRegistry::isSupportedImageOrSVGMIMEType(mimeType);
+    case CachedResource::Script:
+        return MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType);
+    case CachedResource::CSSStyleSheet:
+        return MIMETypeRegistry::isSupportedStyleSheetMIMEType(mimeType);
+    case CachedResource::FontResource:
+        return MIMETypeRegistry::isSupportedFontMIMEType(mimeType);
+    case CachedResource::MediaResource:
+        return MIMETypeRegistry::isSupportedMediaMIMEType(mimeType);
+#if ENABLE(VIDEO_TRACK)
+    case CachedResource::TextTrackResource:
+        return MIMETypeRegistry::isSupportedTextTrackMIMEType(mimeType);
+#endif
+    case CachedResource::RawResource:
+        return true;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return false;
+}
+
+std::unique_ptr<LinkPreloadResourceClient> LinkLoader::preloadIfNeeded(const LinkRelAttribute& relAttribute, const URL& href, Document& document, const String& as, const String& media, const String& mimeType, const String& crossOriginMode, LinkLoader* loader, LinkLoaderClient* client)
 {
     if (!document.loader() || !relAttribute.isLinkPreload)
         return nullptr;
@@ -175,6 +211,10 @@ std::unique_ptr<LinkPreloadResourceClient> LinkLoader::preloadIfNeeded(const Lin
             client->linkLoadingErrored();
         return nullptr;
     }
+    if (!MediaQueryEvaluator::mediaAttributeMatches(document, media))
+        return nullptr;
+    if (!isSupportedType(type.value(), mimeType))
+        return nullptr;
 
     ResourceRequest resourceRequest(document.completeURL(href));
     resourceRequest.setIgnoreForRequestCount(true);
@@ -196,7 +236,7 @@ void LinkLoader::cancelLoad()
         m_preloadResourceClient->clear();
 }
 
-bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const URL& href, const String& as, const String& crossOrigin, Document& document)
+bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const URL& href, const String& as, const String& media, const String& mimeType, const String& crossOrigin, Document& document)
 {
     if (relAttribute.isDNSPrefetch) {
         // FIXME: The href attribute of the link element can be in "//hostname" form, and we shouldn't attempt
@@ -206,7 +246,7 @@ bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const URL& href,
     }
 
     if (m_client.shouldLoadLink()) {
-        auto resourceClient = preloadIfNeeded(relAttribute, href, document, as, crossOrigin, this, &m_client);
+        auto resourceClient = preloadIfNeeded(relAttribute, href, document, as, media, mimeType, crossOrigin, this, &m_client);
         if (resourceClient)
             m_preloadResourceClient = WTFMove(resourceClient);
         else if (m_preloadResourceClient)
index 9c71472..bde2c77 100644 (file)
@@ -51,9 +51,12 @@ public:
     explicit LinkLoader(LinkLoaderClient&);
     virtual ~LinkLoader();
 
-    bool loadLink(const LinkRelAttribute&, const URL&, const String& as, const String& crossOrigin, Document&);
+    bool loadLink(const LinkRelAttribute&, const URL&, const String& as, const String& media, const String& type, const String& crossOrigin, Document&);
     static std::optional<CachedResource::Type> resourceTypeFromAsAttribute(const String& as);
-    static void loadLinksFromHeader(const String& headerValue, const URL& baseURL, Document&);
+
+    enum class MediaAttributeCheck { MediaAttributeEmpty, MediaAttributeNotEmpty };
+    static void loadLinksFromHeader(const String& headerValue, const URL& baseURL, Document&, MediaAttributeCheck);
+    static bool isSupportedType(CachedResource::Type, const String& mimeType);
 
     WeakPtr<LinkLoader> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
     void triggerEvents(const CachedResource&);
@@ -61,7 +64,7 @@ public:
 
 private:
     void notifyFinished(CachedResource&) override;
-    static std::unique_ptr<LinkPreloadResourceClient> preloadIfNeeded(const LinkRelAttribute&, const URL& href, Document&, const String& as, const String& crossOriginMode, LinkLoader*, LinkLoaderClient*);
+    static std::unique_ptr<LinkPreloadResourceClient> preloadIfNeeded(const LinkRelAttribute&, const URL& href, Document&, const String& as, const String& media, const String& type, const String& crossOriginMode, LinkLoader*, LinkLoaderClient*);
 
     LinkLoaderClient& m_client;
     CachedResourceHandle<CachedResource> m_cachedLinkResource;
index 81be9c5..3d6c8d7 100644 (file)
@@ -483,6 +483,11 @@ bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
     return supportedImageMIMETypes->contains(getNormalizedMIMEType(mimeType));
 }
 
+bool MIMETypeRegistry::isSupportedImageOrSVGMIMEType(const String& mimeType)
+{
+    return isSupportedImageMIMEType(mimeType) || equalLettersIgnoringASCIICase(mimeType, "image/svg+xml");
+}
+
 bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
 {
     if (mimeType.isEmpty())
@@ -512,6 +517,24 @@ bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
     return supportedJavaScriptMIMETypes->contains(mimeType);
 }
 
+bool MIMETypeRegistry::isSupportedStyleSheetMIMEType(const String& mimeType)
+{
+    return equalLettersIgnoringASCIICase(mimeType, "text/css");
+}
+
+bool MIMETypeRegistry::isSupportedFontMIMEType(const String& mimeType)
+{
+    static const unsigned fontLen = 5;
+    if (!mimeType.startsWithIgnoringASCIICase("font/"))
+        return false;
+    String subType = mimeType.substring(fontLen);
+    return equalLettersIgnoringASCIICase(subType, "woff")
+        || equalLettersIgnoringASCIICase(subType, "woff2")
+        || equalLettersIgnoringASCIICase(subType, "otf")
+        || equalLettersIgnoringASCIICase(subType, "ttf")
+        || equalLettersIgnoringASCIICase(subType, "sfnt");
+}
+
 bool MIMETypeRegistry::isSupportedJSONMIMEType(const String& mimeType)
 {
     if (mimeType.isEmpty())
@@ -548,6 +571,11 @@ bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType)
     return supportedMediaMIMETypes->contains(mimeType);
 }
 
+bool MIMETypeRegistry::isSupportedTextTrackMIMEType(const String& mimeType)
+{
+    return equalLettersIgnoringASCIICase(mimeType, "text/vtt");
+}
+
 bool MIMETypeRegistry::isUnsupportedTextMIMEType(const String& mimeType)
 {
     if (mimeType.isEmpty())
index 8753d47..0664a48 100644 (file)
@@ -47,6 +47,9 @@ public:
     // image (e.g., <img> tags).
     WEBCORE_EXPORT static bool isSupportedImageMIMEType(const String& mimeType);
 
+    // Check to see if a MIME type is suitable for being loaded as an image, including SVG.
+    WEBCORE_EXPORT static bool isSupportedImageOrSVGMIMEType(const String& mimeType);
+
     // Check to see if a MIME type is suitable for being loaded as an image
     // document in a frame.
     WEBCORE_EXPORT static bool isSupportedImageResourceMIMEType(const String& mimeType);
@@ -58,6 +61,12 @@ public:
     static bool isSupportedJavaScriptMIMEType(const String& mimeType);
     static bool isSupportedJSONMIMEType(const String& mimeType);
 
+    // Check to see if a MIME type is suitable for being loaded as a style sheet.
+    static bool isSupportedStyleSheetMIMEType(const String& mimeType);
+
+    // Check to see if a MIME type is suitable for being loaded as a font.
+    static bool isSupportedFontMIMEType(const String& mimeType);
+
     // Check to see if a non-image MIME type is suitable for being loaded as a
     // document in a frame. Includes supported JavaScript MIME types.
     WEBCORE_EXPORT static bool isSupportedNonImageMIMEType(const String& mimeType);
@@ -65,6 +74,9 @@ public:
     // Check to see if a MIME type is suitable for being loaded using <video> and <audio>.
     WEBCORE_EXPORT static bool isSupportedMediaMIMEType(const String& mimeType);
 
+    // Check to see if a MIME type is suitable for being loaded using <track>>.
+    WEBCORE_EXPORT static bool isSupportedTextTrackMIMEType(const String& mimeType);
+
     // Check to see if a MIME type is a valid Java applet mime type.
     WEBCORE_EXPORT static bool isJavaAppletMIMEType(const String& mimeType);