Implement OffscreenCanvas.convertToBlob
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Dec 2019 16:22:44 +0000 (16:22 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Dec 2019 16:22:44 +0000 (16:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=202573

Patch by Chris Lord <clord@igalia.com> on 2019-12-13
Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Update with fixed worker tests and SecurityError checks. See wpe
issues #20694 and #20698.

* web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob-expected.txt:
* web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.html:
* web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.w-expected.txt:
* web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.w.html:

Source/WebCore:

Implement OffscreenCanvas.convertToBlob. This also involves making
isSupportedImageMIMETypeForEncoding safe to use off the main thread,
and implementing OffscreenCanvas.securityOrigin.

No new tests, these changes fix existing tests.

* html/OffscreenCanvas.cpp:
(WebCore::toEncodingMimeType):
(WebCore::qualityFromDouble):
(WebCore::OffscreenCanvas::convertToBlob):
(WebCore::OffscreenCanvas::securityOrigin const):
* html/OffscreenCanvas.h:
* html/OffscreenCanvas.idl:
* platform/MIMETypeRegistry.cpp:
(WebCore::MIMETypeRegistry::createMIMETypeRegistryThreadGlobalData):
(WebCore::MIMETypeRegistry::isSupportedImageMIMETypeForEncoding):
* platform/MIMETypeRegistry.h:
(WebCore::MIMETypeRegistryThreadGlobalData::MIMETypeRegistryThreadGlobalData):
(WebCore::MIMETypeRegistryThreadGlobalData::supportedImageMIMETypesForEncoding const):
* platform/ThreadGlobalData.cpp:
(WebCore::ThreadGlobalData::mimeTypeRegistryThreadGlobalData):
* platform/ThreadGlobalData.h:
* workers/WorkerGlobalScope.h:

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

14 files changed:
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob-expected.txt
LayoutTests/imported/w3c/web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.html
LayoutTests/imported/w3c/web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.w-expected.txt
LayoutTests/imported/w3c/web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.w.html
Source/WebCore/ChangeLog
Source/WebCore/html/OffscreenCanvas.cpp
Source/WebCore/html/OffscreenCanvas.h
Source/WebCore/html/OffscreenCanvas.idl
Source/WebCore/platform/MIMETypeRegistry.cpp
Source/WebCore/platform/MIMETypeRegistry.h
Source/WebCore/platform/ThreadGlobalData.cpp
Source/WebCore/platform/ThreadGlobalData.h
Source/WebCore/workers/WorkerGlobalScope.h

index 4a00d36..6c9cc27 100644 (file)
@@ -1,3 +1,18 @@
+2019-12-13  Chris Lord  <clord@igalia.com>
+
+        Implement OffscreenCanvas.convertToBlob
+        https://bugs.webkit.org/show_bug.cgi?id=202573
+
+        Reviewed by Darin Adler.
+
+        Update with fixed worker tests and SecurityError checks. See wpe
+        issues #20694 and #20698.
+
+        * web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob-expected.txt:
+        * web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.html:
+        * web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.w-expected.txt:
+        * web-platform-tests/offscreen-canvas/convert-to-blob/offscreencanvas.convert.to.blob.w.html:
+
 2019-12-12  Chris Dumez  <cdumez@apple.com>
 
         Re-sync service-workers web-platform-tests from upstream
index a2c4b53..8fd9ea9 100644 (file)
@@ -1,8 +1,9 @@
 
-FAIL Test that convertToBlob with default type produces correct result offscreenCanvas.convertToBlob is not a function. (In 'offscreenCanvas.convertToBlob()', 'offscreenCanvas.convertToBlob' is undefined)
-FAIL Test that convertToBlob with png produces correct result offscreenCanvas.convertToBlob is not a function. (In 'offscreenCanvas.convertToBlob({type: typeVal})', 'offscreenCanvas.convertToBlob' is undefined)
-FAIL Test that convertToBlob with jpge produces correct result offscreenCanvas.convertToBlob is not a function. (In 'offscreenCanvas.convertToBlob({type: typeVal})', 'offscreenCanvas.convertToBlob' is undefined)
-FAIL Test that convertToBlob with webp produces correct result offscreenCanvas.convertToBlob is not a function. (In 'offscreenCanvas.convertToBlob({type: typeVal})', 'offscreenCanvas.convertToBlob' is undefined)
+PASS Test that convertToBlob with default type produces correct result 
+PASS Test that convertToBlob with png produces correct result 
+PASS Test that convertToBlob with jpge produces correct result 
+PASS Test that convertToBlob with webp produces correct result 
 FAIL Test that call convertToBlob on a detached OffscreenCanvas throws exception The object can not be cloned.
-FAIL Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception offscreenCanvas.convertToBlob is not a function. (In 'offscreenCanvas.convertToBlob()', 'offscreenCanvas.convertToBlob' is undefined)
+PASS Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception 
+PASS Test that call convertToBlob on a OffscreenCanvas with tainted origin throws exception 
 
index fce08e5..7d230d9 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="/common/canvas-tests.js"></script>
+<script src="/2dcontext/resources/canvas-tests.js"></script>
 <link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-converttoblob">
 <script id="myWorker" type="text/worker">
 self.onmessage = function(e) {
@@ -144,5 +144,22 @@ async_test(function(t) {
     }));
 }, "Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception");
 
+async_test(function(t) {
+    var img = new Image();
+    img.src = "/images/green.png";
+    img.crossOrigin = "anonymous";
+    img.onload = t.step_func_done(() => {
+        var offscreenCanvas = new OffscreenCanvas(10, 10);
+        var ctx = offscreenCanvas.getContext("2d");
+        ctx.drawImage(img, 0, 0);
+        offscreenCanvas.convertToBlob().then(t.step_func_done(function() {
+            assert_false("convertToBlob didn't throw, but should");
+        }), t.step_func_done(function(e) {
+            assert_true(e instanceof DOMException);
+            assert_equals(e.name, "SecurityError");
+        }));
+    });
+}, "Test that call convertToBlob on a OffscreenCanvas with tainted origin throws exception");
+
 </script>
 
index 1582111..a96c1b4 100644 (file)
@@ -1,18 +1,19 @@
 
-Harness Error (FAIL), message = TypeError: offscreenCanvas.convertToBlob is not a function. (In 'offscreenCanvas.convertToBlob({type: typeVal, quality: qualityVal})', 'offscreenCanvas.convertToBlob' is undefined)
+Harness Error (FAIL), message = DataCloneError: The object can not be cloned.
 
-FAIL Test that convertToBlob with default arguments produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with default type/1.0 quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with default type/0.2 quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with png/default quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with png/1.0 quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with png/0.2 quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with jpeg/default quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with jpeg/1.0 quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with jpeg/0.2 quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with webp/default quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with webp/1.0 quality produces correct result in a worker assert_unreached: error Reached unreachable code
-FAIL Test that convertToBlob with webp/0.2 quality produces correct result in a worker assert_unreached: error Reached unreachable code
+PASS Test that convertToBlob with default arguments produces correct result in a worker 
+PASS Test that convertToBlob with default type/1.0 quality produces correct result in a worker 
+PASS Test that convertToBlob with default type/0.2 quality produces correct result in a worker 
+PASS Test that convertToBlob with png/default quality produces correct result in a worker 
+PASS Test that convertToBlob with png/1.0 quality produces correct result in a worker 
+PASS Test that convertToBlob with png/0.2 quality produces correct result in a worker 
+PASS Test that convertToBlob with jpeg/default quality produces correct result in a worker 
+PASS Test that convertToBlob with jpeg/1.0 quality produces correct result in a worker 
+PASS Test that convertToBlob with jpeg/0.2 quality produces correct result in a worker 
+PASS Test that convertToBlob with webp/default quality produces correct result in a worker 
+PASS Test that convertToBlob with webp/1.0 quality produces correct result in a worker 
+PASS Test that convertToBlob with webp/0.2 quality produces correct result in a worker 
 FAIL Test that call convertToBlob on a detached OffscreenCanvas throws exception in a worker assert_unreached: error Reached unreachable code
-FAIL Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception in a worker assert_unreached: error Reached unreachable code
+PASS Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception in a worker 
+PASS Test that call convertToBlob on a OffscreenCanvas with tainted origin throws exception in a worker 
 
index 573236f..1c69d4d 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="/common/canvas-tests.js"></script>
+<script src="/2dcontext/resources/canvas-tests.js"></script>
 <link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-converttoblob">
 <script id="myWorker" type="text/worker">
 function drawCanvas(ctx)
@@ -40,12 +40,9 @@ function testConvertToBlobException1()
     var offscreenCanvas = new OffscreenCanvas(10, 10);
     self.postMessage({offscreenCanvas}, [offscreenCanvas]);
     offscreenCanvas.convertToBlob().then(function() {
-        return false;
+        self.postMessage(false);
     }, function(e) {
-        if (e instanceof DOMException && e.name == "InvalidStateError")
-            return true;
-        else
-            return false;
+        self.postMessage(e instanceof DOMException && e.name == "InvalidStateError");
     });
 }
 
@@ -53,16 +50,30 @@ function testConvertToBlobException2()
 {
     var offscreenCanvas = new OffscreenCanvas(0, 0);
     offscreenCanvas.convertToBlob().then(function() {
-        return false;
+        self.postMessage(false);
     }, function(e) {
-        if (e instanceof DOMException && e.name == "IndexSizeError")
-            return true;
-        else
-            return false;
+        self.postMessage(e instanceof DOMException && e.name == "IndexSizeError");
+    });
+}
+
+function testConvertToBlobException3(bitmap)
+{
+    var offscreenCanvas = new OffscreenCanvas(10, 10);
+    var ctx = offscreenCanvas.getContext("2d");
+    ctx.drawImage(bitmap, 0, 0);
+    offscreenCanvas.convertToBlob().then(function() {
+        self.postMessage(false);
+    }, function(e) {
+        self.postMessage(e instanceof DOMException && e.name == "SecurityError");
     });
 }
 
 self.onmessage = function(e) {
+    if (e.data instanceof ImageBitmap) {
+        testConvertToBlobException3(e.data);
+        return;
+    }
+
     switch(e.data) {
         case 'test1':
             testConvertToBlob("empty", "empty");
@@ -101,10 +112,10 @@ self.onmessage = function(e) {
             testConvertToBlob("image/webp", 0.2);
             break;
         case 'test13':
-            self.postMessage(testConvertToBlobException1());
+            testConvertToBlobException1();
             break;
         case 'test14':
-            self.postMessage(testConvertToBlobException2());
+            testConvertToBlobException2();
             break;
     }
 };
@@ -289,8 +300,8 @@ async_test(function(t) {
 async_test(function(t) {
     var worker = makeWorker(t);
     worker.addEventListener('message', t.step_func_done(function(msg) {
-        if (msg.data == true || msg.data == false)
-            assert_true(msg.data);
+        assert_true(msg.data);
+        t.done();
     }));
     worker.postMessage('test13');
 }, "Test that call convertToBlob on a detached OffscreenCanvas throws exception in a worker");
@@ -298,11 +309,27 @@ async_test(function(t) {
 async_test(function(t) {
     var worker = makeWorker(t);
     worker.addEventListener('message', t.step_func_done(function(msg) {
-        if (msg.data == true || msg.data == false)
-            assert_true(msg.data);
+        assert_true(msg.data);
+        t.done();
     }));
     worker.postMessage('test14');
 }, "Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception in a worker");
 
+async_test(function(t) {
+    var img = new Image();
+    img.src = "/images/green.png";
+    img.crossOrigin = "anonymous";
+    img.onload = t.step_func_done(() => {
+        createImageBitmap(img).then(t.step_func_done(bitmap => {
+            var worker = makeWorker(t);
+            worker.addEventListener('message', t.step_func_done(function(msg) {
+                assert_true(msg.data);
+                t.done();
+            }));
+            worker.postMessage(bitmap);
+        }));
+    });
+}, "Test that call convertToBlob on a OffscreenCanvas with tainted origin throws exception in a worker");
+
 </script>
 
index e35ec73..073bde3 100644 (file)
@@ -1,3 +1,34 @@
+2019-12-13  Chris Lord  <clord@igalia.com>
+
+        Implement OffscreenCanvas.convertToBlob
+        https://bugs.webkit.org/show_bug.cgi?id=202573
+
+        Reviewed by Darin Adler.
+
+        Implement OffscreenCanvas.convertToBlob. This also involves making
+        isSupportedImageMIMETypeForEncoding safe to use off the main thread,
+        and implementing OffscreenCanvas.securityOrigin.
+
+        No new tests, these changes fix existing tests.
+
+        * html/OffscreenCanvas.cpp:
+        (WebCore::toEncodingMimeType):
+        (WebCore::qualityFromDouble):
+        (WebCore::OffscreenCanvas::convertToBlob):
+        (WebCore::OffscreenCanvas::securityOrigin const):
+        * html/OffscreenCanvas.h:
+        * html/OffscreenCanvas.idl:
+        * platform/MIMETypeRegistry.cpp:
+        (WebCore::MIMETypeRegistry::createMIMETypeRegistryThreadGlobalData):
+        (WebCore::MIMETypeRegistry::isSupportedImageMIMETypeForEncoding):
+        * platform/MIMETypeRegistry.h:
+        (WebCore::MIMETypeRegistryThreadGlobalData::MIMETypeRegistryThreadGlobalData):
+        (WebCore::MIMETypeRegistryThreadGlobalData::supportedImageMIMETypesForEncoding const):
+        * platform/ThreadGlobalData.cpp:
+        (WebCore::ThreadGlobalData::mimeTypeRegistryThreadGlobalData):
+        * platform/ThreadGlobalData.h:
+        * workers/WorkerGlobalScope.h:
+
 2019-12-13  youenn fablet  <youenn@apple.com>
 
         Make DOMCacheStorage::retrieveCaches take a CompletionHandler
index d5ee5d6..9f78e8b 100644 (file)
@@ -31,7 +31,9 @@
 #include "CSSValuePool.h"
 #include "CanvasRenderingContext.h"
 #include "ImageBitmap.h"
+#include "JSBlob.h"
 #include "JSDOMPromiseDeferred.h"
+#include "MIMETypeRegistry.h"
 #include "OffscreenCanvasRenderingContext2D.h"
 #include "WebGLRenderingContext.h"
 #include "WorkerGlobalScope.h"
@@ -165,11 +167,65 @@ ExceptionOr<RefPtr<ImageBitmap>> OffscreenCanvas::transferToImageBitmap()
     return Exception { NotSupportedError };
 }
 
+static String toEncodingMimeType(const String& mimeType)
+{
+    if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
+        return "image/png"_s;
+    return mimeType.convertToASCIILowercase();
+}
+
+static Optional<double> qualityFromDouble(double qualityNumber)
+{
+    if (!(qualityNumber >= 0 && qualityNumber <= 1))
+        return WTF::nullopt;
+
+    return qualityNumber;
+}
+
+void OffscreenCanvas::convertToBlob(ImageEncodeOptions&& options, Ref<DeferredPromise>&& promise)
+{
+    if (!originClean()) {
+        promise->reject(SecurityError);
+        return;
+    }
+    if (size().isEmpty()) {
+        promise->reject(IndexSizeError);
+        return;
+    }
+    if (!buffer()) {
+        promise->reject(InvalidStateError);
+        return;
+    }
+
+    makeRenderingResultsAvailable();
+
+    auto encodingMIMEType = toEncodingMimeType(options.type);
+    auto quality = qualityFromDouble(options.quality);
+
+    Vector<uint8_t> blobData = buffer()->toData(encodingMIMEType, quality);
+    if (blobData.isEmpty()) {
+        promise->reject(EncodingError);
+        return;
+    }
+
+    Ref<Blob> blob = Blob::create(WTFMove(blobData), encodingMIMEType);
+    promise->resolveWithNewlyCreated<IDLInterface<Blob>>(WTFMove(blob));
+}
+
 void OffscreenCanvas::didDraw(const FloatRect& rect)
 {
     notifyObserversCanvasChanged(rect);
 }
 
+SecurityOrigin* OffscreenCanvas::securityOrigin() const
+{
+    auto& context = *canvasBaseScriptExecutionContext();
+    if (is<WorkerGlobalScope>(context))
+        return &downcast<WorkerGlobalScope>(context).topOrigin();
+
+    return &downcast<Document>(context).securityOrigin();
+}
+
 CSSValuePool& OffscreenCanvas::cssValuePool()
 {
     auto* context = canvasBaseScriptExecutionContext();
index a16eb59..6595789 100644 (file)
@@ -43,6 +43,7 @@ namespace WebCore {
 
 class CanvasRenderingContext;
 class CSSValuePool;
+class DeferredPromise;
 class ImageBitmap;
 class OffscreenCanvasRenderingContext2D;
 class WebGLRenderingContext;
@@ -79,13 +80,14 @@ public:
     ExceptionOr<OffscreenRenderingContext> getContext(JSC::JSGlobalObject&, RenderingContextType, Vector<JSC::Strong<JSC::Unknown>>&& arguments);
 #endif
     ExceptionOr<RefPtr<ImageBitmap>> transferToImageBitmap();
-    // void convertToBlob(ImageEncodeOptions options);
+    void convertToBlob(ImageEncodeOptions&&, Ref<DeferredPromise>&&);
 
     void didDraw(const FloatRect&) final;
 
     Image* copiedImage() const final { return nullptr; }
     bool hasCreatedImageBuffer() const final { return m_hasCreatedImageBuffer; }
 
+    SecurityOrigin* securityOrigin() const final;
     CSSValuePool& cssValuePool();
 
     using RefCounted::ref;
index e2eef33..779031a 100644 (file)
@@ -54,6 +54,6 @@ enum OffscreenRenderingContextType
 
     [CallWith=GlobalObject, MayThrowException] OffscreenRenderingContext? getContext(OffscreenRenderingContextType contextType, any... arguments);
     [MayThrowException] ImageBitmap transferToImageBitmap();
-    // Promise<Blob> convertToBlob(optional ImageEncodeOptions options);
+    Promise<Blob> convertToBlob(optional ImageEncodeOptions options);
 
 };
index 2190784..100dd63 100644 (file)
@@ -28,6 +28,7 @@
 #include "MIMETypeRegistry.h"
 
 #include "MediaPlayer.h"
+#include "ThreadGlobalData.h"
 #include <wtf/HashMap.h>
 #include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
@@ -170,43 +171,6 @@ HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::additionalSupported
     return additionalSupportedImageMIMETypes;
 }
 
-static const HashSet<String, ASCIICaseInsensitiveHash>& supportedImageMIMETypesForEncoding()
-{
-#if PLATFORM(COCOA)
-    static const auto supportedImageMIMETypesForEncoding = makeNeverDestroyed([] {
-        RetainPtr<CFArrayRef> supportedTypes = adoptCF(CGImageDestinationCopyTypeIdentifiers());
-        HashSet<String, ASCIICaseInsensitiveHash> supportedImageMIMETypesForEncoding;
-        CFIndex count = CFArrayGetCount(supportedTypes.get());
-        for (CFIndex i = 0; i < count; i++) {
-            CFStringRef supportedType = reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i));
-            String mimeType = MIMETypeForImageType(supportedType);
-            if (!mimeType.isEmpty())
-                supportedImageMIMETypesForEncoding.add(mimeType);
-        }
-        return supportedImageMIMETypesForEncoding;
-    }());
-#else
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> supportedImageMIMETypesForEncoding =std::initializer_list<String> {
-#if USE(CG) || USE(DIRECT2D)
-        // FIXME: Add Windows support for all the supported UTI's when a way to convert from MIMEType to UTI reliably is found.
-        // For now, only support PNG, JPEG and GIF. See <rdar://problem/6095286>.
-        "image/png"_s,
-        "image/jpeg"_s,
-        "image/gif"_s,
-#elif PLATFORM(GTK)
-        "image/png"_s,
-        "image/jpeg"_s,
-        "image/tiff"_s,
-        "image/bmp"_s,
-        "image/ico"_s,
-#elif USE(CAIRO)
-        "image/png"_s,
-#endif
-    };
-#endif
-    return supportedImageMIMETypesForEncoding;
-}
-
 static const HashSet<String, ASCIICaseInsensitiveHash>& supportedJavaScriptMIMETypes()
 {
     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> supportedJavaScriptMIMETypes = std::initializer_list<String> {
@@ -474,13 +438,45 @@ bool MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType(const String& mimeType
     return false;
 }
 
-bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
+std::unique_ptr<MIMETypeRegistryThreadGlobalData> MIMETypeRegistry::createMIMETypeRegistryThreadGlobalData()
 {
-    ASSERT(isMainThread());
+#if PLATFORM(COCOA)
+    RetainPtr<CFArrayRef> supportedTypes = adoptCF(CGImageDestinationCopyTypeIdentifiers());
+    HashSet<String, ASCIICaseInsensitiveHash> supportedImageMIMETypesForEncoding;
+    CFIndex count = CFArrayGetCount(supportedTypes.get());
+    for (CFIndex i = 0; i < count; i++) {
+        CFStringRef supportedType = reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i));
+        String mimeType = MIMETypeForImageType(supportedType);
+        if (!mimeType.isEmpty())
+            supportedImageMIMETypesForEncoding.add(mimeType);
+    }
+#else
+    HashSet<String, ASCIICaseInsensitiveHash> supportedImageMIMETypesForEncoding = std::initializer_list<String> {
+#if USE(CG) || USE(DIRECT2D)
+        // FIXME: Add Windows support for all the supported UTI's when a way to convert from MIMEType to UTI reliably is found.
+        // For now, only support PNG, JPEG and GIF. See <rdar://problem/6095286>.
+        "image/png"_s,
+        "image/jpeg"_s,
+        "image/gif"_s,
+#elif PLATFORM(GTK)
+        "image/png"_s,
+        "image/jpeg"_s,
+        "image/tiff"_s,
+        "image/bmp"_s,
+        "image/ico"_s,
+#elif USE(CAIRO)
+        "image/png"_s,
+#endif
+    };
+#endif
+    return makeUnique<MIMETypeRegistryThreadGlobalData>(WTFMove(supportedImageMIMETypesForEncoding));
+}
 
+bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
+{
     if (mimeType.isEmpty())
         return false;
-    return supportedImageMIMETypesForEncoding().contains(mimeType);
+    return threadGlobalData().mimeTypeRegistryThreadGlobalData().supportedImageMIMETypesForEncoding().contains(mimeType);
 }
 
 bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
index 876c382..1ae2b49 100644 (file)
 
 namespace WebCore {
 
+struct MIMETypeRegistryThreadGlobalData {
+    WTF_MAKE_NONCOPYABLE(MIMETypeRegistryThreadGlobalData);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    MIMETypeRegistryThreadGlobalData(HashSet<String, ASCIICaseInsensitiveHash>&& supportedImageMIMETypesForEncoding)
+        : m_supportedImageMIMETypesForEncoding(supportedImageMIMETypesForEncoding)
+    { }
+
+    const HashSet<String, ASCIICaseInsensitiveHash>& supportedImageMIMETypesForEncoding() const { return m_supportedImageMIMETypesForEncoding; }
+
+private:
+    HashSet<String, ASCIICaseInsensitiveHash> m_supportedImageMIMETypesForEncoding;
+};
+
 class MIMETypeRegistry {
 public:
     WEBCORE_EXPORT static String getMIMETypeForExtension(const String& extension);
@@ -43,6 +57,8 @@ public:
 
     static String getMIMETypeForPath(const String& path);
 
+    static std::unique_ptr<MIMETypeRegistryThreadGlobalData> createMIMETypeRegistryThreadGlobalData();
+
     // Check to see if a MIME type is suitable for being loaded inline as an
     // image (e.g., <img> tags).
     WEBCORE_EXPORT static bool isSupportedImageMIMEType(const String& mimeType);
index 27a7364..705869d 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "CachedResourceRequestInitiators.h"
 #include "EventNames.h"
+#include "MIMETypeRegistry.h"
 #include "QualifiedNameCache.h"
 #include "TextCodecICU.h"
 #include "ThreadTimers.h"
@@ -117,4 +118,11 @@ ThreadGlobalData& threadGlobalData()
 
 #endif
 
+const MIMETypeRegistryThreadGlobalData& ThreadGlobalData::mimeTypeRegistryThreadGlobalData()
+{
+    if (UNLIKELY(!m_MIMETypeRegistryThreadGlobalData))
+        m_MIMETypeRegistryThreadGlobalData = MIMETypeRegistry::createMIMETypeRegistryThreadGlobalData();
+    return *m_MIMETypeRegistryThreadGlobalData;
+}
+
 } // namespace WebCore
index 5630d95..a3430e3 100644 (file)
@@ -43,6 +43,7 @@ class ThreadTimers;
 struct CachedResourceRequestInitiators;
 struct EventNames;
 struct ICUConverterWrapper;
+struct MIMETypeRegistryThreadGlobalData;
 
 #if USE(WEB_THREAD)
 class ThreadGlobalData : public ThreadSafeRefCounted<ThreadGlobalData> {
@@ -73,6 +74,8 @@ public:
     bool isInRemoveAllEventListeners() const { return m_isInRemoveAllEventListeners; }
     void setIsInRemoveAllEventListeners(bool value) { m_isInRemoveAllEventListeners = value; }
 
+    const MIMETypeRegistryThreadGlobalData& mimeTypeRegistryThreadGlobalData();
+
 private:
     std::unique_ptr<CachedResourceRequestInitiators> m_cachedResourceRequestInitiators;
     std::unique_ptr<EventNames> m_eventNames;
@@ -87,6 +90,7 @@ private:
     bool m_isInRemoveAllEventListeners { false };
 
     std::unique_ptr<ICUConverterWrapper> m_cachedConverterICU;
+    std::unique_ptr<MIMETypeRegistryThreadGlobalData> m_MIMETypeRegistryThreadGlobalData;
 
     WEBCORE_EXPORT friend ThreadGlobalData& threadGlobalData();
 };
index 2eef260..16d0fbe 100644 (file)
@@ -122,6 +122,8 @@ public:
 
     void addConsoleMessage(std::unique_ptr<Inspector::ConsoleMessage>&&) final;
 
+    SecurityOrigin& topOrigin() const final { return m_topOrigin.get(); }
+
     Crypto& crypto();
     Performance& performance() const;
 
@@ -168,7 +170,6 @@ private:
 
     bool shouldBypassMainWorldContentSecurityPolicy() const final { return m_shouldBypassMainWorldContentSecurityPolicy; }
     bool isJSExecutionForbidden() const final;
-    SecurityOrigin& topOrigin() const final { return m_topOrigin.get(); }
 
 #if ENABLE(WEB_CRYPTO)
     bool wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) final;