Include 'video/*' in image request Accept header if browser supports video media...
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Dec 2017 08:49:26 +0000 (08:49 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Dec 2017 08:49:26 +0000 (08:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=179178

Reviewed by Alex Christensen.

Source/WebCore:

Test: http/tests/images/image-supports-video.html

Ensure that 'video/*' is included in the Accept header by asking the ImageDecoder whether "Video"
media is supported. The ImageDecoder will ask all it's constituent decoders, which aside from
ImageDecoderAVFObjC will say only support the "Image" media type.

Drive-by fix: Make sure the MIMETypeRegistry includes all the types supported by AVFoundation when
ImageDecoderAVFObjC is enabled. Also, now that Image reports it can support video mime types, check
whether MediaDocument can support a given mime type before asking ImageDocument.

* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::bestFitSourceFromPictureElement):
* loader/LinkLoader.cpp:
(WebCore::LinkLoader::isSupportedType):
* loader/cache/CachedResourceRequest.cpp:
(WebCore::acceptHeaderValueFromType):
* platform/MIMETypeRegistry.cpp:
(WebCore::MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType):
(WebCore::MIMETypeRegistry::isSupportedImageOrSVGMIMEType): Deleted.
* platform/MIMETypeRegistry.h:
* platform/graphics/ImageDecoder.cpp:
(WebCore::ImageDecoder::supportsMediaType):
* platform/graphics/ImageDecoder.h:
* platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.h:
(WebCore::ImageDecoderAVFObjC::supportsMediaType):
* platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm:
(WebCore::ImageDecoderAVFObjC::supportsContentType):
* platform/graphics/cg/ImageDecoderCG.h:
* platform/graphics/win/ImageDecoderDirect2D.h:
* platform/image-decoders/ScalableImageDecoder.h:
(WebCore::ScalableImageDecoder::supportsMediaType):
* html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):

LayoutTests:

* http/tests/images/image-supports-video-expected.txt: Added.
* http/tests/images/image-supports-video.html: Added.
* http/tests/misc/resources/image-checks-for-accept.php:
* http/tests/resources/redirect-to-video-if-accepted.php: Added.
* platform/ios/TestExpectations:
* platform/mac/imported/w3c/web-platform-tests/html/semantics/the-img-element/update-the-source-set-expected.txt: Added.

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

21 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/images/image-supports-video-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/images/image-supports-video.html [new file with mode: 0644]
LayoutTests/http/tests/misc/resources/image-checks-for-accept.php
LayoutTests/http/tests/resources/redirect-to-video-if-accepted.php [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/mac/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLImageElement.cpp
Source/WebCore/html/parser/HTMLPreloadScanner.cpp
Source/WebCore/loader/LinkLoader.cpp
Source/WebCore/loader/cache/CachedResourceRequest.cpp
Source/WebCore/platform/MIMETypeRegistry.cpp
Source/WebCore/platform/MIMETypeRegistry.h
Source/WebCore/platform/graphics/ImageDecoder.cpp
Source/WebCore/platform/graphics/ImageDecoder.h
Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm
Source/WebCore/platform/graphics/cg/ImageDecoderCG.h
Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h
Source/WebCore/platform/image-decoders/ScalableImageDecoder.h

index 7835aba..074f71a 100644 (file)
@@ -1,3 +1,17 @@
+2017-12-04  Jer Noble  <jer.noble@apple.com>
+
+        Include 'video/*' in image request Accept header if browser supports video media in image contexts.
+        https://bugs.webkit.org/show_bug.cgi?id=179178
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/images/image-supports-video-expected.txt: Added.
+        * http/tests/images/image-supports-video.html: Added.
+        * http/tests/misc/resources/image-checks-for-accept.php:
+        * http/tests/resources/redirect-to-video-if-accepted.php: Added.
+        * platform/ios/TestExpectations:
+        * platform/mac/imported/w3c/web-platform-tests/html/semantics/the-img-element/update-the-source-set-expected.txt: Added.
+
 2017-12-03  Chris Dumez  <cdumez@apple.com>
 
         Re-sync Service Workers web-platform-tests from upstream
diff --git a/LayoutTests/http/tests/images/image-supports-video-expected.txt b/LayoutTests/http/tests/images/image-supports-video-expected.txt
new file mode 100644 (file)
index 0000000..ee7639d
--- /dev/null
@@ -0,0 +1,2 @@
+  
+PASS: video source selected.
diff --git a/LayoutTests/http/tests/images/image-supports-video.html b/LayoutTests/http/tests/images/image-supports-video.html
new file mode 100644 (file)
index 0000000..24d75f4
--- /dev/null
@@ -0,0 +1,36 @@
+<picture>
+    <source srcset="/resources/redirect-to-video-if-accepted.php?video=test.mp4" type="video/mp4">
+    <source srcset="/resources/redirect-to-video-if-accepted.php?video=test.ogv" type="video/ogv">
+    <img src="/resources/square100.png">
+</picture>
+<br>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText(true);
+    testRunner.waitUntilDone();
+}
+
+function endTest() {
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function logResult(text) {
+    document.body.appendChild(document.createTextNode(text));
+}
+
+var img = document.querySelector('img');
+img.addEventListener('load', event => {
+    if (img.currentSrc.endsWith('square100.png'))
+        logResult('FAIL: <img> fallback selected.');
+    else
+        logResult('PASS: video source selected.');
+
+    endTest();
+});
+
+img.addEventListener('error', event => {
+    logResult('FAIL: <img> threw error.');
+    endTest();
+});
+</script>
index 5e5cdc6..e5470fb 100644 (file)
@@ -1,5 +1,6 @@
 <?php
-    if($_SERVER["HTTP_ACCEPT"] == "image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5")
+    if($_SERVER["HTTP_ACCEPT"] == "image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"
+        || $_SERVER["HTTP_ACCEPT"] == "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5")
     {
         header("Content-Type: image/jpg");
         header("Cache-Control: no-store");
diff --git a/LayoutTests/http/tests/resources/redirect-to-video-if-accepted.php b/LayoutTests/http/tests/resources/redirect-to-video-if-accepted.php
new file mode 100644 (file)
index 0000000..e614e16
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+if (strpos($_SERVER['HTTP_ACCEPT'], 'video/*') !== false) {
+    header('HTTP/1.1 301 Moved Permanently');
+    header('Location: ' . $_GET['video']);
+    return;
+}
+
+header('HTTP/1.1 400 Bad Request');
+?>
index 605f3dc..46b37f4 100644 (file)
@@ -3302,3 +3302,6 @@ media/modern-media-controls/time-labels-support/elapsed-time.html [ Skip ]
 
 # Skip WebGL while the ANGLE update has caused many failures
 webgl [ Skip ]
+
+# Requries AVFoundation support <rdar://problem/34502208>
+http/tests/images/image-supports-video.html
diff --git a/LayoutTests/platform/mac/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt b/LayoutTests/platform/mac/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt
new file mode 100644 (file)
index 0000000..4ea9004
--- /dev/null
@@ -0,0 +1,180 @@
+
+PASS <img data-expect=""> 
+FAIL <img src="" data-expect=""> assert_equals: expected "" but got "http://localhost:8800/html/semantics/embedded-content/the-img-element/update-the-source-set.html"
+PASS <img src="data:,a" data-expect="data:,a"> 
+PASS <img srcset="" src="data:,a" data-expect="data:,a"> 
+PASS <img srcset="data:,b" src="data:,a" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b" data-expect="data:,b"><!-- srcset after src --> 
+PASS <img src="data:,a" srcset="data:,b 1x" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 1.0x" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 1e0x" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 10000w" sizes="1px" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 10000w, data:,c 10000x" sizes="1px" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 10000x, data:,c 10000w" sizes="1px" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 1w" sizes="10000px" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 1w, data:,c 0.0001x" sizes="10000px" data-expect="data:,b"> 
+PASS <img src="data:,a" srcset="data:,b 0.0001x, data:,c 1w" sizes="10000px" data-expect="data:,b"> 
+PASS <img srcset="data:,a" data-expect="data:,a"> 
+PASS <picture>foo<img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><!--foo--><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><br><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><p></p><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><video><source srcset="data:,b"></video><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><span><source srcset="data:,b"></span><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><svg><source srcset="data:,b"></source></svg><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><svg></svg><source srcset="data:,b"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><svg><font></font><source srcset="data:,b"></source></svg><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><svg><!--<font face> tag breaks out of svg--></svg><font face=""></font><source srcset="data:,b"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><img src="data:,a"><img src="data:,b" data-expect="data:,b"></picture> 
+PASS <picture><source><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source src="data:,b"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset=""><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset=", ,"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b 1x 1x"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media=""><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" media="all"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" media="all and (min-width:0)"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" media="all and !"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media="all and (!)"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media="not all"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media="not all and (min-width:0)"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media="not all and (max-width:0)"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" media="not all and !"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media="not all and (!)"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media="all, !"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" media=","><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" media=", all"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type=""><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type=" "><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type=" image/gif"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif "><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif;"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif;encodings"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif;encodings="><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif;encodings=foobar"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/png"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/jpeg"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/svg+xml"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="image/x-icon"><img src="data:,a" data-expect="data:,b"></picture> 
+PASS <picture><source srcset="data:,b" type="text/xml"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="text/html"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="text/plain"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="text/css"><img src="data:,a" data-expect="data:,a"></picture> 
+FAIL <picture><source srcset="data:,b" type="video/mp4"><img src="data:,a" data-expect="data:,a"></picture> assert_equals: expected "data:,a" but got "data:,b"
+PASS <picture><source srcset="data:,b" type="video/ogg"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="video/webm"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="unknown/unknown"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="application/octet-stream"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="application/x-shockwave-flash"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="image\gif"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="gif"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type=".gif"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="*"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="*/*"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="image/*"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type=","><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif, image/png"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="image/gif image/png"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><source srcset="data:,b" type="image/foobarbaz"><img src="data:,a" data-expect="data:,a"></picture> 
+PASS <picture><img src="data:,a" data-expect="data:,a">foo</picture> 
+PASS <picture><img src="data:,a" data-expect="data:,a"><br></picture> 
+PASS <picture><img src="data:,a" data-expect="data:,a"><!--foo--></picture> 
+PASS <picture><img src="data:,a" data-expect="data:,a"><img src="data:,b"></picture> 
+PASS <picture><img data-expect=""><img src="data:,b"></picture> 
+PASS <picture><img src="data:,a" data-expect="data:,a"><source srcset="data:,b"></picture> 
+PASS <picture><img data-expect=""><source srcset="data:,b"></picture> 
+PASS <picture><span><source srcset="data:,b"><img data-expect=""></span></picture> 
+PASS <picture><span><source srcset="data:,b"><img src="data:,a" data-expect="data:,a"></span></picture> 
+PASS <picture><source srcset="data:,b"><span><img src="data:,a" data-expect="data:,a"></span></picture> 
+PASS <picture><source srcset="data:,b"><img data-expect="data:,b"></picture> 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+foo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+foo
+
+
+
+
+
+
+
+
+
+
index 09babf5..1d6cedc 100644 (file)
@@ -1,3 +1,44 @@
+2017-12-04  Jer Noble  <jer.noble@apple.com>
+
+        Include 'video/*' in image request Accept header if browser supports video media in image contexts.
+        https://bugs.webkit.org/show_bug.cgi?id=179178
+
+        Reviewed by Alex Christensen.
+
+        Test: http/tests/images/image-supports-video.html
+
+        Ensure that 'video/*' is included in the Accept header by asking the ImageDecoder whether "Video"
+        media is supported. The ImageDecoder will ask all it's constituent decoders, which aside from
+        ImageDecoderAVFObjC will say only support the "Image" media type.
+
+        Drive-by fix: Make sure the MIMETypeRegistry includes all the types supported by AVFoundation when
+        ImageDecoderAVFObjC is enabled. Also, now that Image reports it can support video mime types, check
+        whether MediaDocument can support a given mime type before asking ImageDocument.
+
+        * html/HTMLImageElement.cpp:
+        (WebCore::HTMLImageElement::bestFitSourceFromPictureElement):
+        * loader/LinkLoader.cpp:
+        (WebCore::LinkLoader::isSupportedType):
+        * loader/cache/CachedResourceRequest.cpp:
+        (WebCore::acceptHeaderValueFromType):
+        * platform/MIMETypeRegistry.cpp:
+        (WebCore::MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType):
+        (WebCore::MIMETypeRegistry::isSupportedImageOrSVGMIMEType): Deleted.
+        * platform/MIMETypeRegistry.h:
+        * platform/graphics/ImageDecoder.cpp:
+        (WebCore::ImageDecoder::supportsMediaType):
+        * platform/graphics/ImageDecoder.h:
+        * platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.h:
+        (WebCore::ImageDecoderAVFObjC::supportsMediaType):
+        * platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm:
+        (WebCore::ImageDecoderAVFObjC::supportsContentType):
+        * platform/graphics/cg/ImageDecoderCG.h:
+        * platform/graphics/win/ImageDecoderDirect2D.h:
+        * platform/image-decoders/ScalableImageDecoder.h:
+        (WebCore::ScalableImageDecoder::supportsMediaType):
+        * html/parser/HTMLPreloadScanner.cpp:
+        (WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
+
 2017-12-03  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         WTF shouldn't have both Thread and ThreadIdentifier
index 6f6b4da..42c3d6e 100644 (file)
@@ -163,7 +163,7 @@ ImageCandidate HTMLImageElement::bestFitSourceFromPictureElement()
             String type = typeAttribute.string();
             type.truncate(type.find(';'));
             type = stripLeadingAndTrailingHTMLSpaces(type);
-            if (!type.isEmpty() && !MIMETypeRegistry::isSupportedImageOrSVGMIMEType(type))
+            if (!type.isEmpty() && !MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType(type))
                 continue;
         }
 
index 5ab457b..3623615 100644 (file)
@@ -223,7 +223,7 @@ private:
             if (match(attributeName, typeAttr) && m_typeAttribute.isNull()) {
                 // when multiple type attributes present: first value wins, ignore subsequent (to match ImageElement parser and Blink behaviours)
                 m_typeAttribute = attributeValue;
-                m_typeMatched &= MIMETypeRegistry::isSupportedImageOrSVGMIMEType(m_typeAttribute);
+                m_typeMatched &= MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType(m_typeAttribute);
             }
             break;
         case TagId::Script:
index f7cc579..eb80e84 100644 (file)
@@ -181,7 +181,7 @@ bool LinkLoader::isSupportedType(CachedResource::Type resourceType, const String
         return true;
     switch (resourceType) {
     case CachedResource::ImageResource:
-        return MIMETypeRegistry::isSupportedImageOrSVGMIMEType(mimeType);
+        return MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType(mimeType);
     case CachedResource::Script:
         return MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType);
     case CachedResource::CSSStyleSheet:
index b116128..17b1d97 100644 (file)
@@ -33,6 +33,7 @@
 #include "Element.h"
 #include "FrameLoader.h"
 #include "HTTPHeaderValues.h"
+#include "ImageDecoder.h"
 #include "MemoryCache.h"
 #include "SecurityPolicy.h"
 #include <wtf/NeverDestroyed.h>
@@ -145,6 +146,8 @@ static inline String acceptHeaderValueFromType(CachedResource::Type type)
     case CachedResource::Type::MainResource:
         return ASCIILiteral("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
     case CachedResource::Type::ImageResource:
+        if (ImageDecoder::supportsMediaType(ImageDecoder::MediaType::Video))
+            return ASCIILiteral("image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5");
         return ASCIILiteral("image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5");
     case CachedResource::Type::CSSStyleSheet:
         return ASCIILiteral("text/css,*/*;q=0.1");
index e578667..5144eb7 100644 (file)
 #include "ArchiveFactory.h"
 #endif
 
+#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#include "ContentType.h"
+#include "ImageDecoderAVFObjC.h"
+#endif
+
 namespace WebCore {
 
 static HashSet<String, ASCIICaseInsensitiveHash>* supportedImageResourceMIMETypes;
@@ -450,9 +455,17 @@ bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
     return supportedImageMIMETypes->contains(getNormalizedMIMEType(mimeType));
 }
 
-bool MIMETypeRegistry::isSupportedImageOrSVGMIMEType(const String& mimeType)
+bool MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType(const String& mimeType)
 {
-    return isSupportedImageMIMEType(mimeType) || equalLettersIgnoringASCIICase(mimeType, "image/svg+xml");
+    if (isSupportedImageMIMEType(mimeType) || equalLettersIgnoringASCIICase(mimeType, "image/svg+xml"))
+        return true;
+
+#if HAVE(AVSAMPLEBUFFERGENERATOR)
+    if (ImageDecoderAVFObjC::supportsContentType(ContentType(mimeType)))
+        return true;
+#endif
+
+    return false;
 }
 
 bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
index 8e14317..3bfc4e4 100644 (file)
@@ -47,8 +47,8 @@ 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, including SVG and Video (where supported).
+    WEBCORE_EXPORT static bool isSupportedImageVideoOrSVGMIMEType(const String& mimeType);
 
     // Check to see if a MIME type is suitable for being loaded as an image
     // document in a frame.
index a5d4943..aca09dc 100644 (file)
@@ -58,4 +58,26 @@ RefPtr<ImageDecoder> ImageDecoder::create(SharedBuffer& data, const String& mime
 #endif
 }
 
+bool ImageDecoder::supportsMediaType(MediaType type)
+{
+    bool supports = false;
+#if HAVE(AVSAMPLEBUFFERGENERATOR)
+    if (ImageDecoderAVFObjC::supportsMediaType(type))
+        supports = true;
+#endif
+
+#if USE(CG)
+    if (ImageDecoderCG::supportsMediaType(type))
+        supports = true;
+#elif USE(DIRECT2D)
+    if (ImageDecoderDirect2D::supportsMediaType(type))
+        supports = true;
+#else
+    if (ScalableImageDecoder::supportsMediaType(type))
+        supports = true;
+#endif
+
+    return supports;
+}
+
 }
index 8ade1ae..be9126b 100644 (file)
@@ -46,6 +46,12 @@ public:
     static RefPtr<ImageDecoder> create(SharedBuffer&, const String& mimeType, AlphaOption, GammaAndColorProfileOption);
     virtual ~ImageDecoder() = default;
 
+    enum class MediaType {
+        Image,
+        Video,
+    };
+    static bool supportsMediaType(MediaType);
+
     virtual size_t bytesDecodedToDetermineProperties() const = 0;
 
     virtual EncodedDataStatus encodedDataStatus() const = 0;
index ba11562..d27caf9 100644 (file)
@@ -48,6 +48,7 @@ class MediaTime;
 
 namespace WebCore {
 
+class ContentType;
 class PixelBufferConformerCV;
 class WebCoreDecompressionSession;
 
@@ -56,6 +57,9 @@ public:
     static RefPtr<ImageDecoderAVFObjC> create(SharedBuffer&, const String& mimeType, AlphaOption, GammaAndColorProfileOption);
     virtual ~ImageDecoderAVFObjC();
 
+    static bool supportsMediaType(MediaType);
+    static bool supportsContentType(const ContentType&);
+
     size_t bytesDecodedToDetermineProperties() const override { return 0; }
     static bool canDecodeType(const String& mimeType);
 
index 93f271b..06102c3 100644 (file)
@@ -28,7 +28,9 @@
 
 #if HAVE(AVSAMPLEBUFFERGENERATOR)
 
+#import "AVFoundationMIMETypeCache.h"
 #import "AffineTransform.h"
+#import "ContentType.h"
 #import "FloatQuad.h"
 #import "FloatRect.h"
 #import "FloatSize.h"
@@ -309,8 +311,25 @@ ImageDecoderAVFObjC::ImageDecoderAVFObjC(SharedBuffer& data, const String& mimeT
 
 ImageDecoderAVFObjC::~ImageDecoderAVFObjC() = default;
 
+bool ImageDecoderAVFObjC::supportsMediaType(MediaType type)
+{
+    if (type == MediaType::Video)
+        return getAVURLAssetClass() && canLoad_VideoToolbox_VTCreateCGImageFromCVPixelBuffer();
+    return false;
+}
+
+bool ImageDecoderAVFObjC::supportsContentType(const ContentType& type)
+{
+    if (getAVURLAssetClass() && canLoad_VideoToolbox_VTCreateCGImageFromCVPixelBuffer())
+        return AVFoundationMIMETypeCache::singleton().types().contains(type.containerType());
+    return false;
+}
+
 bool ImageDecoderAVFObjC::canDecodeType(const String& mimeType)
 {
+    if (!supportsMediaType(MediaType::Video))
+        return nullptr;
+
     return [getAVURLAssetClass() isPlayableExtendedMIMEType:mimeType];
 }
 
index 0e370b0..95cacab 100644 (file)
@@ -38,6 +38,8 @@ public:
     {
         return adoptRef(*new ImageDecoderCG(data, alphaOption, gammaAndColorProfileOption));
     }
+
+    static bool supportsMediaType(MediaType type) { return type == MediaType::Image; }
     
     size_t bytesDecodedToDetermineProperties() const final;
 
index fc1cfa8..abf5fcc 100644 (file)
@@ -47,6 +47,8 @@ public:
         return adoptRef(*new ImageDecoderDirect2D());
     }
 
+    static bool supportsMediaType(MediaType type) { return type == MediaType::Image; }
+
     static size_t bytesDecodedToDetermineProperties();
 
     String filenameExtension() const final;
index 7545262..daf58d4 100644 (file)
@@ -56,6 +56,8 @@ public:
     {
     }
 
+    static bool supportsMediaType(MediaType type) { return type == MediaType::Image; }
+
     // Returns nullptr if we can't sniff a supported type from the provided data (possibly
     // because there isn't enough data yet).
     static RefPtr<ScalableImageDecoder> create(SharedBuffer& data, AlphaOption, GammaAndColorProfileOption);