[chromium] Refactor ClipboardChromium and DataTransferItemList/DataTransferItem to...
authordcheng@chromium.org <dcheng@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Mar 2012 20:53:25 +0000 (20:53 +0000)
committerdcheng@chromium.org <dcheng@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Mar 2012 20:53:25 +0000 (20:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=76598

Reviewed by Tony Chang.

Source/WebCore:

We no longer store drag/clipboard data in named fields. We used to maintain the data store
list separately, which resulted in a lot of complicated code to try to make sure that
ChromiumDataObject and this list stayed in sync. We now just store what is essentially a
list MIME type/data pairs directly in ChromiumDataObject. This has the benefit of letting us
easily add write support during dragstart/copy operations using DataTransferItemList.

Tests: fast/events/clipboard-dataTransferItemList.html
       fast/events/drag-dataTransferItemList.html

* platform/chromium/ChromiumDataObject.cpp:
(WebCore::findItem):
(WebCore::ChromiumDataObject::createFromPasteboard):
(WebCore::ChromiumDataObject::create):
(WebCore::ChromiumDataObject::copy):
(WebCore::ChromiumDataObject::items):
(WebCore::ChromiumDataObject::clearData):
(WebCore::ChromiumDataObject::clearAll):
(WebCore::ChromiumDataObject::clearAllExceptFiles):
(WebCore::ChromiumDataObject::types):
(WebCore::ChromiumDataObject::getData):
(WebCore::ChromiumDataObject::setData):
(WebCore::ChromiumDataObject::urlAndTitle):
(WebCore::ChromiumDataObject::setURLAndTitle):
(WebCore::ChromiumDataObject::htmlAndBaseURL):
(WebCore::ChromiumDataObject::setHTMLAndBaseURL):
(WebCore::ChromiumDataObject::containsFilenames):
(WebCore):
(WebCore::ChromiumDataObject::filenames):
(WebCore::ChromiumDataObject::addFilename):
(WebCore::ChromiumDataObject::addSharedBuffer):
(WebCore::ChromiumDataObject::ChromiumDataObject):
* platform/chromium/ChromiumDataObject.h:
(WebCore):
(ChromiumDataObject):
* platform/chromium/ClipboardChromium.cpp:
(WebCore::normalizeType):
(WebCore::ClipboardChromium::ClipboardChromium):
(WebCore::ClipboardChromium::clearData):
(WebCore::ClipboardChromium::clearAllData):
(WebCore::ClipboardChromium::getData):
(WebCore::ClipboardChromium::setData):
(WebCore::ClipboardChromium::types):
(WebCore::ClipboardChromium::files):
(WebCore::writeImageToDataObject):
(WebCore::ClipboardChromium::declareAndWriteDragImage):
(WebCore::ClipboardChromium::writeURL):
(WebCore::ClipboardChromium::writeRange):
(WebCore::ClipboardChromium::writePlainText):
(WebCore::ClipboardChromium::hasData):
(WebCore::ClipboardChromium::items):
* platform/chromium/ClipboardChromium.h:
(WebCore):
(ClipboardChromium):
(WebCore::ClipboardChromium::frame):
* platform/chromium/ClipboardUtilitiesChromium.cpp:
(WebCore::convertURIListToURL):
(WebCore):
* platform/chromium/ClipboardUtilitiesChromium.h:
(WebCore):
* platform/chromium/DataTransferItemChromium.cpp:
(WebCore::DataTransferItemChromium::createFromString):
(WebCore::DataTransferItemChromium::createFromFile):
(WebCore::DataTransferItemChromium::createFromURL):
(WebCore::DataTransferItemChromium::createFromHTML):
(WebCore):
(WebCore::DataTransferItemChromium::createFromSharedBuffer):
(WebCore::DataTransferItemChromium::createFromPasteboard):
(WebCore::DataTransferItemChromium::DataTransferItemChromium):
(WebCore::DataTransferItemChromium::getAsString):
(WebCore::DataTransferItemChromium::getAsFile):
(WebCore::DataTransferItemChromium::internalGetAsString):
(WebCore::DataTransferItemChromium::isFilename):
* platform/chromium/DataTransferItemChromium.h:
(WebCore):
(DataTransferItemChromium):
(WebCore::DataTransferItemChromium::kind):
(WebCore::DataTransferItemChromium::type):
(WebCore::DataTransferItemChromium::sharedBuffer):
(WebCore::DataTransferItemChromium::title):
(WebCore::DataTransferItemChromium::baseURL):
* platform/chromium/DataTransferItemListChromium.cpp:
(WebCore::DataTransferItemListChromium::create):
(WebCore::DataTransferItemListChromium::createFromPasteboard):
(WebCore):
(WebCore::DataTransferItemListChromium::DataTransferItemListChromium):
(WebCore::DataTransferItemListChromium::length):
(WebCore::DataTransferItemListChromium::item):
(WebCore::DataTransferItemListChromium::deleteItem):
(WebCore::DataTransferItemListChromium::clear):
(WebCore::DataTransferItemListChromium::add):
(WebCore::DataTransferItemListChromium::internalAddStringItem):
(WebCore::DataTransferItemListChromium::internalAddFileItem):
* platform/chromium/DataTransferItemListChromium.h:
(WebCore):
(DataTransferItemListChromium):
* platform/chromium/DragDataChromium.cpp:
(WebCore::DragData::asURL):
(WebCore::DragData::asPlainText):
(WebCore::DragData::asFragment):

Source/WebKit/chromium:

* src/WebDragData.cpp:
(WebKit::WebDragData::items):
(WebKit::WebDragData::addItem):
(WebKit::WebDragData::assign):

LayoutTests:

* fast/events/clipboard-dataTransferItemList-expected.txt: Added.
* fast/events/clipboard-dataTransferItemList.html: Added.
* fast/events/drag-dataTransferItemList-expected.txt: Added.
* fast/events/drag-dataTransferItemList.html: Added.
* platform/gtk/Skipped:
* platform/mac/Skipped:
* platform/qt/Skipped:
* platform/win/Skipped:

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

19 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/mac/Skipped
LayoutTests/platform/qt/Skipped
LayoutTests/platform/win/Skipped
Source/WebCore/ChangeLog
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/ClipboardUtilitiesChromium.cpp
Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.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/chromium/DragDataChromium.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebDragData.cpp

index 7bae11f..e621cc1 100644 (file)
@@ -1,3 +1,19 @@
+2012-03-15  Daniel Cheng  <dcheng@chromium.org>
+
+        [chromium] Refactor ClipboardChromium and DataTransferItemList/DataTransferItem to support HTML spec
+        https://bugs.webkit.org/show_bug.cgi?id=76598
+
+        Reviewed by Tony Chang.
+
+        * fast/events/clipboard-dataTransferItemList-expected.txt: Added.
+        * fast/events/clipboard-dataTransferItemList.html: Added.
+        * fast/events/drag-dataTransferItemList-expected.txt: Added.
+        * fast/events/drag-dataTransferItemList.html: Added.
+        * platform/gtk/Skipped:
+        * platform/mac/Skipped:
+        * platform/qt/Skipped:
+        * platform/win/Skipped:
+
 2012-03-16  Xiaomei Ji  <xji@chromium.org>
 
         Skip move-by-word-visually-wrong-left-right.html added in r110965 in wk2 since SetEditingBehavior is not supported.
index b1e8e09..d2edc5c 100644 (file)
@@ -293,6 +293,8 @@ 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
+fast/events/clipboard-dataTransferItemList.html
+fast/events/drag-dataTransferItemList.html
 
 # Custom MIME type support in DataTransfer is not yet implemented.
 editing/pasteboard/clipboard-customData.html
index ebafd03..42fb8df 100644 (file)
@@ -352,6 +352,8 @@ 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
+fast/events/clipboard-dataTransferItemList.html
+fast/events/drag-dataTransferItemList.html
 
 # Replacement text for misspelling is not given from NSSpellChecker.
 # https://bugs.webkit.org/show_bug.cgi?id=77934
index ee0d486..d834adb 100644 (file)
@@ -448,6 +448,8 @@ editing/pasteboard/drag-and-drop-objectimage-contenteditable.html
 editing/pasteboard/data-transfer-items.html
 editing/pasteboard/data-transfer-items-drag-drop-file.html
 editing/pasteboard/data-transfer-items-drag-drop-string.html
+fast/events/clipboard-dataTransferItemList.html
+fast/events/drag-dataTransferItemList.html
 
 # PasteBoard::plainText() does not support file names.
 editing/pasteboard/drag-files-to-editable-element.html
index f75b6a9..84569e5 100644 (file)
@@ -1331,6 +1331,8 @@ 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
+fast/events/clipboard-dataTransferItemList.html
+fast/events/drag-dataTransferItemList.html
 
 # Custom MIME type support in DataTransfer not yet implemented.
 editing/pasteboard/clipboard-customData.html
index 1ccfc68..648bca5 100644 (file)
@@ -1,3 +1,110 @@
+2012-03-15  Daniel Cheng  <dcheng@chromium.org>
+
+        [chromium] Refactor ClipboardChromium and DataTransferItemList/DataTransferItem to support HTML spec
+        https://bugs.webkit.org/show_bug.cgi?id=76598
+
+        Reviewed by Tony Chang.
+
+        We no longer store drag/clipboard data in named fields. We used to maintain the data store
+        list separately, which resulted in a lot of complicated code to try to make sure that
+        ChromiumDataObject and this list stayed in sync. We now just store what is essentially a
+        list MIME type/data pairs directly in ChromiumDataObject. This has the benefit of letting us
+        easily add write support during dragstart/copy operations using DataTransferItemList.
+
+        Tests: fast/events/clipboard-dataTransferItemList.html
+               fast/events/drag-dataTransferItemList.html
+
+        * platform/chromium/ChromiumDataObject.cpp:
+        (WebCore::findItem):
+        (WebCore::ChromiumDataObject::createFromPasteboard):
+        (WebCore::ChromiumDataObject::create):
+        (WebCore::ChromiumDataObject::copy):
+        (WebCore::ChromiumDataObject::items):
+        (WebCore::ChromiumDataObject::clearData):
+        (WebCore::ChromiumDataObject::clearAll):
+        (WebCore::ChromiumDataObject::clearAllExceptFiles):
+        (WebCore::ChromiumDataObject::types):
+        (WebCore::ChromiumDataObject::getData):
+        (WebCore::ChromiumDataObject::setData):
+        (WebCore::ChromiumDataObject::urlAndTitle):
+        (WebCore::ChromiumDataObject::setURLAndTitle):
+        (WebCore::ChromiumDataObject::htmlAndBaseURL):
+        (WebCore::ChromiumDataObject::setHTMLAndBaseURL):
+        (WebCore::ChromiumDataObject::containsFilenames):
+        (WebCore):
+        (WebCore::ChromiumDataObject::filenames):
+        (WebCore::ChromiumDataObject::addFilename):
+        (WebCore::ChromiumDataObject::addSharedBuffer):
+        (WebCore::ChromiumDataObject::ChromiumDataObject):
+        * platform/chromium/ChromiumDataObject.h:
+        (WebCore):
+        (ChromiumDataObject):
+        * platform/chromium/ClipboardChromium.cpp:
+        (WebCore::normalizeType):
+        (WebCore::ClipboardChromium::ClipboardChromium):
+        (WebCore::ClipboardChromium::clearData):
+        (WebCore::ClipboardChromium::clearAllData):
+        (WebCore::ClipboardChromium::getData):
+        (WebCore::ClipboardChromium::setData):
+        (WebCore::ClipboardChromium::types):
+        (WebCore::ClipboardChromium::files):
+        (WebCore::writeImageToDataObject):
+        (WebCore::ClipboardChromium::declareAndWriteDragImage):
+        (WebCore::ClipboardChromium::writeURL):
+        (WebCore::ClipboardChromium::writeRange):
+        (WebCore::ClipboardChromium::writePlainText):
+        (WebCore::ClipboardChromium::hasData):
+        (WebCore::ClipboardChromium::items):
+        * platform/chromium/ClipboardChromium.h:
+        (WebCore):
+        (ClipboardChromium):
+        (WebCore::ClipboardChromium::frame):
+        * platform/chromium/ClipboardUtilitiesChromium.cpp:
+        (WebCore::convertURIListToURL):
+        (WebCore):
+        * platform/chromium/ClipboardUtilitiesChromium.h:
+        (WebCore):
+        * platform/chromium/DataTransferItemChromium.cpp:
+        (WebCore::DataTransferItemChromium::createFromString):
+        (WebCore::DataTransferItemChromium::createFromFile):
+        (WebCore::DataTransferItemChromium::createFromURL):
+        (WebCore::DataTransferItemChromium::createFromHTML):
+        (WebCore):
+        (WebCore::DataTransferItemChromium::createFromSharedBuffer):
+        (WebCore::DataTransferItemChromium::createFromPasteboard):
+        (WebCore::DataTransferItemChromium::DataTransferItemChromium):
+        (WebCore::DataTransferItemChromium::getAsString):
+        (WebCore::DataTransferItemChromium::getAsFile):
+        (WebCore::DataTransferItemChromium::internalGetAsString):
+        (WebCore::DataTransferItemChromium::isFilename):
+        * platform/chromium/DataTransferItemChromium.h:
+        (WebCore):
+        (DataTransferItemChromium):
+        (WebCore::DataTransferItemChromium::kind):
+        (WebCore::DataTransferItemChromium::type):
+        (WebCore::DataTransferItemChromium::sharedBuffer):
+        (WebCore::DataTransferItemChromium::title):
+        (WebCore::DataTransferItemChromium::baseURL):
+        * platform/chromium/DataTransferItemListChromium.cpp:
+        (WebCore::DataTransferItemListChromium::create):
+        (WebCore::DataTransferItemListChromium::createFromPasteboard):
+        (WebCore):
+        (WebCore::DataTransferItemListChromium::DataTransferItemListChromium):
+        (WebCore::DataTransferItemListChromium::length):
+        (WebCore::DataTransferItemListChromium::item):
+        (WebCore::DataTransferItemListChromium::deleteItem):
+        (WebCore::DataTransferItemListChromium::clear):
+        (WebCore::DataTransferItemListChromium::add):
+        (WebCore::DataTransferItemListChromium::internalAddStringItem):
+        (WebCore::DataTransferItemListChromium::internalAddFileItem):
+        * platform/chromium/DataTransferItemListChromium.h:
+        (WebCore):
+        (DataTransferItemListChromium):
+        * platform/chromium/DragDataChromium.cpp:
+        (WebCore::DragData::asURL):
+        (WebCore::DragData::asPlainText):
+        (WebCore::DragData::asFragment):
+
 2012-03-16  Matt Lilek  <mrl@apple.com>
 
         Don't install libWebCoreTestSupport on OS X production builds
index c1b7aa2..679f42d 100644 (file)
 
 #include "ClipboardMimeTypes.h"
 #include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItem.h"
 #include "DataTransferItemListChromium.h"
-#include "Pasteboard.h"
-#include "PlatformSupport.h"
+#include "ExceptionCodePlaceholder.h"
 
 namespace WebCore {
 
-// Per RFC 2483, the line separator for "text/..." MIME types is CR-LF.
-static char const* const textMIMETypeLineSeparator = "\r\n";
-
-void ChromiumDataObject::clearData(const String& type)
+static PassRefPtr<DataTransferItemChromium> findItem(PassRefPtr<DataTransferItemListChromium> itemList, const String& type)
 {
-    if (type == mimeTypeTextPlain) {
-        m_plainText = "";
-        return;
-    }
-
-    if (type == mimeTypeURL || type == mimeTypeTextURIList) {
-        m_uriList = "";
-        m_url = KURL();
-        m_urlTitle = "";
-        return;
-    }
-
-    if (type == mimeTypeTextHTML) {
-        m_textHtml = "";
-        m_htmlBaseUrl = KURL();
-        return;
-    }
-
-    if (type == mimeTypeDownloadURL) {
-        m_downloadMetadata = "";
-        return;
+    for (size_t i = 0; i < itemList->length(); ++i) {
+        if (itemList->item(i)->kind() == DataTransferItem::kindString && itemList->item(i)->type() == type)
+            return itemList->item(i);
     }
+    return 0;
 }
 
-void ChromiumDataObject::clearAll()
+PassRefPtr<ChromiumDataObject> ChromiumDataObject::createFromPasteboard()
 {
-    clearAllExceptFiles();
-    m_filenames.clear();
+    return adoptRef(new ChromiumDataObject(DataTransferItemListChromium::createFromPasteboard()));
 }
 
-void ChromiumDataObject::clearAllExceptFiles()
+PassRefPtr<ChromiumDataObject> ChromiumDataObject::create()
 {
-    m_urlTitle = "";
-    m_url = KURL();
-    m_uriList = "";
-    m_downloadMetadata = "";
-    m_fileExtension = "";
-    m_plainText = "";
-    m_textHtml = "";
-    m_htmlBaseUrl = KURL();
-    m_fileContentFilename = "";
-    if (m_fileContent)
-        m_fileContent->clear();
+    return adoptRef(new ChromiumDataObject(DataTransferItemListChromium::create()));
 }
 
-bool ChromiumDataObject::hasData() const
+PassRefPtr<ChromiumDataObject> ChromiumDataObject::copy() const
 {
-    return !m_url.isEmpty()
-        || !m_uriList.isEmpty()
-        || !m_downloadMetadata.isEmpty()
-        || !m_fileExtension.isEmpty()
-        || !m_filenames.isEmpty()
-        || !m_plainText.isEmpty()
-        || !m_textHtml.isEmpty()
-        || m_fileContent;
+    return adoptRef(new ChromiumDataObject(*this));
 }
 
-HashSet<String> ChromiumDataObject::types() const
+PassRefPtr<DataTransferItemListChromium> ChromiumDataObject::items() const
 {
-    if (m_storageMode == Pasteboard) {
-        bool ignoredContainsFilenames;
-        return PlatformSupport::clipboardReadAvailableTypes(currentPasteboardBuffer(),
-                                                            &ignoredContainsFilenames);
-    }
-
-    HashSet<String> results;
-
-    if (!m_plainText.isEmpty()) {
-        results.add(mimeTypeText);
-        results.add(mimeTypeTextPlain);
-    }
-
-    if (!m_uriList.isEmpty())
-        results.add(mimeTypeTextURIList);
-
-    if (!m_textHtml.isEmpty())
-        results.add(mimeTypeTextHTML);
-
-    if (!m_downloadMetadata.isEmpty())
-        results.add(mimeTypeDownloadURL);
-
-    for (HashMap<String, String>::const_iterator::Keys it = m_customData.begin().keys();
-         it != m_customData.end().keys(); ++it) {
-        results.add(*it);
-    }
-
-    return results;
+    return m_itemList;
 }
 
-String ChromiumDataObject::getData(const String& type, bool& success) const
+void ChromiumDataObject::clearData(const String& type)
 {
-    if (type == mimeTypeTextPlain) {
-        if (m_storageMode == Pasteboard) {
-            String text = PlatformSupport::clipboardReadPlainText(currentPasteboardBuffer());
-            success = !text.isEmpty();
-            return text;
+    for (size_t i = 0; i < m_itemList->length(); ++i) {
+        if (m_itemList->item(i)->kind() == DataTransferItem::kindString && m_itemList->item(i)->type() == type) {
+            // Per the spec, type must be unique among all items of kind 'string'.
+            m_itemList->deleteItem(i);
+            return;
         }
-        success = !m_plainText.isEmpty();
-        return m_plainText;
-    }
-
-    if (type == mimeTypeURL) {
-        success = !m_uriList.isEmpty();
-        return m_url.string();
     }
+}
 
-    if (type == mimeTypeTextURIList) {
-        success = !m_uriList.isEmpty();
-        return m_uriList;
-    }
+void ChromiumDataObject::clearAll()
+{
+    m_itemList->clear();
+}
 
-    if (type == mimeTypeTextHTML) {
-        if (m_storageMode == Pasteboard) {
-            String htmlText;
-            KURL sourceURL;
-            unsigned ignored;
-            PlatformSupport::clipboardReadHTML(currentPasteboardBuffer(), &htmlText, &sourceURL, &ignored, &ignored);
-            success = !htmlText.isEmpty();
-            return htmlText;
+void ChromiumDataObject::clearAllExceptFiles()
+{
+    for (size_t i = 0; i < m_itemList->length(); ) {
+        if (m_itemList->item(i)->kind() != DataTransferItem::kindFile) {
+            m_itemList->deleteItem(i);
+            continue;
         }
-        success = !m_textHtml.isEmpty();
-        return m_textHtml;
-    }
-
-    if (type == mimeTypeDownloadURL) {
-        success = !m_downloadMetadata.isEmpty();
-        return m_downloadMetadata;
+        ++i;
     }
+}
 
-    if (m_storageMode == Pasteboard) {
-        String data = PlatformSupport::clipboardReadCustomData(currentPasteboardBuffer(), type);
-        success = !data.isEmpty();
-        return data;
-    }
+HashSet<String> ChromiumDataObject::types() const
+{
+    HashSet<String> results;
+    bool containsFiles = false;
+    for (size_t i = 0; i < m_itemList->length(); ++i) {
+        if (m_itemList->item(i)->kind() == DataTransferItem::kindString)
+            results.add(m_itemList->item(i)->type());
+        else if (m_itemList->item(i)->kind() == DataTransferItem::kindFile)
+            containsFiles = true;
+        else
+            ASSERT_NOT_REACHED();
+    }
+    if (containsFiles)
+        results.add(mimeTypeFiles);
+    return results;
+}
 
-    HashMap<String, String>::const_iterator it = m_customData.find(type);
-    if (it != m_customData.end()) {
-        success = true;
-        return it->second;
+String ChromiumDataObject::getData(const String& type) const
+{
+    for (size_t i = 0; i < m_itemList->length(); ++i)  {
+        if (m_itemList->item(i)->kind() == DataTransferItem::kindString && m_itemList->item(i)->type() == type)
+            return m_itemList->item(i)->internalGetAsString();
     }
-
-    success = false;
     return String();
 }
 
 bool ChromiumDataObject::setData(const String& type, const String& data)
 {
-    if (type == mimeTypeTextPlain) {
-        m_plainText = data;
-        return true;
-    }
-
-    if (type == mimeTypeURL || type == mimeTypeTextURIList) {
-        m_url = KURL();
-        Vector<String> uriList;
-        // Line separator is \r\n per RFC 2483 - however, for compatibility
-        // reasons we also allow just \n here.
-        data.split('\n', uriList);
-        // Process the input and copy the first valid URL into the url member.
-        // In case no URLs can be found, subsequent calls to getData("URL")
-        // will get an empty string. This is in line with the HTML5 spec (see
-        // "The DragEvent and DataTransfer interfaces").
-        for (size_t i = 0; i < uriList.size(); ++i) {
-            String& line = uriList[i];
-            line = line.stripWhiteSpace();
-            if (line.isEmpty()) {
-                continue;
-            }
-            if (line[0] == '#')
-                continue;
-            KURL url = KURL(ParsedURLString, line);
-            if (url.isValid()) {
-                m_url = url;
-                break;
-            }
-        }
-        m_uriList = data;
-        return true;
-    }
+    clearData(type);
+    m_itemList->add(data, type, ASSERT_NO_EXCEPTION);
+    return true;
+}
 
-    if (type == mimeTypeTextHTML) {
-        m_textHtml = data;
-        m_htmlBaseUrl = KURL();
-        return true;
-    }
+void ChromiumDataObject::urlAndTitle(String& url, String* title) const
+{
+    RefPtr<DataTransferItemChromium> item = findItem(m_itemList, mimeTypeTextURIList);
+    if (!item)
+        return;
+    url = convertURIListToURL(item->internalGetAsString());
+    if (title)
+        *title = item->title();
+}
 
-    if (type == mimeTypeDownloadURL) {
-        m_downloadMetadata = data;
-        return true;
-    }
+void ChromiumDataObject::setURLAndTitle(const String& url, const String& title)
+{
+    clearData(mimeTypeTextURIList);
+    m_itemList->internalAddStringItem(DataTransferItemChromium::createFromURL(url, title));
+}
 
-    if (type.isEmpty())
-        return false;
+void ChromiumDataObject::htmlAndBaseURL(String& html, KURL& baseURL) const
+{
+    RefPtr<DataTransferItemChromium> item = findItem(m_itemList, mimeTypeTextHTML);
+    if (!item)
+        return;
+    html = item->internalGetAsString();
+    baseURL = item->baseURL();
+}
 
-    m_customData.set(type, data);
-    return true;
+void ChromiumDataObject::setHTMLAndBaseURL(const String& html, const KURL& baseURL)
+{
+    clearData(mimeTypeTextHTML);
+    m_itemList->internalAddStringItem(DataTransferItemChromium::createFromHTML(html, baseURL));
 }
 
 bool ChromiumDataObject::containsFilenames() const
 {
-    bool containsFilenames;
-    if (m_storageMode == Pasteboard) {
-        HashSet<String> ignoredResults =
-            PlatformSupport::clipboardReadAvailableTypes(currentPasteboardBuffer(),
-                                                         &containsFilenames);
-    } else
-        containsFilenames = !m_filenames.isEmpty();
-    return containsFilenames;
+    for (size_t i = 0; i < m_itemList->length(); ++i)
+        if (m_itemList->item(i)->isFilename())
+            return true;
+    return false;
+}
+
+Vector<String> ChromiumDataObject::filenames() const
+{
+    Vector<String> results;
+    for (size_t i = 0; i < m_itemList->length(); ++i)
+        if (m_itemList->item(i)->isFilename())
+            results.append(static_cast<File*>(m_itemList->item(i)->getAsFile().get())->path());
+    return results;
+}
+
+void ChromiumDataObject::addFilename(const String& filename)
+{
+    m_itemList->internalAddFileItem(DataTransferItemChromium::createFromFile(File::create(filename)));
+}
+
+void ChromiumDataObject::addSharedBuffer(const String& name, PassRefPtr<SharedBuffer> buffer)
+{
+    m_itemList->internalAddFileItem(DataTransferItemChromium::createFromSharedBuffer(name, buffer));
 }
 
-ChromiumDataObject::ChromiumDataObject(StorageMode storageMode)
-    : m_storageMode(storageMode)
+ChromiumDataObject::ChromiumDataObject(PassRefPtr<DataTransferItemListChromium> itemList)
+    : m_itemList(itemList)
 {
 }
 
 ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other)
     : RefCounted<ChromiumDataObject>()
-    , m_storageMode(other.m_storageMode)
-    , m_urlTitle(other.m_urlTitle)
-    , m_downloadMetadata(other.m_downloadMetadata)
-    , m_fileExtension(other.m_fileExtension)
-    , m_filenames(other.m_filenames)
-    , m_plainText(other.m_plainText)
-    , m_textHtml(other.m_textHtml)
-    , m_htmlBaseUrl(other.m_htmlBaseUrl)
-    , m_fileContentFilename(other.m_fileContentFilename)
-    , m_url(other.m_url)
-    , m_uriList(other.m_uriList)
+    , m_itemList(other.m_itemList)
 {
-    if (other.m_fileContent.get())
-        m_fileContent = other.m_fileContent->copy();
 }
 
 } // namespace WebCore
index 7e675bf..5a1c42e 100644 (file)
 #ifndef ChromiumDataObject_h
 #define ChromiumDataObject_h
 
-#include "KURL.h"
+#include "DataTransferItemListChromium.h"
 #include "PlatformString.h"
-#include "SharedBuffer.h"
-#include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
 
+class KURL;
+class SharedBuffer;
+
 // A data object for holding data that would be in a clipboard or moved
 // during a drag-n-drop operation.  This is the data that WebCore is aware
 // of and is not specific to a platform.
 class ChromiumDataObject : public RefCounted<ChromiumDataObject> {
 public:
-    enum StorageMode {
-        Buffered,
-        Pasteboard,
-    };
-
-    static PassRefPtr<ChromiumDataObject> createFromPasteboard()
-    {
-        return adoptRef(new ChromiumDataObject(Pasteboard));
-    }
+    static PassRefPtr<ChromiumDataObject> createFromPasteboard();
+    static PassRefPtr<ChromiumDataObject> create();
 
-    static PassRefPtr<ChromiumDataObject> create()
-    {
-        return adoptRef(new ChromiumDataObject(Buffered));
-    }
+    PassRefPtr<ChromiumDataObject> copy() const;
 
-    PassRefPtr<ChromiumDataObject> copy() const
-    {
-        return adoptRef(new ChromiumDataObject(*this));
-    }
-
-    StorageMode storageMode() const { return m_storageMode; }
+    PassRefPtr<DataTransferItemListChromium> items() const;
 
     void clearData(const String& type);
     void clearAll();
     void clearAllExceptFiles();
 
-    bool hasData() const;
-
     HashSet<String> types() const;
-    String getData(const String& type, bool& success) const;
+    String getData(const String& type) const;
     bool setData(const String& type, const String& data);
 
-    // Special handlers for URL/HTML metadata.
-    String urlTitle() const { return m_urlTitle; }
-    void setUrlTitle(const String& urlTitle) { m_urlTitle = urlTitle; }
-    KURL htmlBaseUrl() const { return m_htmlBaseUrl; }
-    void setHtmlBaseUrl(const KURL& url) { m_htmlBaseUrl = url; }
+    void urlAndTitle(String& url, String* title = 0) const;
+    void setURLAndTitle(const String& url, const String& title);
+    void htmlAndBaseURL(String& html, KURL& baseURL) const;
+    void setHTMLAndBaseURL(const String& html, const KURL& baseURL);
 
-    // Used to handle files being dragged in and out.
+    // Used for dragging in files from the desktop.
     bool containsFilenames() const;
-    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); }
+    Vector<String> filenames() const;
+    void addFilename(const String&);
 
     // Used to handle files (images) being dragged out.
-    String fileExtension() const { return m_fileExtension; }
-    void setFileExtension(const String& fileExtension) { m_fileExtension = fileExtension; }
-    String fileContentFilename() const { return m_fileContentFilename; }
-    void setFileContentFilename(const String& fileContentFilename) { m_fileContentFilename = fileContentFilename; }
-    PassRefPtr<SharedBuffer> fileContent() const { return m_fileContent; }
-    void setFileContent(PassRefPtr<SharedBuffer> fileContent) { m_fileContent = fileContent; }
-    const HashMap<String, String>& customData() const { return m_customData; }
-    HashMap<String, String>& customData() { return m_customData; }
+    void addSharedBuffer(const String& name, PassRefPtr<SharedBuffer>);
 
 private:
-    explicit ChromiumDataObject(StorageMode);
+    explicit ChromiumDataObject(PassRefPtr<DataTransferItemListChromium>);
     explicit ChromiumDataObject(const ChromiumDataObject&);
 
-    StorageMode m_storageMode;
-
-    String m_urlTitle;
-
-    String m_downloadMetadata;
-
-    String m_fileExtension;
-    Vector<String> m_filenames;
-
-    String m_plainText;
-
-    String m_textHtml;
-    KURL m_htmlBaseUrl;
-
-    String m_fileContentFilename;
-    RefPtr<SharedBuffer> m_fileContent;
-
-    HashMap<String, String> m_customData;
-
-    // These two are linked. Setting m_url will set m_uriList to the same
-    // string value; setting m_uriList will cause its contents to be parsed
-    // according to RFC 2483 and the first URL found will be set in m_url.
-    KURL m_url;
-    String m_uriList;
+    RefPtr<DataTransferItemListChromium> m_itemList;
 };
 
 } // namespace WebCore
index e238b2d..3121ea8 100644 (file)
@@ -31,7 +31,9 @@
 #include "ChromiumDataObject.h"
 #include "ClipboardMimeTypes.h"
 #include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItem.h"
 #include "DataTransferItemChromium.h"
+#include "DataTransferItemList.h"
 #include "DataTransferItemListChromium.h"
 #include "Document.h"
 #include "DragData.h"
@@ -81,7 +83,7 @@ private:
 class DataTransferItemPolicyWrapper : public DataTransferItem {
 public:
     static PassRefPtr<DataTransferItemPolicyWrapper> create(
-        PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItem>);
+        PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItemChromium>);
 
     virtual String kind() const;
     virtual String type() const;
@@ -90,10 +92,10 @@ public:
     virtual PassRefPtr<Blob> getAsFile() const;
 
 private:
-    DataTransferItemPolicyWrapper(PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItem>);
+    DataTransferItemPolicyWrapper(PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItemChromium>);
 
     RefPtr<ClipboardChromium> m_clipboard;
-    RefPtr<DataTransferItem> m_item;
+    RefPtr<DataTransferItemChromium> m_item;
 };
 
 PassRefPtr<DataTransferItemListPolicyWrapper> DataTransferItemListPolicyWrapper::create(
@@ -113,7 +115,7 @@ PassRefPtr<DataTransferItem> DataTransferItemListPolicyWrapper::item(unsigned lo
 {
     if (m_clipboard->policy() == ClipboardNumb)
         return 0;
-    RefPtr<DataTransferItem> item = m_list->item(index);
+    RefPtr<DataTransferItemChromium> item = m_list->item(index);
     if (!item)
         return 0;
     return DataTransferItemPolicyWrapper::create(m_clipboard, item);
@@ -125,8 +127,7 @@ void DataTransferItemListPolicyWrapper::deleteItem(unsigned long index, Exceptio
         ec = INVALID_STATE_ERR;
         return;
     }
-    // FIXME: We handle all the exceptions here, so we don't need to propogate ec.
-    m_list->deleteItem(index, ec);
+    m_list->deleteItem(index);
 }
 
 void DataTransferItemListPolicyWrapper::clear()
@@ -147,7 +148,7 @@ void DataTransferItemListPolicyWrapper::add(PassRefPtr<File> file)
 {
     if (m_clipboard->policy() != ClipboardWritable)
         return;
-    m_list->add(file);
+    m_list->add(file, m_clipboard->frame()->document()->scriptExecutionContext());
 }
 
 DataTransferItemListPolicyWrapper::DataTransferItemListPolicyWrapper(
@@ -158,7 +159,7 @@ DataTransferItemListPolicyWrapper::DataTransferItemListPolicyWrapper(
 }
 
 PassRefPtr<DataTransferItemPolicyWrapper> DataTransferItemPolicyWrapper::create(
-    PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItem> item)
+    PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItemChromium> item)
 {
     return adoptRef(new DataTransferItemPolicyWrapper(clipboard, item));
 }
@@ -182,7 +183,7 @@ void DataTransferItemPolicyWrapper::getAsString(PassRefPtr<StringCallback> callb
     if (m_clipboard->policy() != ClipboardReadable && m_clipboard->policy() != ClipboardWritable)
         return;
 
-    m_item->getAsString(callback);
+    m_item->getAsString(callback, m_clipboard->frame()->document()->scriptExecutionContext());
 }
 
 PassRefPtr<Blob> DataTransferItemPolicyWrapper::getAsFile() const
@@ -194,7 +195,7 @@ PassRefPtr<Blob> DataTransferItemPolicyWrapper::getAsFile() const
 }
 
 DataTransferItemPolicyWrapper::DataTransferItemPolicyWrapper(
-    PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItem> item)
+    PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItemChromium> item)
     : m_clipboard(clipboard)
     , m_item(item)
 {
@@ -207,11 +208,16 @@ using namespace HTMLNames;
 // We provide the IE clipboard types (URL and Text), and the clipboard types specified in the WHATWG Web Applications 1.0 draft
 // see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
 
-static String normalizeType(const String& type)
+static String normalizeType(const String& type, bool* convertToURL = 0)
 {
     String cleanType = type.stripWhiteSpace().lower();
     if (cleanType == mimeTypeText || cleanType.startsWith(mimeTypeTextPlainEtc))
         return mimeTypeTextPlain;
+    if (cleanType == mimeTypeURL) {
+        if (convertToURL)
+          *convertToURL = true;
+        return mimeTypeTextURIList;
+    }
     return cleanType;
 }
 
@@ -227,8 +233,6 @@ ClipboardChromium::ClipboardChromium(ClipboardType clipboardType,
     : Clipboard(policy, clipboardType)
     , m_dataObject(dataObject)
     , m_frame(frame)
-    , m_originalSequenceNumber(PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()))
-    , m_dragStorageUpdated(true)
 {
 }
 
@@ -244,10 +248,9 @@ PassRefPtr<ClipboardChromium> ClipboardChromium::create(ClipboardType clipboardT
 
 void ClipboardChromium::clearData(const String& type)
 {
-    if (policy() != ClipboardWritable || !m_dataObject)
+    if (policy() != ClipboardWritable)
         return;
 
-    m_dragStorageUpdated = true;
     m_dataObject->clearData(normalizeType(type));
 
     ASSERT_NOT_REACHED();
@@ -258,20 +261,40 @@ void ClipboardChromium::clearAllData()
     if (policy() != ClipboardWritable)
         return;
 
-    m_dragStorageUpdated = true;
     m_dataObject->clearAll();
 }
 
 String ClipboardChromium::getData(const String& type) const
 {
-    bool ignoredSuccess = false;
-    if (policy() != ClipboardReadable || !m_dataObject)
+    if (policy() != ClipboardReadable)
         return String();
 
-    if (isForCopyAndPaste() && platformClipboardChanged())
-        return String();
+    bool convertToURL = false;
+    String data = m_dataObject->getData(normalizeType(type, &convertToURL));
+    if (!convertToURL)
+        return data;
+    return convertURIListToURL(data);
+
+    Vector<String> uriList;
+    // Line separator is \r\n per RFC 2483 - howver, for compatiblity
+    // reasons we also allow just \n here.
+    data.split('\n', uriList);
+    // Process the input and return the first valid RUL. In case no URLs can
+    // be found, return an empty string. This is in line with the HTML5
+    // spec (see "The DragEvent and DataTransfer interfaces").
+    for (size_t i = 0; i < uriList.size(); ++i) {
+        String& line = uriList[i];
+        line = line.stripWhiteSpace();
+        if (line.isEmpty())
+            continue;
+        if (line[0] == '#')
+            continue;
+        KURL url = KURL(ParsedURLString, line);
+        if (url.isValid())
+            return url;
+    }
 
-    return m_dataObject->getData(normalizeType(type), ignoredSuccess);
+    return String();
 }
 
 bool ClipboardChromium::setData(const String& type, const String& data)
@@ -279,47 +302,34 @@ bool ClipboardChromium::setData(const String& type, const String& data)
     if (policy() != ClipboardWritable)
         return false;
 
-    m_dragStorageUpdated = true;
     return m_dataObject->setData(normalizeType(type), data);
 }
 
-bool ClipboardChromium::platformClipboardChanged() const
-{
-    return PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()) != m_originalSequenceNumber;
-}
-
 // extensions beyond IE's API
 HashSet<String> ClipboardChromium::types() const
 {
-    HashSet<String> results;
     if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
-        return results;
-
-    if (!m_dataObject)
-        return results;
+        return HashSet<String>();
 
-    results = m_dataObject->types();
-
-    if (m_dataObject->containsFilenames())
-        results.add(mimeTypeFiles);
-
-    return results;
+    return m_dataObject->types();
 }
 
 PassRefPtr<FileList> ClipboardChromium::files() const
 {
+    RefPtr<FileList> files = FileList::create();
     if (policy() != ClipboardReadable)
-        return FileList::create();
-
-    if (!m_dataObject)
-        return FileList::create();
-
-    const Vector<String>& filenames = m_dataObject->filenames();
-    RefPtr<FileList> fileList = FileList::create();
-    for (size_t i = 0; i < filenames.size(); ++i)
-        fileList->append(File::create(filenames.at(i)));
+        return files.release();
+
+    RefPtr<DataTransferItemListChromium> list = m_dataObject->items();
+    for (size_t i = 0; i < list->length(); ++i) {
+        if (list->item(i)->kind() == DataTransferItem::kindFile) {
+            RefPtr<Blob> blob = list->item(i)->getAsFile();
+            if (blob && blob->isFile())
+                files->append(static_cast<File*>(blob.get()));
+        }
+    }
 
-    return fileList.release();
+    return files.release();
 }
 
 void ClipboardChromium::setDragImage(CachedImage* image, Node* node, const IntPoint& loc)
@@ -389,8 +399,6 @@ static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* elem
     if (!imageBuffer || !imageBuffer->size())
         return;
 
-    dataObject->setFileContent(imageBuffer);
-
     // Determine the filename for the file contents of the image.
     String filename = cachedImage->response().suggestedFilename();
     if (filename.isEmpty())
@@ -410,8 +418,7 @@ static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* elem
 
     ClipboardChromium::validateFilename(filename, extension);
 
-    dataObject->setFileContentFilename(filename + extension);
-    dataObject->setFileExtension(extension);
+    dataObject->addSharedBuffer(filename + extension, imageBuffer);
 }
 
 void ClipboardChromium::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
@@ -419,9 +426,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);
+    m_dataObject->setURLAndTitle(url, title);
 
     // Write the bytes in the image to the file format.
     writeImageToDataObject(m_dataObject.get(), element, url);
@@ -436,16 +441,13 @@ void ClipboardChromium::writeURL(const KURL& url, const String& title, Frame*)
         return;
     ASSERT(!url.isEmpty());
 
-    m_dragStorageUpdated = true;
-    m_dataObject->setData(mimeTypeURL, url);
-    m_dataObject->setUrlTitle(title);
+    m_dataObject->setURLAndTitle(url, title);
 
     // The URL can also be used as plain text.
     m_dataObject->setData(mimeTypeTextPlain, url.string());
 
     // The URL can also be used as an HTML fragment.
-    m_dataObject->setData(mimeTypeTextHTML, urlToMarkup(url, title));
-    m_dataObject->setHtmlBaseUrl(url);
+    m_dataObject->setHTMLAndBaseURL(urlToMarkup(url, title), url);
 }
 
 void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
@@ -454,9 +456,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());
+    m_dataObject->setHTMLAndBaseURL(createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs), frame->document()->url());
 
     String str = frame->editor()->selectedText();
 #if OS(WINDOWS)
@@ -477,76 +477,24 @@ void ClipboardChromium::writePlainText(const String& text)
 #endif
     replaceNBSPWithSpace(str);
 
-    m_dragStorageUpdated = true;
     m_dataObject->setData(mimeTypeTextPlain, str);
 }
 
 bool ClipboardChromium::hasData()
 {
     ASSERT(isForDragAndDrop());
-    if (!m_dataObject)
-        return false;
 
-    return m_dataObject->hasData();
+    return m_dataObject->items()->length() > 0;
 }
 
 #if ENABLE(DATA_TRANSFER_ITEMS)
 PassRefPtr<DataTransferItemList> ClipboardChromium::items()
 {
-    if (!m_dataObject)
-        // Return an unassociated empty list.
-        return DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
-
-    if (!m_itemList)
-        m_itemList = DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
-
     // FIXME: According to the spec, we are supposed to return the same collection of items each
     // time. We now return a wrapper that always wraps the *same* set of items, so JS shouldn't be
     // able to tell, but we probably still want to fix this.
-    return DataTransferItemListPolicyWrapper::create(this, 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.append(DataTransferItemChromium::createFromPasteboard(this, scriptExecutionContext, *it));
-        return;
-    }
-
-    bool success = false;
-    String plainText = m_dataObject->getData(mimeTypeTextPlain, success);
-    if (success)
-        items.append(DataTransferItemChromium::create(this, scriptExecutionContext, plainText, mimeTypeTextPlain));
-
-    success = false;
-    String htmlText = m_dataObject->getData(mimeTypeTextHTML, success);
-    if (success)
-        items.append(DataTransferItemChromium::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(DataTransferItemChromium::create(this, scriptExecutionContext, File::create(*it)));
-    }
-    m_dragStorageUpdated = false;
+    return DataTransferItemListPolicyWrapper::create(this, m_dataObject->items());
 }
-
-bool ClipboardChromium::storageHasUpdated() const
-{
-    return (isForCopyAndPaste() && platformClipboardChanged()) || (isForDragAndDrop() && m_dragStorageUpdated);
-}
-
 #endif
 
 } // namespace WebCore
index 3777ad5..b1571cb 100644 (file)
@@ -37,9 +37,6 @@
 namespace WebCore {
 
     class CachedImage;
-    class ChromiumDataObject;
-    class DataTransferItem;
-    class DataTransferItemListChromium;
     class Frame;
     class IntPoint;
 
@@ -84,11 +81,8 @@ 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
+        Frame* frame() const { return m_frame; }
 
     private:
         ClipboardChromium(ClipboardType, PassRefPtr<ChromiumDataObject>, ClipboardAccessPolicy, Frame*);
@@ -97,13 +91,6 @@ namespace WebCore {
         void setDragImage(CachedImage*, Node*, const IntPoint&);
         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 47572c5..62cf99c 100644 (file)
@@ -60,4 +60,26 @@ void replaceNBSPWithSpace(String& str)
     str.replace(NonBreakingSpaceCharacter, SpaceCharacter);
 }
 
+String convertURIListToURL(const String& uriList)
+{
+    Vector<String> items;
+    // Line separator is \r\n per RFC 2483 - however, for compatibility
+    // reasons we allow just \n here.
+    uriList.split('\n', items);
+    // Process the input and return the first valid URL. In case no URLs can
+    // be found, return an empty string. This is in line with the HTML5 spec.
+    for (size_t i = 0; i < items.size(); ++i) {
+        String& line = items[i];
+        line = line.stripWhiteSpace();
+        if (line.isEmpty())
+            continue;
+        if (line[0] == '#')
+            continue;
+        KURL url = KURL(ParsedURLString, line);
+        if (url.isValid())
+            return url;
+    }
+    return String();
+}
+
 } // namespace WebCore
index 7ae5004..49a4838 100644 (file)
@@ -44,6 +44,7 @@ PasteboardPrivate::ClipboardBuffer currentPasteboardBuffer();
 void replaceNewlinesWithWindowsStyleNewlines(String&);
 #endif
 void replaceNBSPWithSpace(String&);
+String convertURIListToURL(const String& uriList);
 
 } // namespace WebCore
 
index 696ee65..4d49df9 100644 (file)
@@ -38,7 +38,7 @@
 #include "ClipboardChromium.h"
 #include "ClipboardMimeTypes.h"
 #include "ClipboardUtilitiesChromium.h"
-#include "DataTransferItemListChromium.h"
+#include "DataTransferItem.h"
 #include "File.h"
 #include "PlatformSupport.h"
 #include "SharedBuffer.h"
 
 namespace WebCore {
 
-PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, const String& type)
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromString(const String& type, const String& data)
 {
-    if (type == mimeTypeTextPlain || type == mimeTypeTextHTML)
-        return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindString, type, String()));
-    return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindFile, type, ""));
+    RefPtr<DataTransferItemChromium> item = adoptRef(new DataTransferItemChromium(DataTransferItem::kindString, type));
+    item->m_data = data;
+    return item.release();
 }
 
-PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr<Clipboard> owner,
-                                                                      ScriptExecutionContext* context,
-                                                                      const String& data,
-                                                                      const String& type)
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromFile(PassRefPtr<File> file)
 {
-    return adoptRef(new DataTransferItemChromium(owner, context, DataTransferItemChromium::InternalSource, kindString, type, data));
+    RefPtr<DataTransferItemChromium> item = adoptRef(new DataTransferItemChromium(DataTransferItem::kindFile, file->type()));
+    item->m_file = file;
+    return item.release();
 }
 
-PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr<Clipboard> owner,
-                                                                      ScriptExecutionContext* context,
-                                                                      PassRefPtr<File> file)
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromURL(const String& url, const String& title)
 {
-    return adoptRef(new DataTransferItemChromium(owner, context, DataTransferItemChromium::InternalSource, file));
+    RefPtr<DataTransferItemChromium> item = adoptRef(new DataTransferItemChromium(DataTransferItem::kindString, mimeTypeTextURIList));
+    item->m_data = url;
+    item->m_title = title;
+    return item.release();
 }
 
-DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, DataSource source, const String& kind, const String& type, const String& data)
-    : m_context(context)
-    , m_owner(owner)
-    , m_kind(kind)
-    , m_type(type)
-    , m_source(source)
-    , m_data(data)
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromHTML(const String& html, const KURL& baseURL)
 {
+    RefPtr<DataTransferItemChromium> item = adoptRef(new DataTransferItemChromium(DataTransferItem::kindString, mimeTypeTextHTML));
+    item->m_data = html;
+    item->m_baseURL = baseURL;
+    return item.release();
 }
 
-DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, DataSource source, PassRefPtr<File> file)
-    : m_context(context)
-    , m_owner(owner)
-    , m_kind(kindFile)
-    , m_type(file.get() ? file->type() : String())
-    , m_source(source)
-    , m_file(file)
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromSharedBuffer(const String& name, PassRefPtr<SharedBuffer> buffer)
 {
+    RefPtr<DataTransferItemChromium> item = adoptRef(new DataTransferItemChromium(DataTransferItem::kindFile, String()));
+    item->m_sharedBuffer = buffer;
+    item->m_title = name;
+    return item.release();
 }
 
-void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback) const
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromPasteboard(const String& type, uint64_t sequenceNumber)
 {
-    if (kind() != kindString)
-        return;
-
-    if (clipboardChromium()->storageHasUpdated())
-        return;
+    if (type == mimeTypeImagePng)
+        return adoptRef(new DataTransferItemChromium(DataTransferItem::kindFile, type, sequenceNumber));
+    return adoptRef(new DataTransferItemChromium(DataTransferItem::kindString, type, sequenceNumber));
+}
 
-    if (m_source == InternalSource) {
-        callback->scheduleCallback(m_context, m_data);
-        return;
-    }
+DataTransferItemChromium::DataTransferItemChromium(const String& kind, const String& type)
+    : m_source(InternalSource)
+    , m_kind(kind)
+    , m_type(type)
+{
+}
 
-    ASSERT(m_source == PasteboardSource);
+DataTransferItemChromium::DataTransferItemChromium(const String& kind, const String& type, uint64_t sequenceNumber)
+    : m_source(PasteboardSource)
+    , m_kind(kind)
+    , m_type(type)
+    , m_sequenceNumber(sequenceNumber)
+{
+}
 
-    // This is ugly but there's no real alternative.
-    if (type() == mimeTypeTextPlain) {
-        callback->scheduleCallback(m_context, PlatformSupport::clipboardReadPlainText(currentPasteboardBuffer()));
-        return;
-    }
-    if (type() == mimeTypeTextHTML) {
-        String html;
-        KURL ignoredSourceURL;
-        unsigned ignored;
-        PlatformSupport::clipboardReadHTML(currentPasteboardBuffer(), &html, &ignoredSourceURL, &ignored, &ignored);
-        callback->scheduleCallback(m_context, html);
+void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback, ScriptExecutionContext* context) const
+{
+    if (!callback || kind() != DataTransferItem::kindString)
         return;
-    }
-    ASSERT_NOT_REACHED();
+
+    callback->scheduleCallback(context, internalGetAsString());
 }
 
 PassRefPtr<Blob> DataTransferItemChromium::getAsFile() const
 {
-    if (kind() != kindFile || clipboardChromium()->storageHasUpdated())
+    if (kind() != DataTransferItem::kindFile)
         return 0;
 
-    if (m_source == InternalSource)
-        return m_file;
+    if (m_source == InternalSource) {
+        if (m_file)
+            return m_file;
+        ASSERT(m_sharedBuffer);
+        // FIXME: This code is currently impossible--we never populate m_sharedBuffer when dragging
+        // in. At some point though, we may need to support correctly converting a shared buffer
+        // into a file.
+        return 0;
+    }
 
     ASSERT(m_source == PasteboardSource);
     if (type() == mimeTypeImagePng) {
@@ -146,12 +148,38 @@ PassRefPtr<Blob> DataTransferItemChromium::getAsFile() const
         blobData->setContentType(mimeTypeImagePng);
         return Blob::create(blobData.release(), data->size());
     }
+
     return 0;
 }
 
-ClipboardChromium* DataTransferItemChromium::clipboardChromium() const
+String DataTransferItemChromium::internalGetAsString() const
+{
+    ASSERT(m_kind == DataTransferItem::kindString);
+
+    if (m_source == InternalSource)
+        return m_data;
+
+    ASSERT(m_source == PasteboardSource);
+
+    String data;
+    // This is ugly but there's no real alternative.
+    if (m_type == mimeTypeTextPlain)
+        data = PlatformSupport::clipboardReadPlainText(currentPasteboardBuffer());
+    else if (m_type == mimeTypeTextHTML) {
+        KURL ignoredSourceURL;
+        unsigned ignored;
+        PlatformSupport::clipboardReadHTML(currentPasteboardBuffer(), &data, &ignoredSourceURL, &ignored, &ignored);
+    } else
+        data = PlatformSupport::clipboardReadCustomData(currentPasteboardBuffer(), m_type);
+
+    return PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()) == m_sequenceNumber ? data : String();
+}
+
+bool DataTransferItemChromium::isFilename() const
 {
-    return static_cast<ClipboardChromium*>(m_owner.get());
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=81261: When we properly support File dragout,
+    // we'll need to make sure this works as expected for DragDataChromium.
+    return m_kind == DataTransferItem::kindFile && m_file;
 }
 
 } // namespace WebCore
index 2a91900..1925ba1 100644 (file)
 
 #if ENABLE(DATA_TRANSFER_ITEMS)
 
-#include "DataTransferItem.h"
+#include "File.h"
+#include "KURL.h"
+#include "SharedBuffer.h"
+#include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
-class Clipboard;
-class ClipboardChromium;
-class File;
+class Blob;
 class ScriptExecutionContext;
+class StringCallback;
 
-class DataTransferItemChromium : public DataTransferItem {
+class DataTransferItemChromium : public RefCounted<DataTransferItemChromium> {
 public:
-    static PassRefPtr<DataTransferItemChromium> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& data, const String& type);
-    static PassRefPtr<DataTransferItemChromium> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, PassRefPtr<File>);
-    static PassRefPtr<DataTransferItemChromium> createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& type);
+    static PassRefPtr<DataTransferItemChromium> createFromString(const String& type, const String& data);
+    static PassRefPtr<DataTransferItemChromium> createFromFile(PassRefPtr<File>);
+    static PassRefPtr<DataTransferItemChromium> createFromURL(const String& url, const String& title);
+    static PassRefPtr<DataTransferItemChromium> createFromHTML(const String& html, const KURL& baseURL);
+    static PassRefPtr<DataTransferItemChromium> createFromSharedBuffer(const String& filename, PassRefPtr<SharedBuffer>);
+    static PassRefPtr<DataTransferItemChromium> createFromPasteboard(const String& type, uint64_t sequenceNumber);
 
-    virtual String kind() const { return m_kind; }
-    virtual String type() const { return m_type; }
-    virtual void getAsString(PassRefPtr<StringCallback>) const;
-    virtual PassRefPtr<Blob> getAsFile() const;
+    String kind() const { return m_kind; }
+    String type() const { return m_type; }
+    void getAsString(PassRefPtr<StringCallback>, ScriptExecutionContext*) const;
+    PassRefPtr<Blob> getAsFile() const;
 
-private:
-    friend class DataTransferItemListChromium;
+    // Used to support legacy DataTransfer APIs and renderer->browser serialization.
+    String internalGetAsString() const;
+    PassRefPtr<SharedBuffer> sharedBuffer() const { return m_sharedBuffer; }
+    String title() const { return m_title; }
+    KURL baseURL() const { return m_baseURL; }
+    bool isFilename() const;
 
+private:
     enum DataSource {
         PasteboardSource,
         InternalSource,
     };
 
-    DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, DataSource, const String& kind, const String& type, const String& data);
-    DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, DataSource, PassRefPtr<File>);
+    DataTransferItemChromium(const String& kind, const String& type);
+    DataTransferItemChromium(const String& kind, const String& type, uint64_t sequenceNumber);
 
-    ClipboardChromium* clipboardChromium() const;
+    DataSource m_source;
+    String m_kind;
+    String m_type;
 
-    ScriptExecutionContext* m_context;
-    const RefPtr<Clipboard> m_owner;
-    const String m_kind;
-    const String m_type;
-    const DataSource m_source;
-    const String m_data;
+    String m_data;
     RefPtr<File> m_file;
+    RefPtr<SharedBuffer> m_sharedBuffer;
+    // Optional metadata. Currently used for URL, HTML, and dragging files in.
+    String m_title;
+    KURL m_baseURL;
+
+    uint64_t m_sequenceNumber; // Only valid when m_source == PasteboardSource
 };
 
 } // namespace WebCore
index 3a280fe..7befb80 100644 (file)
 #include "ChromiumDataObject.h"
 #include "ClipboardChromium.h"
 #include "ClipboardMimeTypes.h"
+#include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItem.h"
 #include "DataTransferItemChromium.h"
 #include "ExceptionCode.h"
 #include "File.h"
 #include "KURL.h"
+#include "PlatformSupport.h"
 #include "ScriptExecutionContext.h"
 #include "ThreadableBlobRegistry.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
-PassRefPtr<DataTransferItemListChromium> DataTransferItemListChromium::create(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
+PassRefPtr<DataTransferItemListChromium> DataTransferItemListChromium::create()
 {
-    return adoptRef(new DataTransferItemListChromium(owner, context));
+    return adoptRef(new DataTransferItemListChromium());
 }
 
-DataTransferItemListChromium::DataTransferItemListChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
-    : m_owner(owner)
-    , m_context(context)
+PassRefPtr<DataTransferItemListChromium> DataTransferItemListChromium::createFromPasteboard()
+{
+    RefPtr<DataTransferItemListChromium> list = create();
+    uint64_t sequenceNumber = PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer());
+    bool ignored;
+    HashSet<String> types = PlatformSupport::clipboardReadAvailableTypes(currentPasteboardBuffer(), &ignored);
+    for (HashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it)
+        list->m_itemList.append(DataTransferItemChromium::createFromPasteboard(*it, sequenceNumber));
+    return list.release();
+}
+
+DataTransferItemListChromium::DataTransferItemListChromium()
 {
 }
 
 size_t DataTransferItemListChromium::length() const
 {
-    clipboardChromium()->mayUpdateItems(m_items);
-    return m_items.size();
+    return m_itemList.size();
 }
 
-PassRefPtr<DataTransferItem> DataTransferItemListChromium::item(unsigned long index)
+PassRefPtr<DataTransferItemChromium> DataTransferItemListChromium::item(unsigned long index)
 {
-    clipboardChromium()->mayUpdateItems(m_items);
     if (index >= length())
         return 0;
-    return m_items[index];
+    return m_itemList[index];
 }
 
-void DataTransferItemListChromium::deleteItem(unsigned long index, ExceptionCode& ec)
+void DataTransferItemListChromium::deleteItem(unsigned long index)
 {
-    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);
+    m_itemList.remove(index);
 }
 
 void DataTransferItemListChromium::clear()
 {
-    m_items.clear();
-    clipboardChromium()->clearAllData();
+    m_itemList.clear();
 }
 
 void DataTransferItemListChromium::add(const String& data, const String& type, ExceptionCode& ec)
 {
-    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.
+    if (!internalAddStringItem(DataTransferItemChromium::createFromString(type, data)))
         ec = NOT_SUPPORTED_ERR;
-        return;
-    }
-
-    m_items.clear();
-    dataObject->setData(type, data);
 }
 
-void DataTransferItemListChromium::add(PassRefPtr<File> file)
+void DataTransferItemListChromium::add(PassRefPtr<File> file, ScriptExecutionContext* context)
 {
     if (!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;
+    m_itemList.append(DataTransferItemChromium::createFromFile(file));
 
-    KURL urlForDownload = BlobURL::createPublicURL(m_context->securityOrigin());
+    // FIXME: Allow multiple files to be dragged out at once if more than one file is added to the storage.
+    KURL urlForDownload = BlobURL::createPublicURL(context->securityOrigin());
     ThreadableBlobRegistry::registerBlobURL(urlForDownload, file->url());
 
     StringBuilder downloadUrl;
@@ -157,12 +117,26 @@ void DataTransferItemListChromium::add(PassRefPtr<File> file)
     downloadUrl.append(encodeWithURLEscapeSequences(file->name()));
     downloadUrl.append(":");
     downloadUrl.append(urlForDownload.string());
-    dataObject->setData(mimeTypeDownloadURL, downloadUrl.toString());
+
+    internalAddStringItem(DataTransferItemChromium::createFromString(mimeTypeDownloadURL, downloadUrl.toString()));
+}
+
+// FIXME: Make sure item is released correctly in case of failure.
+bool DataTransferItemListChromium::internalAddStringItem(PassRefPtr<DataTransferItemChromium> item)
+{
+    ASSERT(item->kind() == DataTransferItem::kindString);
+    for (size_t i = 0; i < m_itemList.size(); ++i)
+        if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == item->type())
+            return false;
+
+    m_itemList.append(item);
+    return true;
 }
 
-ClipboardChromium* DataTransferItemListChromium::clipboardChromium() const
+void DataTransferItemListChromium::internalAddFileItem(PassRefPtr<DataTransferItemChromium> item)
 {
-    return static_cast<ClipboardChromium*>(m_owner.get());
+    ASSERT(item->kind() == DataTransferItem::kindFile);
+    m_itemList.append(item);
 }
 
 } // namespace WebCore
index 61bd167..da43aa5 100644 (file)
 
 #if ENABLE(DATA_TRANSFER_ITEMS)
 
-#include "DataTransferItemList.h"
+#include "DataTransferItemChromium.h"
+#include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
 
-class Clipboard;
-class ClipboardChromium;
+class ChromiumDataObject;
 class File;
+class KURL;
 class ScriptExecutionContext;
 
 typedef int ExceptionCode;
 
-class DataTransferItemListChromium : public DataTransferItemList {
+class DataTransferItemListChromium : public RefCounted<DataTransferItemListChromium> {
 public:
-    static PassRefPtr<DataTransferItemListChromium> create(PassRefPtr<Clipboard>, ScriptExecutionContext*);
+    static PassRefPtr<DataTransferItemListChromium> create();
+    static PassRefPtr<DataTransferItemListChromium> createFromPasteboard();
 
-    virtual size_t length() const;
-    virtual PassRefPtr<DataTransferItem> item(unsigned long index);
+    size_t length() const;
+    PassRefPtr<DataTransferItemChromium> 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>);
+    void deleteItem(unsigned long index);
+    void clear();
+    void add(const String& data, const String& type, ExceptionCode&);
+    void add(PassRefPtr<File>, ScriptExecutionContext*);
 
 private:
-    DataTransferItemListChromium(PassRefPtr<Clipboard>, ScriptExecutionContext*);
-    ClipboardChromium* clipboardChromium() const;
+    friend class ChromiumDataObject;
 
-    RefPtr<Clipboard> m_owner;
-    // Indirectly owned by our parent.
-    ScriptExecutionContext* m_context;
-    // FIXME: m_items should not be mutable. This will be fixed by https://bugs.webkit.org/show_bug.cgi?id=76598
-    mutable Vector<RefPtr<DataTransferItem> > m_items;
+    DataTransferItemListChromium();
+
+    // FIXME: Combine with ChromiumDataObject to eliminate the need for these methods.
+    bool internalAddStringItem(PassRefPtr<DataTransferItemChromium>);
+    void internalAddFileItem(PassRefPtr<DataTransferItemChromium>);
+
+    Vector<RefPtr<DataTransferItemChromium> > m_itemList;
 };
 
 } // namespace WebCore
index 3d94a19..009a3a0 100644 (file)
@@ -57,12 +57,9 @@ bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) cons
 String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const
 {
     String url;
-    if (m_platformDragData->types().contains(mimeTypeTextURIList)) {
-        bool ignoredSuccess;
-        url = m_platformDragData->getData(mimeTypeURL, ignoredSuccess);
-        if (title)
-            *title = m_platformDragData->urlTitle();
-    } else if (filenamePolicy == ConvertFilenames && containsFiles()) {
+    if (m_platformDragData->types().contains(mimeTypeTextURIList))
+        m_platformDragData->urlAndTitle(url, title);
+    else if (filenamePolicy == ConvertFilenames && containsFiles()) {
         url = PlatformSupport::filePathToURL(PlatformSupport::getAbsolutePath(m_platformDragData->filenames()[0]));
     }
     return url;
@@ -92,8 +89,7 @@ bool DragData::containsPlainText() const
 
 String DragData::asPlainText(Frame*) const
 {
-    bool ignoredSuccess;
-    return m_platformDragData->getData(mimeTypeTextPlain, ignoredSuccess);
+    return m_platformDragData->getData(mimeTypeTextPlain);
 }
 
 bool DragData::containsColor() const
@@ -142,9 +138,10 @@ PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range
     }
 
     if (m_platformDragData->types().contains(mimeTypeTextHTML)) {
-        bool ignoredSuccess;
-        RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(),
-            m_platformDragData->getData(mimeTypeTextHTML, ignoredSuccess), m_platformDragData->htmlBaseUrl(), FragmentScriptingNotAllowed);
+        String html;
+        KURL baseURL;
+        m_platformDragData->htmlAndBaseURL(html, baseURL);
+        RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, baseURL, FragmentScriptingNotAllowed);
         return fragment.release();
     }
 
index 0f1f171..5606fb0 100644 (file)
@@ -1,3 +1,15 @@
+2012-03-15  Daniel Cheng  <dcheng@chromium.org>
+
+        [chromium] Refactor ClipboardChromium and DataTransferItemList/DataTransferItem to support HTML spec
+        https://bugs.webkit.org/show_bug.cgi?id=76598
+
+        Reviewed by Tony Chang.
+
+        * src/WebDragData.cpp:
+        (WebKit::WebDragData::items):
+        (WebKit::WebDragData::addItem):
+        (WebKit::WebDragData::assign):
+
 2012-03-16  Dana Jansens  <danakj@chromium.org>
 
         [chromium] Add overdraw metrics for texture uploads
index 322dfba..fbf5da7 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "ChromiumDataObject.h"
 #include "ClipboardMimeTypes.h"
+#include "DataTransferItem.h"
 #include "platform/WebData.h"
 #include "platform/WebString.h"
 #include "platform/WebURL.h"
@@ -69,57 +70,29 @@ void WebDragData::assign(const WebDragData& other)
 WebVector<WebDragData::Item> WebDragData::items() const
 {
     Vector<Item> itemList;
-    const HashSet<String>& types = m_private->types();
-    if (types.contains(mimeTypeTextPlain)) {
-        Item item;
-        item.storageType = Item::StorageTypeString;
-        item.stringType = String(mimeTypeTextPlain);
-        bool ignored;
-        item.stringData = m_private->getData(mimeTypeTextPlain, ignored);
+    for (size_t i = 0; i < m_private->items()->length(); ++i) {
+        DataTransferItemChromium* originalItem = m_private->items()->item(i).get();
+        // We don't handle filenames here, since they are never used for dragging out.
+        ASSERT(!originalItem->isFilename());
+        WebDragData::Item item;
+        if (originalItem->kind() == DataTransferItem::kindString) {
+            item.storageType = Item::StorageTypeString;
+            item.stringType = originalItem->type();
+            item.stringData = originalItem->internalGetAsString();
+        } else if (originalItem->kind() == DataTransferItem::kindFile) {
+            if (originalItem->sharedBuffer()) {
+                item.storageType = Item::StorageTypeBinaryData;
+                item.binaryData = originalItem->sharedBuffer();
+            } else
+                // FIXME: Currently we only handle image dragouts using the default drag handling.
+                // If we want to plumb DataTransferItemList::add(File), we'll need to add logic.
+                continue;
+        } else
+            ASSERT_NOT_REACHED();
+        item.title = originalItem->title();
+        item.baseURL = originalItem->baseURL();
         itemList.append(item);
     }
-    if (types.contains(mimeTypeTextURIList)) {
-        Item item;
-        item.storageType = Item::StorageTypeString;
-        item.stringType = String(mimeTypeTextURIList);
-        bool ignored;
-        item.stringData = m_private->getData(mimeTypeURL, ignored);
-        item.title = m_private->urlTitle();
-        itemList.append(item);
-    }
-    if (types.contains(mimeTypeTextHTML)) {
-        Item item;
-        item.storageType = Item::StorageTypeString;
-        item.stringType = String(mimeTypeTextHTML);
-        bool ignored;
-        item.stringData = m_private->getData(mimeTypeTextHTML, ignored);
-        item.baseURL = m_private->htmlBaseUrl();
-        itemList.append(item);
-    }
-    if (types.contains(mimeTypeDownloadURL)) {
-        Item item;
-        item.storageType = Item::StorageTypeString;
-        item.stringType = String(mimeTypeDownloadURL);
-        bool ignored;
-        item.stringData = m_private->getData(mimeTypeDownloadURL, ignored);
-        itemList.append(item);
-    }
-    const HashMap<String, String>& customData = m_private->customData();
-    for (HashMap<String, String>::const_iterator it = customData.begin(); it != customData.end(); ++it) {
-        Item item;
-        item.storageType = Item::StorageTypeString;
-        item.stringType = it->first;
-        item.stringData = it->second;
-        itemList.append(item);
-    }
-    if (m_private->fileContent()) {
-        Item item;
-        item.storageType = Item::StorageTypeBinaryData;
-        item.binaryData = m_private->fileContent();
-        item.title = m_private->fileContentFilename();
-        itemList.append(item);
-    }
-    // We don't handle filenames here, since they are never used for dragging out.
     return itemList;
 }
 
@@ -135,11 +108,12 @@ void WebDragData::addItem(const Item& item)
     ensureMutable();
     switch (item.storageType) {
     case Item::StorageTypeString:
-        m_private->setData(item.stringType, item.stringData);
         if (String(item.stringType) == mimeTypeTextURIList)
-            m_private->setUrlTitle(item.title);
+            m_private->setURLAndTitle(item.stringData, item.title);
         else if (String(item.stringType) == mimeTypeTextHTML)
-            m_private->setHtmlBaseUrl(item.baseURL);
+            m_private->setHTMLAndBaseURL(item.stringData, item.baseURL);
+        else
+            m_private->setData(item.stringType, item.stringData);
         return;
     case Item::StorageTypeFilename:
         m_private->addFilename(item.filenameData);
@@ -168,7 +142,6 @@ WebDragData::operator WTF::PassRefPtr<WebCore::ChromiumDataObject>() const
 
 void WebDragData::assign(WebDragDataPrivate* p)
 {
-    ASSERT(!p || p->storageMode() == ChromiumDataObject::Buffered);
     // p is already ref'd for us by the caller
     if (m_private)
         m_private->deref();