File inputs only accept UTI types that can be inserted into contenteditable areas...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 23 Apr 2017 03:52:12 +0000 (03:52 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 23 Apr 2017 03:52:12 +0000 (03:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171177
<rdar://problem/31765379>

Reviewed by Andy Estes.

Source/WebCore:

Currently, DragController::canProcessDrag bails immediately with `false` if the drag data does not contain
compatible content. However, if we are dragging over a file input, we want the presence of files in the drag
data to take priority. To fix this, we teach DragData::containsCompatibleContent to take the purpose of the drag
into account (by default, this is Editing, but when dragging over a file input, this becomes FileUpload). We
then consider DragData to have compatible content for the purpose of file uploading if it contains any files.

Test: DataInteractionTests.ExternalSourceJSONToFileInput.

* page/DragController.cpp:
(WebCore::DragController::canProcessDrag):
* platform/DragData.h:
* platform/gtk/DragDataGtk.cpp:
(WebCore::DragData::containsCompatibleContent):
* platform/mac/DragDataMac.mm:
(WebCore::DragData::containsCompatibleContent):
* platform/win/DragDataWin.cpp:
(WebCore::DragData::containsCompatibleContent):

Tools:

Tests uploading a JSON file to a file input.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::TEST):

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

Source/WebCore/ChangeLog
Source/WebCore/page/DragController.cpp
Source/WebCore/platform/DragData.h
Source/WebCore/platform/gtk/DragDataGtk.cpp
Source/WebCore/platform/mac/DragDataMac.mm
Source/WebCore/platform/win/DragDataWin.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm

index 56e1de1..ea22c2a 100644 (file)
@@ -1,3 +1,29 @@
+2017-04-22  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        File inputs only accept UTI types that can be inserted into contenteditable areas when dropping
+        https://bugs.webkit.org/show_bug.cgi?id=171177
+        <rdar://problem/31765379>
+
+        Reviewed by Andy Estes.
+
+        Currently, DragController::canProcessDrag bails immediately with `false` if the drag data does not contain
+        compatible content. However, if we are dragging over a file input, we want the presence of files in the drag
+        data to take priority. To fix this, we teach DragData::containsCompatibleContent to take the purpose of the drag
+        into account (by default, this is Editing, but when dragging over a file input, this becomes FileUpload). We
+        then consider DragData to have compatible content for the purpose of file uploading if it contains any files.
+
+        Test: DataInteractionTests.ExternalSourceJSONToFileInput.
+
+        * page/DragController.cpp:
+        (WebCore::DragController::canProcessDrag):
+        * platform/DragData.h:
+        * platform/gtk/DragDataGtk.cpp:
+        (WebCore::DragData::containsCompatibleContent):
+        * platform/mac/DragDataMac.mm:
+        (WebCore::DragData::containsCompatibleContent):
+        * platform/win/DragDataWin.cpp:
+        (WebCore::DragData::containsCompatibleContent):
+
 2017-04-22  Eric Carlson  <eric.carlson@apple.com>
 
         [MediaStream] Fix regression caused by r215626
index 66643e8..4801cec 100644 (file)
@@ -569,9 +569,6 @@ bool DragController::concludeEditDrag(const DragData& dragData)
 
 bool DragController::canProcessDrag(const DragData& dragData)
 {
-    if (!dragData.containsCompatibleContent())
-        return false;
-
     IntPoint point = m_page.mainFrame().view()->windowToContents(dragData.clientPosition());
     HitTestResult result = HitTestResult(point);
     if (!m_page.mainFrame().contentRenderer())
@@ -582,7 +579,14 @@ bool DragController::canProcessDrag(const DragData& dragData)
     if (!result.innerNonSharedNode())
         return false;
 
-    if (dragData.containsFiles() && asFileInput(*result.innerNonSharedNode()))
+    DragData::DraggingPurpose dragPurpose = DragData::DraggingPurpose::ForEditing;
+    if (asFileInput(*result.innerNonSharedNode()))
+        dragPurpose = DragData::DraggingPurpose::ForFileUpload;
+
+    if (!dragData.containsCompatibleContent(dragPurpose))
+        return false;
+
+    if (dragPurpose == DragData::DraggingPurpose::ForFileUpload)
         return true;
 
     if (is<HTMLPlugInElement>(*result.innerNonSharedNode())) {
index 195721b..eb74b37 100644 (file)
@@ -76,6 +76,7 @@ typedef HashMap<unsigned, Vector<String>> DragDataMap;
 class DragData {
 public:
     enum FilenameConversionPolicy { DoNotConvertFilenames, ConvertFilenames };
+    enum class DraggingPurpose { ForEditing, ForFileUpload };
 
     // clientPosition is taken to be the position of the drag event within the target window, with (0,0) at the top left
     WEBCORE_EXPORT DragData(DragDataRef, const IntPoint& clientPosition, const IntPoint& globalPosition, DragOperation, DragApplicationFlags = DragApplicationNone, DragDestinationAction actions = DragDestinationActionAny);
@@ -96,7 +97,7 @@ public:
     DragOperation draggingSourceOperationMask() const { return m_draggingSourceOperationMask; }
     bool containsURL(FilenameConversionPolicy = ConvertFilenames) const;
     bool containsPlainText() const;
-    bool containsCompatibleContent() const;
+    bool containsCompatibleContent(DraggingPurpose = DraggingPurpose::ForEditing) const;
     String asURL(FilenameConversionPolicy = ConvertFilenames, String* title = nullptr) const;
     String asPlainText() const;
     void asFilenames(Vector<String>&) const;
index d987e42..265ef3c 100644 (file)
@@ -61,7 +61,7 @@ Color DragData::asColor() const
     return Color();
 }
 
-bool DragData::containsCompatibleContent() const
+bool DragData::containsCompatibleContent(DraggingPurpose) const
 {
     return containsPlainText() || containsURL() || m_platformDragData->hasMarkup() || containsColor() || containsFiles();
 }
index ea5fc30..fb4829f 100644 (file)
@@ -190,8 +190,11 @@ Color DragData::asColor() const
     return platformStrategies()->pasteboardStrategy()->color(m_pasteboardName);
 }
 
-bool DragData::containsCompatibleContent() const
+bool DragData::containsCompatibleContent(DraggingPurpose purpose) const
 {
+    if (purpose == DraggingPurpose::ForFileUpload)
+        return containsFiles();
+
     Vector<String> types;
     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
     return types.contains(String(WebArchivePboardType))
index 17e2b27..a867086 100644 (file)
@@ -193,7 +193,7 @@ bool DragData::canSmartReplace() const
     return m_dragDataMap.contains(smartPasteFormat()->cfFormat);
 }
 
-bool DragData::containsCompatibleContent() const
+bool DragData::containsCompatibleContent(DraggingPurpose) const
 {
     return containsPlainText() || containsURL()
         || ((m_platformDragData) ? (containsHTML(m_platformDragData) || containsFilenames(m_platformDragData))
index 618e041..4531748 100644 (file)
@@ -1,3 +1,16 @@
+2017-04-22  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        File inputs only accept UTI types that can be inserted into contenteditable areas when dropping
+        https://bugs.webkit.org/show_bug.cgi?id=171177
+        <rdar://problem/31765379>
+
+        Reviewed by Andy Estes.
+
+        Tests uploading a JSON file to a file input.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (TestWebKitAPI::TEST):
+
 2017-04-21  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Support writing link titles to the pasteboard when beginning data interaction on a link
index 70ccd7e..eb2d346 100644 (file)
@@ -333,6 +333,23 @@ TEST(DataInteractionTests, EnterAndLeaveEvents)
     checkSelectionRectsWithLogging(@[ ], [dataInteractionSimulator finalSelectionRects]);
 }
 
+TEST(DataInteractionTests, ExternalSourceJSONToFileInput)
+{
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [webView synchronouslyLoadTestPageNamed:@"file-uploading"];
+
+    RetainPtr<UIItemProvider> simulatedJSONItemProvider = adoptNS([[UIItemProvider alloc] init]);
+    NSData *jsonData = [@"{ \"foo\": \"bar\",  \"bar\": \"baz\" }" dataUsingEncoding:NSUTF8StringEncoding];
+    [simulatedJSONItemProvider registerFileRepresentationForTypeIdentifier:(NSString *)kUTTypeJSON withData:jsonData filename:@"data.json"];
+
+    RetainPtr<DataInteractionSimulator> dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [dataInteractionSimulator setExternalItemProviders:@[ simulatedJSONItemProvider.get() ]];
+    [dataInteractionSimulator runFrom:CGPointMake(200, 100) to:CGPointMake(100, 100)];
+
+    EXPECT_WK_STREQ("application/json", [webView stringByEvaluatingJavaScript:@"output.value"]);
+    cleanUpDataInteractionTemporaryPath();
+}
+
 TEST(DataInteractionTests, ExternalSourceImageToFileInput)
 {
     RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);