Add DataTransferItems support for drag-and-drop'ed files and texts
authorkinuko@chromium.org <kinuko@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jan 2012 12:08:56 +0000 (12:08 +0000)
committerkinuko@chromium.org <kinuko@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jan 2012 12:08:56 +0000 (12:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=76367

Reviewed by Tony Chang.

WebKit-svn:

* ManualTests/data-transfer-items-file-dragout.html: Added.
* ManualTests/resources/test:lorem-text.html: Added.

WebKit-svn/LayoutTests:

* editing/pasteboard/data-transfer-items-drag-drop-file-expected.txt: Added.
* editing/pasteboard/data-transfer-items-drag-drop-file.html: Added.
* editing/pasteboard/data-transfer-items-drag-drop-string-expected.txt: Added.
* editing/pasteboard/data-transfer-items-drag-drop-string.html: Added.
* platform/gtk/Skipped: Added the new tests as the platform does not support dataTransferItems yet.
* platform/mac/Skipped: Ditto.
* platform/qt/Skipped: Ditto.
* platform/win/Skipped: Ditto.

WebKit-svn/Source/WebCore:

Per http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-datatransfer-interface
the new interface should also support drag-and-dropped files and texts in
addition to pasted texts/images.  The user apps should also be able to add
texts/files to the drag store by calling event.dataTransfer.items.add().

This patch adds drag-and-drop'ed items support in DataTransferItem and
DataTransferItemList so that they work for dropped files and texts (as well as
the copy-pasted texts/images).

This patch also adds customized toJS()/toV8() code to Blob/File javascript
binding so that the JS code can get either Blob or File underlying object
where the API returns Blob. This change is necessary since we return Blob
from DataTransferItem.getAsFile() for pasted images but want to return File
for dropped files.

Tests: editing/pasteboard/data-transfer-items-drag-drop-file.html
       editing/pasteboard/data-transfer-items-drag-drop-string.html

* GNUmakefile.list.am: Added entries for the new {JS,V8}BlobCustom.
* Target.pri: Ditto.
* UseJSC.cmake: Ditto.
* WebCore.gypi: Ditto.
* bindings/js/JSBindingsAllInOne.cpp: Ditto.
* bindings/js/JSBlobCustom.cpp: Added toJS custom code that returns File or
Blob depending on the return value of isFile().
(WebCore::toJS):
* bindings/v8/custom/V8BlobCustom.cpp: Added toV8 custom code.
(WebCore::toV8):
* dom/DataTransferItem.h: Added a new create() method which takes File.
* dom/DataTransferItemList.cpp: Added add(File) method.
(WebCore::DataTransferItemList::add):
* dom/DataTransferItemList.h: Ditto.
* dom/DataTransferItemList.idl: Ditto.
* fileapi/Blob.idl: Added CustomToJS for toJS/toV8.
* platform/chromium/ClipboardChromium.cpp: Added code for drag-and-drop'ed items.
(WebCore::ClipboardChromium::items): Revised.
(WebCore::ClipboardChromium::mayUpdateItems): Added.
(WebCore::ClipboardChromium::isStorageUpdated): Added.
* platform/chromium/ClipboardChromium.h:
* platform/chromium/DataTransferItemChromium.cpp: Added a new constructor that
takes File and updated getAsFile() to make it support dropped files.
(WebCore::DataTransferItem::create):
(WebCore::DataTransferItemChromium::DataTransferItemChromium):
(WebCore::DataTransferItemChromium::getAsFile):
* platform/chromium/DataTransferItemChromium.h:
* platform/chromium/DataTransferItemListChromium.cpp:
(WebCore::DataTransferItemListChromium::addInternalItem):
* platform/chromium/DataTransferItemListChromium.cpp: Added overrides implementation for m_item accessors to make them reflect the changes in the owner clipboard.
(WebCore::DataTransferItemListChromium::length):
(WebCore::DataTransferItemListChromium::item):
(WebCore::DataTransferItemListChromium::deleteItem):
(WebCore::DataTransferItemListChromium::clear):
(WebCore::DataTransferItemListChromium::add):
(WebCore::DataTransferItemListChromium::mayUpdateItems): Added.
* platform/qt/DataTransferItemQt.cpp: Added a new constructor that takes File and updated
getAsFile() to make it support dropped files.
(WebCore::DataTransferItem::create):
(WebCore::DataTransferItemQt::DataTransferItemQt):
(WebCore::DataTransferItemQt::getAsFile):
* platform/qt/DataTransferItemQt.h:

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

38 files changed:
ChangeLog
LayoutTests/ChangeLog
LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-string-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-string.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/data-transfer-items-expected.txt
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/mac/Skipped
LayoutTests/platform/qt/Skipped
LayoutTests/platform/win/Skipped
ManualTests/data-transfer-items-file-dragout.html [new file with mode: 0644]
ManualTests/resources/test:lorem-text.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/UseJSC.cmake
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
Source/WebCore/bindings/js/JSBlobCustom.cpp [new file with mode: 0644]
Source/WebCore/bindings/v8/custom/V8BlobCustom.cpp [new file with mode: 0644]
Source/WebCore/dom/DataTransferItem.h
Source/WebCore/dom/DataTransferItemList.cpp
Source/WebCore/dom/DataTransferItemList.h
Source/WebCore/dom/DataTransferItemList.idl
Source/WebCore/fileapi/Blob.idl
Source/WebCore/platform/chromium/ChromiumDataObject.cpp
Source/WebCore/platform/chromium/ChromiumDataObject.h
Source/WebCore/platform/chromium/ClipboardChromium.cpp
Source/WebCore/platform/chromium/ClipboardChromium.h
Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
Source/WebCore/platform/chromium/DataTransferItemChromium.h
Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp
Source/WebCore/platform/chromium/DataTransferItemListChromium.h
Source/WebCore/platform/qt/DataTransferItemQt.cpp
Source/WebCore/platform/qt/DataTransferItemQt.h

index 1275ff4..ef15711 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-01-20  Kinuko Yasuda  <kinuko@chromium.org>
+
+        Add DataTransferItems support for drag-and-drop'ed files and texts
+        https://bugs.webkit.org/show_bug.cgi?id=76367
+
+        Reviewed by Tony Chang.
+
+        * ManualTests/data-transfer-items-file-dragout.html: Added.
+        * ManualTests/resources/test:lorem-text.html: Added.
+
 2012-01-20  Mario Sanchez Prada  <msanchez@igalia.com>
 
         [GTK] Expose accessibility hierarchy in WebKit2 to ATK/AT-SPI based ATs
index 78848bd..0a7450a 100644 (file)
@@ -1,3 +1,19 @@
+2012-01-20  Kinuko Yasuda  <kinuko@chromium.org>
+
+        Add DataTransferItems support for drag-and-drop'ed files and texts
+        https://bugs.webkit.org/show_bug.cgi?id=76367
+
+        Reviewed by Tony Chang.
+
+        * editing/pasteboard/data-transfer-items-drag-drop-file-expected.txt: Added.
+        * editing/pasteboard/data-transfer-items-drag-drop-file.html: Added.
+        * editing/pasteboard/data-transfer-items-drag-drop-string-expected.txt: Added.
+        * editing/pasteboard/data-transfer-items-drag-drop-string.html: Added.
+        * platform/gtk/Skipped: Added the new tests as the platform does not support dataTransferItems yet.
+        * platform/mac/Skipped: Ditto.
+        * platform/qt/Skipped: Ditto.
+        * platform/win/Skipped: Ditto.
+
 2012-01-20  Mario Sanchez Prada  <msanchez@igalia.com>
 
         [Gtk] Unreviewed, unskipping test passing after r105286.
diff --git a/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file-expected.txt
new file mode 100644 (file)
index 0000000..51bea25
--- /dev/null
@@ -0,0 +1,23 @@
+This tests the basic functionality and properties of DataTransferItems for files with drag and drop. This test requires DRT.
+Drop files here if you test this manually
+Dragging file: resources/mozilla.gif
+Dragging file: resources/drop-file-svg.svg
+Dragging file: resources/copy-backslash-euc.html
+Verifying contents of DataTransferItems...
+PASS: "3" == "3"
+PASS: "file" == "file"
+PASS: "image/gif" == "image/gif"
+PASS: "image/gif" == "image/gif"
+PASS: "2593" == "2593"
+PASS: "mozilla.gif" == "mozilla.gif"
+PASS: "file" == "file"
+PASS: "image/svg+xml" == "image/svg+xml"
+PASS: "image/svg+xml" == "image/svg+xml"
+PASS: "109" == "109"
+PASS: "drop-file-svg.svg" == "drop-file-svg.svg"
+PASS: "file" == "file"
+PASS: "text/html" == "text/html"
+PASS: "text/html" == "text/html"
+PASS: "478" == "478"
+PASS: "copy-backslash-euc.html" == "copy-backslash-euc.html"
+
diff --git a/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file.html b/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file.html
new file mode 100644 (file)
index 0000000..81ff3a2
--- /dev/null
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div>This tests the basic functionality and properties of DataTransferItems for files with drag and drop. This test requires DRT.</div>
+
+<div id="destination" style="min-height:100px; border: solid 1px black">Drop files here if you test this manually</div>
+
+<div id="console"></div>
+
+<script>
+var testFiles = [
+  { path: 'resources/mozilla.gif',
+    type: 'image/gif',
+    size: 2593 },
+  { path: 'resources/drop-file-svg.svg',
+    type: 'image/svg+xml',
+    size: 109 },
+  { path: 'resources/copy-backslash-euc.html',
+    type: 'text/html',
+    size: 478 }
+];
+
+function log(text)
+{
+    var console = document.getElementById('console');
+    console.appendChild(document.createTextNode(text));
+    console.appendChild(document.createElement('br'));
+}
+
+function test(expect, actual)
+{
+    log((expect == actual ? 'PASS' : 'FAIL') + ': "' + expect + '" == "' + actual + '"');
+}
+
+function startTest()
+{
+    var destination = document.getElementById('destination');
+    destination.addEventListener('dragover', handleDragOver, false);
+    destination.addEventListener('drop', handleDrop, false);
+
+    if (!window.layoutTestController)
+        return;
+    layoutTestController.waitUntilDone();
+    layoutTestController.dumpAsText();
+
+    var files = [];
+    for (var i = 0; i < testFiles.length; ++i) {
+      log('Dragging file: ' + testFiles[i].path);
+      files.push(testFiles[i].path);
+    }
+
+    // Perform drag-and-drop with the testFiles.
+    eventSender.beginDragWithFiles(files);
+    eventSender.leapForward(500);
+    eventSender.mouseMoveTo(destination.offsetLeft + 10, destination.offsetTop + destination.offsetHeight / 2);
+    eventSender.mouseUp();
+}
+
+function handleDragOver(e)
+{
+    e.stopPropagation();
+    e.preventDefault();
+}
+
+function handleDrop(e)
+{
+    e.stopPropagation();
+    e.preventDefault();
+
+    log('Verifying contents of DataTransferItems...');
+    var items = e.dataTransfer.items;
+    var files = [];
+    test(testFiles.length, items.length);
+    for (var i = 0; i < items.length; ++i) {
+        // The items should be in the same order as we added.
+        var expected = testFiles[i];
+
+        var file = items[i].getAsFile();
+        files.push(file);
+
+        test('file', items[i].kind);
+        test(expected.type, items[i].type);
+        test(expected.type, file.type);
+        test(expected.size, file.size);
+
+        var components = expected.path.split('/');
+        var name = components[components.length - 1];
+        test(name, file.name);
+    }
+
+    layoutTestController.notifyDone();
+}
+
+startTest();
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-string-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-string-expected.txt
new file mode 100644 (file)
index 0000000..e9ff61c
--- /dev/null
@@ -0,0 +1,16 @@
+This tests the basic functionality and properties of DataTransferItems for string data with drag and drop. This test requires DRT.
+Lorem ipsum 
+Drop text here if you test this manually
+Dragging text in source1: Lorem ipsum
+Verifying contents of DataTransferItems...
+items.length: 1
+items[0].kind: string
+items[0].type: text/plain
+PASS: "Lorem ipsum" == "Lorem ipsum"
+Dragging text in source2: http://example.com
+Verifying contents of DataTransferItems...
+items.length: 1
+items[0].kind: string
+items[0].type: text/plain
+PASS: "http://example.com" == "http://example.com"
+
diff --git a/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-string.html b/LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-string.html
new file mode 100644 (file)
index 0000000..5e4155f
--- /dev/null
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div>This tests the basic functionality and properties of DataTransferItems for string data with drag and drop. This test requires DRT.</div>
+
+<input id="source1" value="Lorem ipsum">Lorem ipsum</input>
+<input id="source2" value="http://example.com"></input>
+<div id="destination" style="min-height:100px; border: solid 1px black">Drop text here if you test this manually</div>
+
+<div id="console"></div>
+
+<script>
+var testSources = [ 'source1', 'source2' ];
+var testIndex = 0;
+var expectedDroppedText = '';
+
+function log(text)
+{
+    var console = document.getElementById('console');
+    console.appendChild(document.createTextNode(text));
+    console.appendChild(document.createElement('br'));
+}
+
+function test(expect, actual)
+{
+    log((expect == actual ? 'PASS' : 'FAIL') + ': "' + expect + '" == "' + actual + '"');
+}
+
+function startTest()
+{
+    var destination = document.getElementById('destination');
+    destination.addEventListener('dragover', handleDragOver, false);
+    destination.addEventListener('drop', handleDrop, false);
+
+    if (!window.layoutTestController)
+        return;
+    layoutTestController.waitUntilDone();
+    layoutTestController.dumpAsText();
+
+    runNextTest();
+}
+
+function runNextTest()
+{
+    if (testIndex == testSources.length) {
+        layoutTestController.notifyDone();
+        return;
+    }
+
+    var sourceId = testSources[testIndex++];
+    var source = document.getElementById(sourceId);
+    expectedDroppedText = source.value;
+    log('Dragging text in ' + sourceId + ': ' + source.value);
+
+    // Drag a text in the source element.
+    source.setSelectionRange(0, source.value.length);
+    x = source.offsetLeft + 10;
+    y = source.offsetTop + source.offsetHeight / 2;
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseDown();
+
+    // Drop it off to the destination field.
+    var destination = document.getElementById("destination");
+    eventSender.leapForward(500);
+    eventSender.mouseMoveTo(destination.offsetLeft + 10, destination.offsetTop + destination.offsetHeight / 2);
+    eventSender.mouseUp();
+}
+
+function handleDragOver(e)
+{
+    e.stopPropagation();
+    e.preventDefault();
+}
+
+function handleDrop(e)
+{
+    e.stopPropagation();
+    e.preventDefault();
+
+    log('Verifying contents of DataTransferItems...');
+
+    var items = e.dataTransfer.items;
+    var remaining = items.length;
+
+    for (var i = 0; i < items.length; ++i) {
+        log('items.length: ' + items.length);
+        log('items[' + i + '].kind: ' + items[i].kind);
+        log('items[' + i + '].type: ' + items[i].type);
+
+        items[i].getAsString(function(data) {
+            test(expectedDroppedText, data);
+            if (--remaining == 0 && window.layoutTestController)
+                runNextTest();
+        });
+    }
+}
+
+startTest();
+
+</script>
+</body>
+</html>
index 664e88d..519060c 100644 (file)
@@ -1,6 +1,6 @@
 This file tests the basic functionality and properties of DataTransferItems. This test requires DRT.
 Populating DataTransferItems...
-Caught exception "Error: INVALID_STATE_ERR: DOM Exception 11" as expected.
+Caught exception "Error: NOT_SUPPORTED_ERR: DOM Exception 9" as expected.
 Verifying contents of DataTransferItems...
 items.length: 2
 items[0].kind: string
index 655075f..104ae16 100644 (file)
@@ -292,6 +292,8 @@ media/media-captions.html
 # DataTransferItems is not yet implemented.
 editing/pasteboard/data-transfer-items.html
 editing/pasteboard/data-transfer-items-image-png.html
+editing/pasteboard/data-transfer-items-drag-drop-file.html
+editing/pasteboard/data-transfer-items-drag-drop-string.html
 
 # Custom MIME type support in DataTransfer is not yet implemented.
 editing/pasteboard/clipboard-customData.html
index ed0ebf6..4c6c369 100644 (file)
@@ -340,6 +340,8 @@ compositing/webgl/webgl-nonpremultiplied-blend.html
 # DataTransferItems is not yet implemented.
 editing/pasteboard/data-transfer-items.html
 editing/pasteboard/data-transfer-items-image-png.html
+editing/pasteboard/data-transfer-items-drag-drop-file.html
+editing/pasteboard/data-transfer-items-drag-drop-string.html
 
 # Custom MIME type support in DataTransfer is not yet implemented.
 editing/pasteboard/clipboard-customData.html
index 9a32f28..35f1e61 100644 (file)
@@ -353,6 +353,8 @@ editing/pasteboard/drag-and-drop-objectimage-contenteditable.html
 # data-transfer-items is not a default build option
 # See bug https://bugs.webkit.org/show_bug.cgi?id=60068
 editing/pasteboard/data-transfer-items.html
+editing/pasteboard/data-transfer-items-drag-drop-file.html
+editing/pasteboard/data-transfer-items-drag-drop-string.html
 
 # Missing drag & drop functionality in DRT
 editing/pasteboard/drop-inputtext-acquires-style.html
index d77f76b..6622f2e 100644 (file)
@@ -1300,6 +1300,8 @@ editing/pasteboard/onpaste-text-html-types.html
 # DataTransferItems is not yet implemented.
 editing/pasteboard/data-transfer-items.html
 editing/pasteboard/data-transfer-items-image-png.html
+editing/pasteboard/data-transfer-items-drag-drop-file.html
+editing/pasteboard/data-transfer-items-drag-drop-string.html
 
 # Custom MIME type support in DataTransfer not yet implemented.
 editing/pasteboard/clipboard-customData.html
diff --git a/ManualTests/data-transfer-items-file-dragout.html b/ManualTests/data-transfer-items-file-dragout.html
new file mode 100644 (file)
index 0000000..b76d25a
--- /dev/null
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p><b>BUG ID: 76367</b> <a href="http://bugs.webkit.org/show_bug.cgi?id=76367">Bugzilla bug </a> Add DataTransferItems support for drag-and-drop'ed files and texts</p>
+
+<p id="test" style="background-color:skyblue; padding:3px;"><b>STEPS TO TEST:</b> <br>
+1. Open the <a href="resources">$(WebKitRoot)/ManualTests/resources</a> folder in your native file browser.<br>
+2. Drag and drop the file 'test:lorem-text.html' into the 'Drop files here' area below.<br>
+3. Drag out <a href="#" id="dragout" draggable="true">this link</a> out of the browser window into a different folder in the native file browser).
+</p>
+
+<div id="destination" style="min-height:100px; margin: 5px; border: solid 1px black">Drop files here </div>
+
+<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
+The same file you dropped in the step 2 should be dragged out to the folder in the step 3.  The file should have the same content and the same file name (i.e. 'test:lorem-text.html', make sure the prefix 'test:' is not dropped) as the dropped file.  (NOTE: this does not work for multiple files yet.)
+</p>
+
+<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b>
+Nothing happens or a different file from the dropped one (likely a text file with the page title) is dragged out.
+</p>
+<p id="console"></p>
+
+<script>
+function log(text)
+{
+    var console = document.getElementById('console');
+    console.appendChild(document.createTextNode(text));
+    console.appendChild(document.createElement('br'));
+}
+
+function test(expect, actual)
+{
+    log((expect == actual ? 'PASS' : 'FAIL') + ': "' + expect + '" == "' + actual + '"');
+}
+
+var destination = document.getElementById('destination');
+destination.addEventListener('dragover', handleDragOver, false);
+destination.addEventListener('drop', handleDrop, false);
+
+function handleDragOver(e)
+{
+    e.stopPropagation();
+    e.preventDefault();
+}
+
+function handleDrop(e)
+{
+    e.stopPropagation();
+    e.preventDefault();
+
+    log('Verifying contents of DataTransferItems...');
+    var items = e.dataTransfer.items;
+    var files = [];
+    test(1, items.length);
+
+    for (var i = 0; i < items.length; ++i) {
+        test('file', items[i].kind);
+        var file = items[i].getAsFile();
+        log('Dragged files: ' + file.name);
+        log('Dragged file size: ' + file.size);
+        files.push(file);
+    }
+
+    // Setting up dragout items.
+    log('Setting up dragging out with the dropped items...');
+    var source = document.getElementById('dragout');
+    source.addEventListener('dragstart', function(e) {
+        for (var i = 0; i < files.length; ++i) {
+            log('Dragging out ' + files[i].name);
+            e.dataTransfer.items.add(files[i]);
+        }
+    }, false);
+
+    log('Please dragout the link (noted in the step 3) and see if the same file you dropped in in the step 2 is properly drag out.');
+}
+
+</script>
+</body>
+</html>
diff --git a/ManualTests/resources/test:lorem-text.html b/ManualTests/resources/test:lorem-text.html
new file mode 100644 (file)
index 0000000..12a42a6
--- /dev/null
@@ -0,0 +1,34 @@
+<HTML><HEAD><META http-equiv="Content-Type" content="text/html; charset=UTF-8"></HEAD><BODY><P>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
+        nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+        sed diam voluptua. At vero eos et accusam et justo duo dolores et ea
+        rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem
+        ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing
+        elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna
+        aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
+        dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus
+        est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
+        sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
+        dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam
+        et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
+        takimata sanctus est Lorem ipsum dolor sit amet.
+      </P>
+      <P>        Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse
+        molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero
+        eros et accumsan et iusto odio dignissim qui blandit praesent luptatum
+        zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum
+        dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh
+        euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+      </P>
+      <P>        Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
+        suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem
+        vel eum iriure dolor in hendrerit in vulputate velit esse molestie
+        consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et
+        accumsan et iusto odio dignissim qui blandit praesent luptatum zzril
+        delenit augue duis dolore te feugait nulla facilisi.
+      </P>
+      <P>        Nam liber tempor cum soluta nobis eleifend option congue nihil
+        imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum
+        dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh
+        euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut
+        wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
+        suscipit lobortis nisl ut aliquip ex ea commodo consequat.</P></BODY></HTML>
\ No newline at end of file
index f388863..339e9b5 100755 (executable)
@@ -1,3 +1,71 @@
+2012-01-20  Kinuko Yasuda  <kinuko@chromium.org>
+
+        Add DataTransferItems support for drag-and-drop'ed files and texts
+        https://bugs.webkit.org/show_bug.cgi?id=76367
+
+        Reviewed by Tony Chang.
+
+        Per http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-datatransfer-interface
+        the new interface should also support drag-and-dropped files and texts in
+        addition to pasted texts/images.  The user apps should also be able to add
+        texts/files to the drag store by calling event.dataTransfer.items.add().
+
+        This patch adds drag-and-drop'ed items support in DataTransferItem and
+        DataTransferItemList so that they work for dropped files and texts (as well as
+        the copy-pasted texts/images).
+
+        This patch also adds customized toJS()/toV8() code to Blob/File javascript
+        binding so that the JS code can get either Blob or File underlying object
+        where the API returns Blob. This change is necessary since we return Blob
+        from DataTransferItem.getAsFile() for pasted images but want to return File
+        for dropped files.
+
+        Tests: editing/pasteboard/data-transfer-items-drag-drop-file.html
+               editing/pasteboard/data-transfer-items-drag-drop-string.html
+
+        * GNUmakefile.list.am: Added entries for the new {JS,V8}BlobCustom.
+        * Target.pri: Ditto.
+        * UseJSC.cmake: Ditto.
+        * WebCore.gypi: Ditto.
+        * bindings/js/JSBindingsAllInOne.cpp: Ditto.
+        * bindings/js/JSBlobCustom.cpp: Added toJS custom code that returns File or
+        Blob depending on the return value of isFile().
+        (WebCore::toJS):
+        * bindings/v8/custom/V8BlobCustom.cpp: Added toV8 custom code.
+        (WebCore::toV8):
+        * dom/DataTransferItem.h: Added a new create() method which takes File.
+        * dom/DataTransferItemList.cpp: Added add(File) method.
+        (WebCore::DataTransferItemList::add):
+        * dom/DataTransferItemList.h: Ditto.
+        * dom/DataTransferItemList.idl: Ditto.
+        * fileapi/Blob.idl: Added CustomToJS for toJS/toV8.
+        * platform/chromium/ClipboardChromium.cpp: Added code for drag-and-drop'ed items.
+        (WebCore::ClipboardChromium::items): Revised.
+        (WebCore::ClipboardChromium::mayUpdateItems): Added.
+        (WebCore::ClipboardChromium::isStorageUpdated): Added.
+        * platform/chromium/ClipboardChromium.h:
+        * platform/chromium/DataTransferItemChromium.cpp: Added a new constructor that
+        takes File and updated getAsFile() to make it support dropped files.
+        (WebCore::DataTransferItem::create):
+        (WebCore::DataTransferItemChromium::DataTransferItemChromium):
+        (WebCore::DataTransferItemChromium::getAsFile):
+        * platform/chromium/DataTransferItemChromium.h:
+        * platform/chromium/DataTransferItemListChromium.cpp:
+        (WebCore::DataTransferItemListChromium::addInternalItem):
+        * platform/chromium/DataTransferItemListChromium.cpp: Added overrides implementation for m_item accessors to make them reflect the changes in the owner clipboard.
+        (WebCore::DataTransferItemListChromium::length):
+        (WebCore::DataTransferItemListChromium::item):
+        (WebCore::DataTransferItemListChromium::deleteItem):
+        (WebCore::DataTransferItemListChromium::clear):
+        (WebCore::DataTransferItemListChromium::add):
+        (WebCore::DataTransferItemListChromium::mayUpdateItems): Added.
+        * platform/qt/DataTransferItemQt.cpp: Added a new constructor that takes File and updated
+        getAsFile() to make it support dropped files.
+        (WebCore::DataTransferItem::create):
+        (WebCore::DataTransferItemQt::DataTransferItemQt):
+        (WebCore::DataTransferItemQt::getAsFile):
+        * platform/qt/DataTransferItemQt.h:
+
 2012-01-20  Alexis Menard  <alexis.menard@openbossa.org>
 
         remove CSSBorderImageValue
index 1a1b83d..785073f 100644 (file)
@@ -1006,6 +1006,7 @@ webcore_sources += \
        Source/WebCore/bindings/js/JSArrayBufferCustom.cpp \
        Source/WebCore/bindings/js/JSArrayBufferViewHelper.h \
        Source/WebCore/bindings/js/JSAttrCustom.cpp \
+       Source/WebCore/bindings/js/JSBlobCustom.cpp \
        Source/WebCore/bindings/js/JSCDATASectionCustom.cpp \
        Source/WebCore/bindings/js/JSCSSFontFaceRuleCustom.cpp \
        Source/WebCore/bindings/js/JSCSSImportRuleCustom.cpp \
index c047d75..1ca09e6 100644 (file)
@@ -78,6 +78,7 @@ v8 {
     SOURCES += \
         bindings/v8/custom/V8ArrayBufferCustom.cpp \
         bindings/v8/custom/V8ArrayBufferViewCustom.cpp \
+        bindings/v8/custom/V8BlobCustom.cpp \
         bindings/v8/custom/V8CustomXPathNSResolver.cpp \
         bindings/v8/custom/V8DataViewCustom.cpp \
         bindings/v8/custom/V8DeviceMotionEventCustom.cpp \
@@ -236,6 +237,7 @@ v8 {
         bindings/js/GCController.cpp \
         bindings/js/JSArrayBufferCustom.cpp \
         bindings/js/JSAttrCustom.cpp \
+        bindings/js/JSBlobCustom.cpp \
         bindings/js/JSCDATASectionCustom.cpp \
         bindings/js/JSCSSFontFaceRuleCustom.cpp \
         bindings/js/JSCSSImportRuleCustom.cpp \
index ed595f3..38e6731 100644 (file)
@@ -12,10 +12,11 @@ LIST(APPEND WebCore_SOURCES
     bindings/js/DOMObjectHashTableMap.cpp
     bindings/js/DOMWrapperWorld.cpp
     bindings/js/GCController.cpp
-    bindings/js/JSAttrCustom.cpp
     bindings/js/JSArrayBufferCustom.cpp
-    bindings/js/JSDataViewCustom.cpp
+    bindings/js/JSAttrCustom.cpp
+    bindings/js/JSBlobCustom.cpp
     bindings/js/JSCDATASectionCustom.cpp
+    bindings/js/JSDataViewCustom.cpp
     bindings/js/JSCSSFontFaceRuleCustom.cpp
     bindings/js/JSCSSImportRuleCustom.cpp
     bindings/js/JSCSSMediaRuleCustom.cpp
index 06af14b..5002534 100644 (file)
             'bindings/js/JSAudioBufferSourceNodeCustom.cpp',
             'bindings/js/JSAudioContextCustom.cpp',
             'bindings/js/JSBindingsAllInOne.cpp',
+            'bindings/js/JSBlobCustom.cpp',
             'bindings/js/JSCDATASectionCustom.cpp',
             'bindings/js/JSCSSFontFaceRuleCustom.cpp',
             'bindings/js/JSCSSImportRuleCustom.cpp',
             'bindings/v8/custom/V8AudioBufferSourceNodeCustom.cpp',
             'bindings/v8/custom/V8AudioContextCustom.cpp',
             'bindings/v8/custom/V8BindingMacros.h',
+            'bindings/v8/custom/V8BlobCustom.cpp',
             'bindings/v8/custom/V8CSSRuleCustom.cpp',
             'bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp',
             'bindings/v8/custom/V8CSSStyleSheetCustom.cpp',
index 5044ec0..d3f9fab 100755 (executable)
                                        >
                                </File>
                                <File
+                                       RelativePath="..\bindings\js\JSBlobCustom.cpp"
+                                       >
+                                       <FileConfiguration
+                                               Name="Debug|Win32"
+                                               ExcludedFromBuild="true"
+                                               >
+                                               <Tool
+                                                       Name="VCCLCompilerTool"
+                                               />
+                                       </FileConfiguration>
+                                       <FileConfiguration
+                                               Name="Release|Win32"
+                                               ExcludedFromBuild="true"
+                                               >
+                                               <Tool
+                                                       Name="VCCLCompilerTool"
+                                               />
+                                       </FileConfiguration>
+                                       <FileConfiguration
+                                               Name="Debug_Cairo_CFLite|Win32"
+                                               ExcludedFromBuild="true"
+                                               >
+                                               <Tool
+                                                       Name="VCCLCompilerTool"
+                                               />
+                                       </FileConfiguration>
+                                       <FileConfiguration
+                                               Name="Release_Cairo_CFLite|Win32"
+                                               ExcludedFromBuild="true"
+                                               >
+                                               <Tool
+                                                       Name="VCCLCompilerTool"
+                                               />
+                                       </FileConfiguration>
+                                       <FileConfiguration
+                                               Name="Debug_All|Win32"
+                                               ExcludedFromBuild="true"
+                                               >
+                                               <Tool
+                                                       Name="VCCLCompilerTool"
+                                               />
+                                       </FileConfiguration>
+                                       <FileConfiguration
+                                               Name="Production|Win32"
+                                               ExcludedFromBuild="true"
+                                               >
+                                               <Tool
+                                                       Name="VCCLCompilerTool"
+                                               />
+                                       </FileConfiguration>
+                               </File>
+                               <File
                                        RelativePath="..\bindings\js\JSCallbackData.cpp"
                                        >
                                        <FileConfiguration
index a30039b..250cb8d 100644 (file)
                892CF20E134C8BB300AAEDA1 /* JSStorageInfoErrorCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 892CF206134C8BB300AAEDA1 /* JSStorageInfoErrorCallback.h */; };
                892CF211134C8BB300AAEDA1 /* JSStorageInfoUsageCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 892CF209134C8BB300AAEDA1 /* JSStorageInfoUsageCallback.cpp */; };
                892CF212134C8BB300AAEDA1 /* JSStorageInfoUsageCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 892CF20A134C8BB300AAEDA1 /* JSStorageInfoUsageCallback.h */; };
+               8931DE5B14C44C44000DC9D2 /* JSBlobCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8931DE5A14C44C44000DC9D2 /* JSBlobCustom.cpp */; };
                893C47A71238908B002B3D86 /* FileCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 893C47A51238908B002B3D86 /* FileCallback.h */; };
                893C47A81238908B002B3D86 /* FileWriterCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 893C47A61238908B002B3D86 /* FileWriterCallback.h */; };
                893C47B71238A099002B3D86 /* JSFileCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 893C47B51238A099002B3D86 /* JSFileCallback.cpp */; };
                892CF206134C8BB300AAEDA1 /* JSStorageInfoErrorCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStorageInfoErrorCallback.h; sourceTree = "<group>"; };
                892CF209134C8BB300AAEDA1 /* JSStorageInfoUsageCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStorageInfoUsageCallback.cpp; sourceTree = "<group>"; };
                892CF20A134C8BB300AAEDA1 /* JSStorageInfoUsageCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStorageInfoUsageCallback.h; sourceTree = "<group>"; };
+               8931DE5A14C44C44000DC9D2 /* JSBlobCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBlobCustom.cpp; sourceTree = "<group>"; };
                893C47A51238908B002B3D86 /* FileCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileCallback.h; path = fileapi/FileCallback.h; sourceTree = "<group>"; };
                893C47A61238908B002B3D86 /* FileWriterCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileWriterCallback.h; path = fileapi/FileWriterCallback.h; sourceTree = "<group>"; };
                893C47B51238A099002B3D86 /* JSFileCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFileCallback.cpp; sourceTree = "<group>"; };
                                BC2ED6BB0C6BD2F000920BFF /* JSAttrCustom.cpp */,
                                FDEAAAEF12B02EE400DCF33B /* JSAudioBufferSourceNodeCustom.cpp */,
                                FDEAAAF012B02EE400DCF33B /* JSAudioContextCustom.cpp */,
+                               8931DE5A14C44C44000DC9D2 /* JSBlobCustom.cpp */,
                                49EED14B1051971900099FAB /* JSCanvasRenderingContext2DCustom.cpp */,
                                49EED14D1051971A00099FAB /* JSCanvasRenderingContextCustom.cpp */,
                                93BA59B10F2AA5FE008E8E99 /* JSCDATASectionCustom.cpp */,
                                93F19A2608245E59001E9ABC /* CursorMac.mm in Sources */,
                                62CD32591157E57C0063B0A7 /* CustomEvent.cpp in Sources */,
                                50D405F9147D31F300D30BB5 /* CustomFilterMesh.cpp in Sources */,
+                               50CC0A3914C6F5B10017AB51 /* CustomFilterOperation.cpp in Sources */,
                                503D0CAA14B5B08700F32F57 /* CustomFilterProgram.cpp in Sources */,
                                50D40611147D49DE00D30BB5 /* CustomFilterShader.cpp in Sources */,
                                5196116A0CAC56570010A80C /* Database.cpp in Sources */,
                                BC946346107A934B00857193 /* JSBeforeLoadEvent.cpp in Sources */,
                                FDF09DC81399B62200688E5B /* JSBiquadFilterNode.cpp in Sources */,
                                2E2D99CD10E2BBDA00496337 /* JSBlob.cpp in Sources */,
+                               8931DE5B14C44C44000DC9D2 /* JSBlobCustom.cpp in Sources */,
                                1449E287107D4DB400B5793F /* JSCallbackData.cpp in Sources */,
                                65DF323909D1DE65000BE325 /* JSCanvasGradient.cpp in Sources */,
                                65DF323B09D1DE65000BE325 /* JSCanvasPattern.cpp in Sources */,
                                A8CFF5E70A155A05000A4234 /* RootInlineBox.cpp in Sources */,
                                49E911C80EF86D47009D0CAF /* RotateTransformOperation.cpp in Sources */,
                                A73F95FE12C97BFE0031AAF9 /* RoundedRect.cpp in Sources */,
+                               BC0B358314C4F9540055E22A /* RunLoopMac.mm in Sources */,
+                               BC0B358714C4F9830055E22A /* RunLoop.cpp in Sources */,
                                1C63A2490F71646600C09D5A /* RunLoopTimerCF.cpp in Sources */,
                                1A569D1E0D7E2B82007C3983 /* runtime_array.cpp in Sources */,
                                1A569D200D7E2B82007C3983 /* runtime_method.cpp in Sources */,
                                E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */,
                                977E2E0E12F0FC9C00C13379 /* XSSAuditor.cpp in Sources */,
                                FD537352137B651800008DCE /* ZeroPole.cpp in Sources */,
-                               50CC0A3914C6F5B10017AB51 /* CustomFilterOperation.cpp in Sources */,
-                               BC0B358314C4F9540055E22A /* RunLoopMac.mm in Sources */,
-                               BC0B358714C4F9830055E22A /* RunLoop.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index b8afda2..061ca59 100644 (file)
@@ -31,6 +31,7 @@
 #include "GCController.cpp"
 #include "JSArrayBufferCustom.cpp"
 #include "JSAttrCustom.cpp"
+#include "JSBlobCustom.cpp"
 #include "JSCDATASectionCustom.cpp"
 #include "JSCSSFontFaceRuleCustom.cpp"
 #include "JSCSSImportRuleCustom.cpp"
diff --git a/Source/WebCore/bindings/js/JSBlobCustom.cpp b/Source/WebCore/bindings/js/JSBlobCustom.cpp
new file mode 100644 (file)
index 0000000..0494560
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSBlob.h"
+
+#include "Blob.h"
+#include "JSDOMBinding.h"
+#include "JSFile.h"
+#include <wtf/Assertions.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Blob* blob)
+{
+    if (!blob)
+        return jsNull();
+
+    if (blob->isFile())
+        return CREATE_DOM_WRAPPER(exec, globalObject, File, blob);
+
+    return CREATE_DOM_WRAPPER(exec, globalObject, Blob, blob);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/custom/V8BlobCustom.cpp b/Source/WebCore/bindings/v8/custom/V8BlobCustom.cpp
new file mode 100644 (file)
index 0000000..6853578
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Blob.h"
+
+#include "V8Blob.h"
+#include "V8File.h"
+#include "V8Proxy.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+v8::Handle<v8::Value> toV8(Blob* impl)
+{
+    if (!impl)
+        return v8::Null();
+
+    if (impl->isFile())
+        return toV8(static_cast<File*>(impl));
+
+    return V8Blob::wrap(impl);
+}
+
+} // namespace WebCore
index 74c25b7..18126db 100644 (file)
@@ -41,6 +41,7 @@
 namespace WebCore {
 
 class Blob;
+class File;
 class StringCallback;
 class ScriptExecutionContext;
 
@@ -49,6 +50,7 @@ public:
     virtual ~DataTransferItem() { }
 
     static PassRefPtr<DataTransferItem> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& data, const String& type);
+    static PassRefPtr<DataTransferItem> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, PassRefPtr<File>);
 
     static const char kindString[];
     static const char kindFile[];
@@ -64,6 +66,8 @@ protected:
     Clipboard* owner();
 
 private:
+    friend class DataTransferItemList;
+
     const RefPtr<Clipboard> m_owner;
     const String m_kind;
     const String m_type;
index b5feaca..58f5f4a 100644 (file)
@@ -45,7 +45,7 @@ DataTransferItemList::DataTransferItemList(PassRefPtr<Clipboard> clipboard, Scri
 {
 }
 
-size_t DataTransferItemList::length() const
+size_t DataTransferItemList::length()
 {
     if (m_owner->policy() == ClipboardNumb)
         return 0;
@@ -91,7 +91,7 @@ void DataTransferItemList::add(const String& data, const String& type, Exception
     // Only one 'string' item with a given type is allowed in the collection.
     for (size_t i = 0; i < m_items.size(); ++i) {
         if (m_items[i]->type() == type && m_items[i]->kind() == DataTransferItem::kindString) {
-            ec = INVALID_STATE_ERR;
+            ec = NOT_SUPPORTED_ERR;
             return;
         }
     }
@@ -99,6 +99,14 @@ void DataTransferItemList::add(const String& data, const String& type, Exception
     m_items.append(DataTransferItem::create(m_owner, m_context, data, type));
 }
 
+void DataTransferItemList::add(PassRefPtr<File> file)
+{
+    if (m_owner->policy() != ClipboardWritable || !file)
+        return;
+
+    m_items.append(DataTransferItem::create(m_owner, m_context, file));
+}
+
 }
 
 #endif
index ef318e9..28b7c24 100644 (file)
@@ -40,6 +40,7 @@
 namespace WebCore {
 
 class Clipboard;
+class File;
 
 typedef int ExceptionCode;
 
@@ -47,11 +48,13 @@ class DataTransferItemList : public RefCounted<DataTransferItemList> {
 public:
     virtual ~DataTransferItemList() { }
 
-    virtual size_t length() const;
+    virtual size_t length();
     virtual PassRefPtr<DataTransferItem> item(unsigned long index);
+    // FIXME: Implement V8DataTransferItemList::indexedPropertyDeleter to get this called.
     virtual void deleteItem(unsigned long index, ExceptionCode&);
     virtual void clear();
     virtual void add(const String& data, const String& type, ExceptionCode&);
+    virtual void add(PassRefPtr<File>);
 
 protected:
     DataTransferItemList(PassRefPtr<Clipboard>, ScriptExecutionContext*);
@@ -69,4 +72,3 @@ protected:
 #endif // ENABLE(DATA_TRANSFER_ITEMS)
 
 #endif // DataTransferItemList_h
-
index b033939..4adff1e 100644 (file)
@@ -33,6 +33,7 @@ module core {
     interface [
         Conditional=DATA_TRANSFER_ITEMS,
         HasIndexGetter,
+        GenerateNativeConverter,
 #if defined(V8_BINDING) && V8_BINDING
         CustomDeleteProperty,
 #endif
@@ -41,6 +42,7 @@ module core {
         DataTransferItem item(in [Optional=CallWithDefaultValue] unsigned long index);
 
         void clear();
+        void add(in File file);
         void add(in [Optional=CallWithDefaultValue] DOMString data, 
                  in [Optional=CallWithDefaultValue] DOMString type) raises(DOMException);
     };
index e9b7959..9902cd4 100644 (file)
@@ -32,6 +32,7 @@ module html {
 
     interface [
         GenerateIsReachable=Impl,
+        CustomToJS,
         NoStaticTables
     ] Blob {
         readonly attribute unsigned long long size;
index 05c5e13..cc42fa8 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "ClipboardMimeTypes.h"
 #include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItemListChromium.h"
 #include "Pasteboard.h"
 #include "PlatformSupport.h"
 
index 9ddfb0b..7e675bf 100644 (file)
@@ -85,11 +85,14 @@ public:
     KURL htmlBaseUrl() const { return m_htmlBaseUrl; }
     void setHtmlBaseUrl(const KURL& url) { m_htmlBaseUrl = url; }
 
-    // Used to handle files being dragged in.
+    // Used to handle files being dragged in and out.
     bool containsFilenames() const;
-    Vector<String> filenames() const { return m_filenames; }
+    const Vector<String>& filenames() const { return m_filenames; }
     void setFilenames(const Vector<String>& filenames) { m_filenames = filenames; }
 
+    // Used to handle files being dragged out.
+    void addFilename(const String& filename) { m_filenames.append(filename); }
+
     // Used to handle files (images) being dragged out.
     String fileExtension() const { return m_fileExtension; }
     void setFileExtension(const String& fileExtension) { m_fileExtension = fileExtension; }
index cd0bf78..3278390 100644 (file)
 #include "ChromiumDataObject.h"
 #include "ClipboardMimeTypes.h"
 #include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItemChromium.h"
 #include "DataTransferItemListChromium.h"
 #include "Document.h"
 #include "DragData.h"
 #include "Element.h"
+#include "File.h"
 #include "FileList.h"
 #include "Frame.h"
 #include "HTMLNames.h"
@@ -48,7 +50,6 @@
 #include "ScriptExecutionContext.h"
 #include "markup.h"
 
-#include <wtf/text/StringBuilder.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -79,6 +80,11 @@ ClipboardChromium::ClipboardChromium(ClipboardType clipboardType,
     , m_dataObject(dataObject)
     , m_frame(frame)
     , m_originalSequenceNumber(PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()))
+    , m_dragStorageUpdated(true)
+{
+}
+
+ClipboardChromium::~ClipboardChromium()
 {
 }
 
@@ -93,6 +99,7 @@ void ClipboardChromium::clearData(const String& type)
     if (policy() != ClipboardWritable || !m_dataObject)
         return;
 
+    m_dragStorageUpdated = true;
     m_dataObject->clearData(normalizeType(type));
 
     ASSERT_NOT_REACHED();
@@ -103,6 +110,7 @@ void ClipboardChromium::clearAllData()
     if (policy() != ClipboardWritable)
         return;
 
+    m_dragStorageUpdated = true;
     m_dataObject->clearAll();
 }
 
@@ -123,6 +131,7 @@ bool ClipboardChromium::setData(const String& type, const String& data)
     if (policy() != ClipboardWritable)
         return false;
 
+    m_dragStorageUpdated = true;
     return m_dataObject->setData(normalizeType(type), data);
 }
 
@@ -260,6 +269,7 @@ void ClipboardChromium::declareAndWriteDragImage(Element* element, const KURL& u
     if (!m_dataObject)
         return;
 
+    m_dragStorageUpdated = true;
     m_dataObject->setData(mimeTypeURL, url);
     m_dataObject->setUrlTitle(title);
 
@@ -275,6 +285,8 @@ void ClipboardChromium::writeURL(const KURL& url, const String& title, Frame*)
     if (!m_dataObject)
         return;
     ASSERT(!url.isEmpty());
+
+    m_dragStorageUpdated = true;
     m_dataObject->setData(mimeTypeURL, url);
     m_dataObject->setUrlTitle(title);
 
@@ -292,6 +304,7 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
     if (!m_dataObject)
          return;
 
+    m_dragStorageUpdated = true;
     m_dataObject->setData(mimeTypeTextHTML, createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs));
     m_dataObject->setHtmlBaseUrl(frame->document()->url());
 
@@ -313,6 +326,8 @@ void ClipboardChromium::writePlainText(const String& text)
     replaceNewlinesWithWindowsStyleNewlines(str);
 #endif
     replaceNBSPWithSpace(str);
+
+    m_dragStorageUpdated = true;
     m_dataObject->setData(mimeTypeTextPlain, str);
 }
 
@@ -328,19 +343,58 @@ bool ClipboardChromium::hasData()
 #if ENABLE(DATA_TRANSFER_ITEMS)
 PassRefPtr<DataTransferItemList> ClipboardChromium::items()
 {
-    RefPtr<DataTransferItemListChromium> items = DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
+    if (!m_dataObject || (policy() != ClipboardReadable && policy() != ClipboardWritable)) {
+        // Return an unassociated empty list.
+        return DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
+    }
 
-    if (!m_dataObject)
-        return items;
+    if (!m_itemList)
+        m_itemList = DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
+
+    return m_itemList;
+}
+
+// FIXME: integrate ChromiumDataObject and DataTransferItemList rather than holding them separately and keeping them synced.
+void ClipboardChromium::mayUpdateItems(Vector<RefPtr<DataTransferItem> >& items)
+{
+    if (!items.isEmpty() && !storageHasUpdated())
+        return;
+
+    items.clear();
+
+    ScriptExecutionContext* scriptExecutionContext = m_frame->document()->scriptExecutionContext();
 
     if (isForCopyAndPaste() && policy() == ClipboardReadable) {
         // Iterate through the types and add them.
         HashSet<String> types = m_dataObject->types();
         for (HashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it)
-            items->addPasteboardItem(*it);
+            items.append(DataTransferItemChromium::createFromPasteboard(this, scriptExecutionContext, *it));
+        return;
     }
-    return items;
+
+    bool success = false;
+    String plainText = m_dataObject->getData(mimeTypeTextPlain, success);
+    if (success)
+        items.append(DataTransferItem::create(this, scriptExecutionContext, plainText, mimeTypeTextPlain));
+
+    success = false;
+    String htmlText = m_dataObject->getData(mimeTypeTextHTML, success);
+    if (success)
+        items.append(DataTransferItem::create(this, scriptExecutionContext, htmlText, mimeTypeTextHTML));
+
+    if (m_dataObject->containsFilenames()) {
+        const Vector<String>& filenames = m_dataObject->filenames();
+        for (Vector<String>::const_iterator it = filenames.begin(); it != filenames.end(); ++it)
+            items.append(DataTransferItem::create(this, scriptExecutionContext, File::create(*it)));
+    }
+    m_dragStorageUpdated = false;
 }
+
+bool ClipboardChromium::storageHasUpdated() const
+{
+    return (isForCopyAndPaste() && platformClipboardChanged()) || (isForDragAndDrop() && m_dragStorageUpdated);
+}
+
 #endif
 
 } // namespace WebCore
index 8b17452..30e8739 100644 (file)
@@ -38,13 +38,15 @@ namespace WebCore {
 
     class CachedImage;
     class ChromiumDataObject;
+    class DataTransferItem;
+    class DataTransferItemListChromium;
     class Frame;
     class IntPoint;
 
     class ClipboardChromium : public Clipboard, public CachedImageClient {
         WTF_MAKE_FAST_ALLOCATED;
     public:
-        ~ClipboardChromium() {}
+        ~ClipboardChromium();
 
         static PassRefPtr<ClipboardChromium> create(
             ClipboardType, PassRefPtr<ChromiumDataObject>, ClipboardAccessPolicy, Frame*);
@@ -83,6 +85,10 @@ namespace WebCore {
 
 #if ENABLE(DATA_TRANSFER_ITEMS)
         virtual PassRefPtr<DataTransferItemList> items();
+
+        // Internal routines to keep the list returned by items() (i.e. m_itemList) synchronized with the content of the clipboard data.
+        void mayUpdateItems(Vector<RefPtr<DataTransferItem> >& items);
+        bool storageHasUpdated() const;
 #endif
 
     private:
@@ -93,7 +99,12 @@ namespace WebCore {
         RefPtr<ChromiumDataObject> m_dataObject;
         Frame* m_frame;
 
+#if ENABLE(DATA_TRANSFER_ITEMS)
+        RefPtr<DataTransferItemListChromium> m_itemList;
+#endif
+
         uint64_t m_originalSequenceNumber;
+        bool m_dragStorageUpdated;
     };
 
 } // namespace WebCore
index a79ae85..557fe36 100644 (file)
@@ -38,6 +38,8 @@
 #include "ClipboardChromium.h"
 #include "ClipboardMimeTypes.h"
 #include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItemListChromium.h"
+#include "File.h"
 #include "PlatformSupport.h"
 #include "SharedBuffer.h"
 #include "StringCallback.h"
@@ -47,24 +49,23 @@ namespace WebCore {
 PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, const String& type)
 {
     if (type == mimeTypeTextPlain || type == mimeTypeTextHTML)
-        return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindString, type, ""));
+        return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindString, type, String()));
     return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindFile, type, ""));
 }
 
-PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr<Clipboard> owner,
-                                                                      ScriptExecutionContext* context,
-                                                                      const String& data,
-                                                                      const String& type)
+PassRefPtr<DataTransferItem> DataTransferItem::create(PassRefPtr<Clipboard> owner,
+                                                      ScriptExecutionContext* context,
+                                                      const String& data,
+                                                      const String& type)
 {
-    return adoptRef(new DataTransferItemChromium(owner, context, InternalSource, DataTransferItem::kindString, type, data));
+    return adoptRef(new DataTransferItemChromium(owner, context, DataTransferItemChromium::InternalSource, kindString, type, data));
 }
 
 PassRefPtr<DataTransferItem> DataTransferItem::create(PassRefPtr<Clipboard> owner,
                                                       ScriptExecutionContext* context,
-                                                      const String& data,
-                                                      const String& type)
+                                                      PassRefPtr<File> file)
 {
-    return DataTransferItemChromium::create(owner, context, data, type);
+    return adoptRef(new DataTransferItemChromium(owner, context, DataTransferItemChromium::InternalSource, file));
 }
 
 DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, DataSource source, const String& kind, const String& type, const String& data)
@@ -75,20 +76,29 @@ DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner,
 {
 }
 
+DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, DataSource source, PassRefPtr<File> file)
+    : DataTransferItem(owner, DataTransferItem::kindFile, file.get() ? file->type() : String())
+    , m_context(context)
+    , m_source(source)
+    , m_file(file)
+{
+}
+
 void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback)
 {
     if ((owner()->policy() != ClipboardReadable && owner()->policy() != ClipboardWritable)
         || kind() != kindString)
         return;
 
+    if (clipboardChromium()->storageHasUpdated())
+        return;
+
     if (m_source == InternalSource) {
         callback->scheduleCallback(m_context, m_data);
         return;
     }
 
     ASSERT(m_source == PasteboardSource);
-    if (static_cast<ClipboardChromium*>(owner())->platformClipboardChanged())
-        return;
 
     // This is ugly but there's no real alternative.
     if (type() == mimeTypeTextPlain) {
@@ -108,11 +118,11 @@ void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback)
 
 PassRefPtr<Blob> DataTransferItemChromium::getAsFile()
 {
-    if (m_source == InternalSource)
+    if (kind() != kindFile || clipboardChromium()->storageHasUpdated())
         return 0;
 
-    if (static_cast<ClipboardChromium*>(owner())->platformClipboardChanged())
-        return 0;
+    if (m_source == InternalSource)
+        return m_file;
 
     ASSERT(m_source == PasteboardSource);
     if (type() == mimeTypeImagePng) {
@@ -136,6 +146,11 @@ PassRefPtr<Blob> DataTransferItemChromium::getAsFile()
     return 0;
 }
 
+ClipboardChromium* DataTransferItemChromium::clipboardChromium()
+{
+    return static_cast<ClipboardChromium*>(owner());
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(DATA_TRANSFER_ITEMS)
index 144e40f..1a8dde7 100644 (file)
 namespace WebCore {
 
 class Clipboard;
+class ClipboardChromium;
+class File;
 class ScriptExecutionContext;
 
 class DataTransferItemChromium : public DataTransferItem {
 public:
     static PassRefPtr<DataTransferItemChromium> createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& type);
-    static PassRefPtr<DataTransferItemChromium> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& data, const String& type);
 
     virtual void getAsString(PassRefPtr<StringCallback>);
     virtual PassRefPtr<Blob> getAsFile();
@@ -56,11 +57,17 @@ private:
         InternalSource,
     };
 
+    friend class DataTransferItem;
+
     DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, DataSource, const String& kind, const String& type, const String& data);
+    DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, DataSource, PassRefPtr<File>);
+
+    ClipboardChromium* clipboardChromium();
 
     ScriptExecutionContext* m_context;
     const DataSource m_source;
     const String m_data;
+    RefPtr<File> m_file;
 };
 
 } // namespace WebCore
index 320e749..038db8b 100644 (file)
 
 #if ENABLE(DATA_TRANSFER_ITEMS)
 
-#include "Clipboard.h"
+#include "BlobURL.h"
+#include "ChromiumDataObject.h"
+#include "ClipboardChromium.h"
+#include "ClipboardMimeTypes.h"
 #include "DataTransferItemChromium.h"
 #include "ExceptionCode.h"
+#include "File.h"
+#include "KURL.h"
+#include "ScriptExecutionContext.h"
+#include "ThreadableBlobRegistry.h"
+#include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
@@ -49,9 +57,127 @@ DataTransferItemListChromium::DataTransferItemListChromium(PassRefPtr<Clipboard>
 {
 }
 
-void DataTransferItemListChromium::addPasteboardItem(const String& type)
+size_t DataTransferItemListChromium::length()
 {
-    m_items.append(DataTransferItemChromium::createFromPasteboard(m_owner, m_context, type));
+    if (m_owner->policy() == ClipboardNumb)
+        return 0;
+    clipboardChromium()->mayUpdateItems(m_items);
+    return m_items.size();
+}
+
+PassRefPtr<DataTransferItem> DataTransferItemListChromium::item(unsigned long index)
+{
+    if (m_owner->policy() == ClipboardNumb)
+        return 0;
+
+    clipboardChromium()->mayUpdateItems(m_items);
+    if (index >= length())
+        return 0;
+    return m_items[index];
+}
+
+void DataTransferItemListChromium::deleteItem(unsigned long index, ExceptionCode& ec)
+{
+    if (m_owner->policy() != ClipboardWritable) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    clipboardChromium()->mayUpdateItems(m_items);
+    if (index >= length())
+        return;
+    RefPtr<DataTransferItem> item = m_items[index];
+
+    RefPtr<ChromiumDataObject> dataObject = clipboardChromium()->dataObject();
+    if (!dataObject)
+        return;
+
+    if (item->kind() == DataTransferItem::kindString) {
+        m_items.remove(index);
+        dataObject->clearData(item->type());
+        return;
+    }
+
+    ASSERT(item->kind() == DataTransferItem::kindFile);
+    RefPtr<Blob> blob = item->getAsFile();
+    if (!blob || !blob->isFile())
+        return;
+
+    m_items.clear();
+    const Vector<String>& filenames = dataObject->filenames();
+    Vector<String> copiedFilenames;
+    for (size_t i = 0; i < filenames.size(); ++i) {
+        if (filenames[i] != static_cast<File*>(blob.get())->path())
+            copiedFilenames.append(static_cast<File*>(blob.get())->path());
+    }
+    dataObject->setFilenames(copiedFilenames);
+}
+
+void DataTransferItemListChromium::clear()
+{
+    if (m_owner->policy() != ClipboardWritable)
+        return;
+
+    m_items.clear();
+    clipboardChromium()->clearAllData();
+}
+
+void DataTransferItemListChromium::add(const String& data, const String& type, ExceptionCode& ec)
+{
+    if (m_owner->policy() != ClipboardWritable)
+        return;
+
+    RefPtr<ChromiumDataObject> dataObject = clipboardChromium()->dataObject();
+    if (!dataObject)
+        return;
+
+    bool success = false;
+    dataObject->getData(type, success);
+    if (success) {
+        // Adding data with the same type should fail with NOT_SUPPORTED_ERR.
+        ec = NOT_SUPPORTED_ERR;
+        return;
+    }
+
+    m_items.clear();
+    dataObject->setData(type, data);
+}
+
+void DataTransferItemListChromium::add(PassRefPtr<File> file)
+{
+    if (m_owner->policy() != ClipboardWritable || !file)
+        return;
+
+    RefPtr<ChromiumDataObject> dataObject = clipboardChromium()->dataObject();
+    if (!dataObject)
+        return;
+
+    m_items.clear();
+
+    // Updating dataObject's fileset so that we will be seeing the consistent list even if we reconstruct the items later.
+    dataObject->addFilename(file->path());
+
+    // FIXME: Allow multiple files to be dragged out at once if more than one file is added to the storage. For now we manually set up drag-out download URL only if it has not been set yet.
+    bool success = false;
+    dataObject->getData(mimeTypeDownloadURL, success);
+    if (success)
+        return;
+
+    KURL urlForDownload = BlobURL::createPublicURL(m_context->securityOrigin());
+    ThreadableBlobRegistry::registerBlobURL(urlForDownload, file->url());
+
+    StringBuilder downloadUrl;
+    downloadUrl.append(file->type());
+    downloadUrl.append(":");
+    downloadUrl.append(encodeWithURLEscapeSequences(file->name()));
+    downloadUrl.append(":");
+    downloadUrl.append(urlForDownload.string());
+    dataObject->setData(mimeTypeDownloadURL, downloadUrl.toString());
+}
+
+ClipboardChromium* DataTransferItemListChromium::clipboardChromium() const
+{
+    return static_cast<ClipboardChromium*>(m_owner.get());
 }
 
 } // namespace WebCore
index a3321b5..c137cad 100644 (file)
@@ -40,7 +40,8 @@
 namespace WebCore {
 
 class Clipboard;
-class DataTransferItemChromium;
+class ClipboardChromium;
+class File;
 class ScriptExecutionContext;
 
 typedef int ExceptionCode;
@@ -49,12 +50,17 @@ class DataTransferItemListChromium : public DataTransferItemList {
 public:
     static PassRefPtr<DataTransferItemListChromium> create(PassRefPtr<Clipboard>, ScriptExecutionContext*);
 
-private:
-    friend class ClipboardChromium;
+    // DataTransferItemList overrides.
+    virtual size_t length();
+    virtual PassRefPtr<DataTransferItem> item(unsigned long index);
+    virtual void deleteItem(unsigned long index, ExceptionCode&);
+    virtual void clear();
+    virtual void add(const String& data, const String& type, ExceptionCode&);
+    virtual void add(PassRefPtr<File>);
 
+private:
     DataTransferItemListChromium(PassRefPtr<Clipboard>, ScriptExecutionContext*);
-
-    virtual void addPasteboardItem(const String& type);
+    ClipboardChromium* clipboardChromium() const;
 };
 
 } // namespace WebCore
@@ -62,4 +68,3 @@ private:
 #endif // ENABLE(DATA_TRANSFER_ITEMS)
 
 #endif // DataTransferItemListChromium_h
-
index b277bef..2ab77ac 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "Blob.h"
 #include "Clipboard.h"
+#include "File.h"
 #include "NotImplemented.h"
 #include "StringCallback.h"
 #include <QApplication>
@@ -45,7 +46,14 @@ PassRefPtr<DataTransferItem> DataTransferItem::create(PassRefPtr<Clipboard> owne
                                                       const String& data,
                                                       const String& type)
 {
-    return DataTransferItemQt::create(owner, context, type, data);
+    return adoptRef(new DataTransferItemQt(owner, context, DataTransferItemQt::InternalSource, kindString, type, data));
+}
+
+PassRefPtr<DataTransferItem> DataTransferItem::create(PassRefPtr<Clipboard> owner,
+                                                      ScriptExecutionContext* context,
+                                                      PassRefPtr<File> file)
+{
+    return adoptRef(new DataTransferItemQt(owner, context, DataTransferItemQt::InternalSource, file));
 }
 
 PassRefPtr<DataTransferItemQt> DataTransferItemQt::createFromPasteboard(PassRefPtr<Clipboard> owner,
@@ -58,14 +66,6 @@ PassRefPtr<DataTransferItemQt> DataTransferItemQt::createFromPasteboard(PassRefP
     return adoptRef(new DataTransferItemQt(owner, context, PasteboardSource, DataTransferItem::kindFile, type, ""));
 }
 
-PassRefPtr<DataTransferItemQt> DataTransferItemQt::create(PassRefPtr<Clipboard> owner,
-                                                          ScriptExecutionContext* context,
-                                                          const String& type,
-                                                          const String& data)
-{
-    return adoptRef(new DataTransferItemQt(owner, context, InternalSource, DataTransferItem::kindString, type, data));
-}
-
 DataTransferItemQt::DataTransferItemQt(PassRefPtr<Clipboard> owner,
                                        ScriptExecutionContext* context,
                                        DataSource source,
@@ -78,6 +78,17 @@ DataTransferItemQt::DataTransferItemQt(PassRefPtr<Clipboard> owner,
 {
 }
 
+DataTransferItemQt::DataTransferItemQt(PassRefPtr<Clipboard> owner,
+                                       ScriptExecutionContext* context,
+                                       DataSource source,
+                                       PassRefPtr<File> file)
+    : DataTransferItem(owner, DataTransferItem::kindFile, file.get() ? file->type() : "")
+    , m_context(context)
+    , m_source(source)
+    , m_file(file)
+{
+}
+
 void DataTransferItemQt::getAsString(PassRefPtr<StringCallback> callback)
 {
     if ((owner()->policy() != ClipboardReadable && owner()->policy() != ClipboardWritable)
@@ -108,7 +119,9 @@ void DataTransferItemQt::getAsString(PassRefPtr<StringCallback> callback)
 
 PassRefPtr<Blob> DataTransferItemQt::getAsFile()
 {
-    notImplemented();
+    if (kind() == kindFile && m_dataSource == InternalSource)
+        return m_file;
+
     return 0;
 }
 
index 025ba41..d1f58e5 100644 (file)
@@ -34,6 +34,7 @@
 namespace WebCore {
 
 class Clipboard;
+class File;
 class ScriptExecutionContext;
 
 class DataTransferItemQt : public DataTransferItem {
@@ -41,11 +42,6 @@ public:
     static PassRefPtr<DataTransferItemQt> createFromPasteboard(PassRefPtr<Clipboard> owner,
                                                                ScriptExecutionContext*,
                                                                const String&);
-    static PassRefPtr<DataTransferItemQt> create(PassRefPtr<Clipboard> owner,
-                                                 ScriptExecutionContext*,
-                                                 const String&,
-                                                 const String&);
-
     virtual void getAsString(PassRefPtr<StringCallback>);
     virtual PassRefPtr<Blob> getAsFile();
 
@@ -55,14 +51,21 @@ private:
         InternalSource
     };
 
+    friend class DataTransferItem;
+
     DataTransferItemQt(PassRefPtr<Clipboard> owner,
                        ScriptExecutionContext*,
                        DataSource,
                        const String&, const String&, const String&);
+    DataTransferItemQt(PassRefPtr<Clipboard> owner,
+                       ScriptExecutionContext*,
+                       DataSource,
+                       PassRefPtr<File>);
 
     ScriptExecutionContext* m_context;
     const DataSource m_dataSource;
     const String m_data;
+    RefPtr<File> m_file;
 };
 
 }