Multiple File Input Icon Set Regardless of File List
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Apr 2019 20:18:05 +0000 (20:18 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Apr 2019 20:18:05 +0000 (20:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195537

Source/WebCore:

Patch by Guy Lewin <guy@lewin.co.il> on 2019-04-23
Reviewed by Alexey Proskuryakov.

File input elements display icon with an empty file list after
resetting the file list in 'change' event handler - on iOS

Test: fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html

* html/FileInputType.cpp:
(WebCore::FileInputType::filesChosen):

Source/WebKit:

Patch by Guy Lewin <guy@lewin.co.il> on 2019-04-23
Reviewed by Alexey Proskuryakov.

Add WKOpenPanelResultListenerChooseMediaFiles() to choose files with
icon and display string on iOS file open panels

* UIProcess/API/C/WKOpenPanelResultListener.cpp:
(WKOpenPanelResultListenerChooseMediaFiles):
* UIProcess/API/C/WKOpenPanelResultListener.h:

Tools:

Patch by Guy Lewin <guy@lewin.co.il> on 2019-04-23
Reviewed by Alexey Proskuryakov.

Add setOpenPanelFilesMediaIcon to TestRunner in order to test icon and
display string in iOS file inputs

* DumpRenderTree/TestRunner.cpp:
(SetOpenPanelFilesMediaIconCallback):
(TestRunner::staticFunctions):
(TestRunner::setOpenPanelFilesMediaIcon):
* DumpRenderTree/TestRunner.h:
(TestRunner::openPanelFilesMediaIcon const):
* DumpRenderTree/mac/UIDelegate.mm:
(-[UIDelegate webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:]):
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setOpenPanelFilesMediaIcon):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::runOpenPanel):
(WTR::TestController::resetStateToConsistentValues):
* WebKitTestRunner/TestController.h:
(WTR::TestController::openPanelFileURLsMediaIcon const):
(WTR::TestController::setOpenPanelFileURLsMediaIcon):
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):

LayoutTests:

Add a layout test to verify file input icon resets on change event (iOS)
Change expectations according to
file-reset-in-change-using-open-panel.html

Patch by Guy Lewin <guy@lewin.co.il> on 2019-04-23
Reviewed by Alexey Proskuryakov.

* fast/forms/file/file-reset-in-change-using-open-panel-with-icon-expected.html: Added.
* fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html: Added.
* platform/win/TestExpectations:
* platform/wincairo/TestExpectations:

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

20 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/forms/file/file-reset-in-change-using-open-panel-with-icon-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html [new file with mode: 0644]
LayoutTests/platform/win/TestExpectations
LayoutTests/platform/wincairo/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/html/FileInputType.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/C/WKOpenPanelResultListener.cpp
Source/WebKit/UIProcess/API/C/WKOpenPanelResultListener.h
Tools/ChangeLog
Tools/DumpRenderTree/TestRunner.cpp
Tools/DumpRenderTree/TestRunner.h
Tools/DumpRenderTree/mac/UIDelegate.mm
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestInvocation.cpp

index 1ab34cb..0e628f9 100644 (file)
@@ -1,3 +1,19 @@
+2019-04-23  Guy Lewin  <guy@lewin.co.il>
+
+        Multiple File Input Icon Set Regardless of File List
+        https://bugs.webkit.org/show_bug.cgi?id=195537
+
+        Add a layout test to verify file input icon resets on change event (iOS)
+        Change expectations according to
+        file-reset-in-change-using-open-panel.html
+
+        Reviewed by Alexey Proskuryakov.
+
+        * fast/forms/file/file-reset-in-change-using-open-panel-with-icon-expected.html: Added.
+        * fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html: Added.
+        * platform/win/TestExpectations:
+        * platform/wincairo/TestExpectations:
+
 2019-04-23  Devin Rousso  <drousso@apple.com>
 
         Unreviewed, speculative fix for failing inspector/canvas/ tests.
diff --git a/LayoutTests/fast/forms/file/file-reset-in-change-using-open-panel-with-icon-expected.html b/LayoutTests/fast/forms/file/file-reset-in-change-using-open-panel-with-icon-expected.html
new file mode 100644 (file)
index 0000000..b48384e
--- /dev/null
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<body>
+<p>Resetting a file upload control by script should clear the icon.</p>
+<p>Manual test: Select a file for the file upload control, and confirm it has no icon.</p>
+<input id=file1 type=file multiple=multiple>
+</form>
+</body>
diff --git a/LayoutTests/fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html b/LayoutTests/fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html
new file mode 100644 (file)
index 0000000..5f0ba71
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<script src="../../../resources/ui-helper.js"></script>
+<body>
+<p>Resetting a file upload control by script should clear the icon.</p>
+<p>Manual test: Select a file for the file upload control, and confirm it has no icon.</p>
+<input id=file1 type=file multiple=multiple>
+</form>
+<script>
+function openFilesInElement(element, files, icon) {
+    testRunner.setOpenPanelFiles(files);
+    if (testRunner.setOpenPanelFilesMediaIcon)
+        testRunner.setOpenPanelFilesMediaIcon(icon);
+    var centerX = element.offsetLeft + element.offsetWidth / 2;
+    var centerY = element.offsetTop + element.offsetHeight / 2;
+    UIHelper.activateAt(centerX, centerY);
+}
+
+function handleChange() {
+    file1.value = '';
+    // The change event can be fired before the mouse up, so use a timeout here to ensure the next mouse down happens after the pending mouse up.
+    window.setTimeout(function() {
+        UIHelper.activateAt(1, 1).then(function() {
+            testRunner.notifyDone();
+        });
+    }, 0);
+}
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+var file1 = document.getElementById('file1');
+file1.addEventListener('change', handleChange);
+// Icon is configured manually to avoid ObjC calls from C++ code
+var iconBytes = new Uint8Array([255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0, 96, 0, 96, 0, 0, 255, 219, 0, 67, 0, 8, 6, 6, 7, 6, 5, 8, 7, 7, 7, 9, 9, 8, 10, 12, 20, 13, 12, 11, 11, 12, 25, 18, 19, 15, 20, 29, 26, 31, 30, 29, 26, 28, 28, 32, 36, 46, 39, 32, 34, 44, 35, 28, 28, 40, 55, 41, 44, 48, 49, 52, 52, 52, 31, 39, 57, 61, 56, 50, 60, 46, 51, 52, 50, 255, 219, 0, 67, 1, 9, 9, 9, 12, 11, 12, 24, 13, 13, 24, 50, 33, 28, 33, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 255, 192, 0, 17, 8, 0, 1, 0, 1, 3, 1, 34, 0, 2, 17, 1, 3, 17, 1, 255, 196, 0, 31, 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 255, 196, 0, 181, 16, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125, 1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81, 97, 7, 34, 113, 20, 50, 129, 145, 161, 8, 35, 66, 177, 193, 21, 82, 209, 240, 36, 51, 98, 114, 130, 9, 10, 22, 23, 24, 25, 26, 37, 38, 39, 40, 41, 42, 52, 53, 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, 131, 132, 133, 134, 135, 136, 137, 138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217, 218, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 255, 196, 0, 31, 1, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 255, 196, 0, 181, 17, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119, 0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18, 65, 81, 7, 97, 113, 19, 34, 50, 129, 8, 20, 66, 145, 161, 177, 193, 9, 35, 51, 82, 240, 21, 98, 114, 209, 10, 22, 36, 52, 225, 37, 241, 23, 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, 130, 131, 132, 133, 134, 135, 136, 137, 138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217, 218, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242, 243, 244, 245, 246, 247, 248, 249, 250, 255, 218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0, 247, 250, 40, 162, 128, 63, 255, 217]);
+openFilesInElement(file1, ['foo.txt', 'bar.txt'], iconBytes);
+</script>
+</body>
index 7dbb445..d82e011 100644 (file)
@@ -3633,6 +3633,7 @@ editing/selection/character-granularity-selected-range-after-dismissing-selectio
 fast/dom/FileList-iterator-using-open-panel.html [ Skip ]
 fast/forms/file/file-input-reset-using-open-panel.html [ Skip ]
 fast/forms/file/file-reset-in-change-using-open-panel.html [ Skip ]
+fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html [ Skip ]
 fast/forms/file/get-file-upload-using-open-panel.html [ Skip ]
 fast/forms/file/input-file-value-using-open-panel.html [ Skip ]
 fast/forms/file/input-file-write-files-using-open-panel.html [ Skip ]
index e713a11..ec94087 100644 (file)
@@ -774,6 +774,7 @@ fast/files/filereader-zip-bundle-using-open-panel.html [ Timeout ]
 fast/forms/file/file-input-reset-using-open-panel.html [ Timeout ]
 fast/forms/file/entries-api/webkitdirectory-open-panel.html [ Timeout ]
 fast/forms/file/file-reset-in-change-using-open-panel.html [ Timeout ]
+fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html [ Timeout ]
 fast/forms/file/get-file-upload-using-open-panel.html [ Timeout ]
 fast/forms/file/input-file-value-using-open-panel.html [ Timeout ]
 fast/forms/file/input-file-write-files-using-open-panel.html [ Timeout ]
index dfefe74..d63878f 100644 (file)
@@ -1,3 +1,18 @@
+2019-04-23  Guy Lewin  <guy@lewin.co.il>
+
+        Multiple File Input Icon Set Regardless of File List
+        https://bugs.webkit.org/show_bug.cgi?id=195537
+
+        Reviewed by Alexey Proskuryakov.
+
+        File input elements display icon with an empty file list after
+        resetting the file list in 'change' event handler - on iOS
+
+        Test: fast/forms/file/file-reset-in-change-using-open-panel-with-icon.html
+
+        * html/FileInputType.cpp:
+        (WebCore::FileInputType::filesChosen):
+
 2019-04-23  Eric Carlson  <eric.carlson@apple.com>
 
         Create AVFoundationSoftLink.{h,mm} to reduce duplicate code
index 998f9ef..c324050 100644 (file)
@@ -419,7 +419,7 @@ void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& paths, const
         m_fileListCreator = nullptr;
     });
 
-    if (icon)
+    if (icon && !m_fileList->isEmpty())
         iconLoaded(icon);
 }
 
index d709e39..cb31435 100644 (file)
@@ -1,3 +1,17 @@
+2019-04-23  Guy Lewin  <guy@lewin.co.il>
+
+        Multiple File Input Icon Set Regardless of File List
+        https://bugs.webkit.org/show_bug.cgi?id=195537
+
+        Reviewed by Alexey Proskuryakov.
+
+        Add WKOpenPanelResultListenerChooseMediaFiles() to choose files with
+        icon and display string on iOS file open panels
+
+        * UIProcess/API/C/WKOpenPanelResultListener.cpp:
+        (WKOpenPanelResultListenerChooseMediaFiles):
+        * UIProcess/API/C/WKOpenPanelResultListener.h:
+
 2019-04-23  Eric Carlson  <eric.carlson@apple.com>
 
         Create AVFoundationSoftLink.{h,mm} to reduce duplicate code
index 4a0ffc4..2b394fc 100644 (file)
@@ -27,6 +27,8 @@
 #include "WKOpenPanelResultListener.h"
 
 #include "APIArray.h"
+#include "APIData.h"
+#include "APIString.h"
 #include "WKAPICast.h"
 #include "WebOpenPanelResultListenerProxy.h"
 #include <wtf/URL.h>
@@ -54,6 +56,13 @@ static Vector<String> filePathsFromFileURLs(const API::Array& fileURLs)
     return filePaths;
 }
 
+#if PLATFORM(IOS_FAMILY)
+void WKOpenPanelResultListenerChooseMediaFiles(WKOpenPanelResultListenerRef listenerRef, WKArrayRef fileURLsRef, WKStringRef displayString, WKDataRef iconImageDataRef)
+{
+    toImpl(listenerRef)->chooseFiles(filePathsFromFileURLs(*toImpl(fileURLsRef)), toImpl(displayString)->string(), toImpl(iconImageDataRef));
+}
+#endif
+
 void WKOpenPanelResultListenerChooseFiles(WKOpenPanelResultListenerRef listenerRef, WKArrayRef fileURLsRef)
 {
     toImpl(listenerRef)->chooseFiles(filePathsFromFileURLs(*toImpl(fileURLsRef)));
index 21c92ee..2618de0 100644 (file)
@@ -34,6 +34,7 @@ extern "C" {
 
 WK_EXPORT WKTypeID WKOpenPanelResultListenerGetTypeID();
 
+WK_EXPORT void WKOpenPanelResultListenerChooseMediaFiles(WKOpenPanelResultListenerRef listenerRef, WKArrayRef fileURLsRef, WKStringRef displayString, WKDataRef iconImageDataRef);
 WK_EXPORT void WKOpenPanelResultListenerChooseFiles(WKOpenPanelResultListenerRef listener, WKArrayRef fileURLs);
 WK_EXPORT void WKOpenPanelResultListenerCancel(WKOpenPanelResultListenerRef listener);
 
index b50ca6c..ffa2b02 100644 (file)
@@ -1,3 +1,34 @@
+2019-04-23  Guy Lewin  <guy@lewin.co.il>
+
+        Multiple File Input Icon Set Regardless of File List
+        https://bugs.webkit.org/show_bug.cgi?id=195537
+
+        Reviewed by Alexey Proskuryakov.
+
+        Add setOpenPanelFilesMediaIcon to TestRunner in order to test icon and
+        display string in iOS file inputs
+
+        * DumpRenderTree/TestRunner.cpp:
+        (SetOpenPanelFilesMediaIconCallback):
+        (TestRunner::staticFunctions):
+        (TestRunner::setOpenPanelFilesMediaIcon):
+        * DumpRenderTree/TestRunner.h:
+        (TestRunner::openPanelFilesMediaIcon const):
+        * DumpRenderTree/mac/UIDelegate.mm:
+        (-[UIDelegate webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:]):
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setOpenPanelFilesMediaIcon):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::runOpenPanel):
+        (WTR::TestController::resetStateToConsistentValues):
+        * WebKitTestRunner/TestController.h:
+        (WTR::TestController::openPanelFileURLsMediaIcon const):
+        (WTR::TestController::setOpenPanelFileURLsMediaIcon):
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
+
 2019-04-23  Eric Carlson  <eric.carlson@apple.com>
 
         Create AVFoundationSoftLink.{h,mm} to reduce duplicate code
index 6222242..b5e753f 100644 (file)
@@ -1829,6 +1829,15 @@ static JSValueRef setOpenPanelFilesCallback(JSContextRef context, JSObjectRef fu
     return JSValueMakeUndefined(context);
 }
 
+#if PLATFORM(IOS_FAMILY)
+static JSValueRef SetOpenPanelFilesMediaIconCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    if (argumentCount == 1)
+        static_cast<TestRunner*>(JSObjectGetPrivate(thisObject))->setOpenPanelFilesMediaIcon(context, arguments[0]);
+    return JSValueMakeUndefined(context);
+}
+#endif
+
 // Static Values
 
 static JSValueRef getTimeoutCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
@@ -2293,6 +2302,9 @@ JSStaticFunction* TestRunner::staticFunctions()
         { "setSpellCheckerLoggingEnabled", setSpellCheckerLoggingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setSpellCheckerResults", setSpellCheckerResultsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setOpenPanelFiles", setOpenPanelFilesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+#if PLATFORM(IOS_FAMILY)
+        { "setOpenPanelFilesMediaIcon", SetOpenPanelFilesMediaIconCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+#endif
         { "forceImmediateCompletion", forceImmediateCompletionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { 0, 0, 0 }
     };
@@ -2526,6 +2538,23 @@ void TestRunner::setOpenPanelFiles(JSContextRef context, JSValueRef filesValue)
     }
 }
 
+#if PLATFORM(IOS_FAMILY)
+void TestRunner::setOpenPanelFilesMediaIcon(JSContextRef context, JSValueRef mediaIcon)
+{
+    // FIXME (123058): Use a JSC API to get buffer contents once such is exposed.
+    JSC::VM& vm = toJS(context)->vm();
+    JSC::JSLockHolder lock(vm);
+    
+    JSC::JSArrayBufferView* jsBufferView = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(vm, toJS(toJS(context), mediaIcon));
+    ASSERT(jsBufferView);
+    RefPtr<JSC::ArrayBufferView> bufferView = jsBufferView->unsharedImpl();
+    const char* buffer = static_cast<const char*>(bufferView->baseAddress());
+    std::vector<char> mediaIconData(buffer, buffer + bufferView->byteLength());
+    
+    m_openPanelFilesMediaIcon = mediaIconData;
+}
+#endif
+
 void TestRunner::cleanup()
 {
     clearTestRunnerCallbacks();
index 4209190..a1c6406 100644 (file)
@@ -383,6 +383,11 @@ public:
     const std::vector<std::string>& openPanelFiles() const { return m_openPanelFiles; }
     void setOpenPanelFiles(JSContextRef, JSValueRef);
 
+#if PLATFORM(IOS_FAMILY)
+    const std::vector<char>& openPanelFilesMediaIcon() const { return m_openPanelFilesMediaIcon; }
+    void setOpenPanelFilesMediaIcon(JSContextRef, JSValueRef);
+#endif
+
     bool didCancelClientRedirect() const { return m_didCancelClientRedirect; }
     void setDidCancelClientRedirect(bool value) { m_didCancelClientRedirect = value; }
 
@@ -478,6 +483,9 @@ private:
     UIScriptInvocationData* m_pendingUIScriptInvocationData { nullptr };
 
     std::vector<std::string> m_openPanelFiles;
+#if PLATFORM(IOS_FAMILY)
+    std::vector<char> m_openPanelFilesMediaIcon;
+#endif
 
     static JSClassRef getJSClass();
     static JSStaticValue* staticValues();
index c86a0b2..0634a9e 100644 (file)
@@ -385,12 +385,32 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil;
         [filePaths addObject:fileURL.path];
     }
 
+#if PLATFORM(IOS_FAMILY)
+    NSURL *firstURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:openPanelFiles[0].c_str()] relativeToURL:baseURL];
+    NSString *displayString = firstURL.lastPathComponent;
+    const std::vector<char>& iconData = gTestRunner->openPanelFilesMediaIcon();
+    CGImageRef imageRef;
+    if (!iconData.empty()) {
+        RetainPtr<CFDataRef> dataRef = adoptCF(CFDataCreate(nullptr, (unsigned char *)iconData.data(), iconData.size()));
+        RetainPtr<CGDataProviderRef> imageProviderRef = adoptCF(CGDataProviderCreateWithCFData(dataRef.get()));
+        imageRef = CGImageCreateWithJPEGDataProvider(imageProviderRef.get(), nullptr, true, kCGRenderingIntentDefault);
+    }
+#endif
+
     if (allowMultipleFiles) {
+#if PLATFORM(IOS_FAMILY)
+        [resultListener chooseFilenames:filePaths.get() displayString:displayString iconImage:imageRef];
+#else
         [resultListener chooseFilenames:filePaths.get()];
+#endif
         return;
     }
 
+#if PLATFORM(IOS_FAMILY)
+    [resultListener chooseFilename:[filePaths firstObject] displayString:displayString iconImage:imageRef];
+#else
     [resultListener chooseFilename:[filePaths firstObject]];
+#endif
 }
 
 #if !PLATFORM(IOS_FAMILY)
index 5059b0c..3cb877c 100644 (file)
@@ -340,6 +340,7 @@ interface TestRunner {
 
     // Open panel
     void setOpenPanelFiles(object filesArray);
+    void setOpenPanelFilesMediaIcon(object mediaIcon);
 
     // Modal alerts
     void setShouldDismissJavaScriptAlertsAsynchronously(boolean value);
index bc21e04..41ff1f0 100644 (file)
@@ -2445,6 +2445,25 @@ void TestRunner::setOpenPanelFiles(JSValueRef filesValue)
     WKBundlePagePostMessage(page, messageName.get(), fileURLs.get());
 }
 
+#if PLATFORM(IOS_FAMILY)
+void TestRunner::setOpenPanelFilesMediaIcon(JSValueRef data)
+{
+    WKBundlePageRef page = InjectedBundle::singleton().page()->page();
+    JSContextRef context = WKBundleFrameGetJavaScriptContext(WKBundlePageGetMainFrame(page));
+
+    auto& injectedBundle = InjectedBundle::singleton();
+    // FIXME (123058): Use a JSC API to get buffer contents once such is exposed.
+    WKRetainPtr<WKDataRef> iconData(AdoptWK, WKBundleCreateWKDataFromUInt8Array(injectedBundle.bundle(), context, data));
+
+    static auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetOpenPanelFileURLsMediaIcon"));
+    WKBundlePagePostMessage(page, messageName.get(), iconData.get());
+}
+#else
+void TestRunner::setOpenPanelFilesMediaIcon(JSValueRef)
+{
+}
+#endif // PLATFORM(IOS_FAMILY)
+
 void TestRunner::removeAllSessionCredentials(JSValueRef callback)
 {
     cacheTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID, callback);
index 7701b90..0daec00 100644 (file)
@@ -455,6 +455,7 @@ public:
 
     // Open panel
     void setOpenPanelFiles(JSValueRef);
+    void setOpenPanelFilesMediaIcon(JSValueRef);
 
     // Modal alerts
     void setShouldDismissJavaScriptAlertsAsynchronously(bool);
index f6d3d10..196792f 100644 (file)
@@ -61,6 +61,7 @@
 #include <WebKit/WKRetainPtr.h>
 #include <WebKit/WKSecurityOriginRef.h>
 #include <WebKit/WKTextChecker.h>
+#include <WebKit/WKURL.h>
 #include <WebKit/WKUserContentControllerRef.h>
 #include <WebKit/WKUserContentExtensionStoreRef.h>
 #include <WebKit/WKUserMediaPermissionCheck.h>
@@ -199,13 +200,29 @@ static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParameters
         WKOpenPanelResultListenerCancel(resultListenerRef);
         return;
     }
+    
+    WKTypeRef firstItem = WKArrayGetItemAtIndex(fileURLs, 0);
+    
+#if PLATFORM(IOS_FAMILY)
+    WKStringRef displayString = WKURLCopyLastPathComponent(static_cast<WKURLRef>(firstItem));
+    WKDataRef mediaIcon = TestController::singleton().openPanelFileURLsMediaIcon();
+    
+    if (mediaIcon) {
+        if (WKOpenPanelParametersGetAllowsMultipleFiles(parameters)) {
+            WKOpenPanelResultListenerChooseMediaFiles(resultListenerRef, fileURLs, displayString, mediaIcon);
+            return;
+        }
+        
+        WKOpenPanelResultListenerChooseMediaFiles(resultListenerRef, adoptWK(WKArrayCreate(&firstItem, 1)).get(), displayString, mediaIcon);
+        return;
+    }
+#endif
 
     if (WKOpenPanelParametersGetAllowsMultipleFiles(parameters)) {
         WKOpenPanelResultListenerChooseFiles(resultListenerRef, fileURLs);
         return;
     }
 
-    WKTypeRef firstItem = WKArrayGetItemAtIndex(fileURLs, 0);
     WKOpenPanelResultListenerChooseFiles(resultListenerRef, adoptWK(WKArrayCreate(&firstItem, 1)).get());
 }
 
@@ -1005,6 +1022,9 @@ bool TestController::resetStateToConsistentValues(const TestOptions& options, Re
     setIgnoresViewportScaleLimits(options.ignoresViewportScaleLimits);
 
     m_openPanelFileURLs = nullptr;
+#if PLATFORM(IOS_FAMILY)
+    m_openPanelFileURLsMediaIcon = nullptr;
+#endif
     
     statisticsResetToConsistentState();
     
index 722dd08..d7df524 100644 (file)
@@ -251,6 +251,11 @@ public:
     WKArrayRef openPanelFileURLs() const { return m_openPanelFileURLs.get(); }
     void setOpenPanelFileURLs(WKArrayRef fileURLs) { m_openPanelFileURLs = fileURLs; }
 
+#if PLATFORM(IOS_FAMILY)
+    WKDataRef openPanelFileURLsMediaIcon() const { return m_openPanelFileURLsMediaIcon.get(); }
+    void setOpenPanelFileURLsMediaIcon(WKDataRef mediaIcon) { m_openPanelFileURLsMediaIcon = mediaIcon; }
+#endif
+
     void terminateNetworkProcess();
     void terminateServiceWorkerProcess();
 
@@ -560,6 +565,9 @@ private:
     bool m_didReceiveServerRedirectForProvisionalNavigation { false };
 
     WKRetainPtr<WKArrayRef> m_openPanelFileURLs;
+#if PLATFORM(IOS_FAMILY)
+    WKRetainPtr<WKDataRef> m_openPanelFileURLsMediaIcon;
+#endif
 
     std::unique_ptr<EventSenderProxy> m_eventSenderProxy;
 
index fe9916a..bcfd009 100644 (file)
@@ -794,6 +794,13 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
         return;
     }
 
+#if PLATFORM(IOS_FAMILY)
+    if (WKStringIsEqualToUTF8CString(messageName, "SetOpenPanelFileURLsMediaIcon")) {
+        TestController::singleton().setOpenPanelFileURLsMediaIcon(static_cast<WKDataRef>(messageBody));
+        return;
+    }
+#endif
+
     ASSERT_NOT_REACHED();
 }