1 /* 2 * Copyright (c) 2008, 2009, 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/platform/chromium/ChromiumDataObject.h" 33 34 #include "bindings/v8/ExceptionState.h" 35 #include "bindings/v8/ExceptionStatePlaceholder.h" 36 #include "core/dom/DataTransferItem.h" 37 #include "core/dom/ExceptionCode.h" 38 #include "core/platform/chromium/ClipboardMimeTypes.h" 39 #include "core/platform/chromium/ClipboardUtilitiesChromium.h" 40 #include "public/platform/Platform.h" 41 #include "public/platform/WebClipboard.h" 42 43 namespace WebCore { 44 45 PassRefPtr<ChromiumDataObject> ChromiumDataObject::createFromPasteboard() 46 { 47 RefPtr<ChromiumDataObject> dataObject = create(); 48 uint64_t sequenceNumber = WebKit::Platform::current()->clipboard()->sequenceNumber(currentPasteboardBuffer()); 49 bool ignored; 50 WebKit::WebVector<WebKit::WebString> webTypes = WebKit::Platform::current()->clipboard()->readAvailableTypes(currentPasteboardBuffer(), &ignored); 51 ListHashSet<String> types; 52 for (size_t i = 0; i < webTypes.size(); ++i) 53 types.add(webTypes[i]); 54 for (ListHashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it) 55 dataObject->m_itemList.append(ChromiumDataObjectItem::createFromPasteboard(*it, sequenceNumber)); 56 return dataObject.release(); 57 } 58 59 PassRefPtr<ChromiumDataObject> ChromiumDataObject::create() 60 { 61 return adoptRef(new ChromiumDataObject()); 62 } 63 64 PassRefPtr<ChromiumDataObject> ChromiumDataObject::copy() const 65 { 66 return adoptRef(new ChromiumDataObject(*this)); 67 } 68 69 size_t ChromiumDataObject::length() const 70 { 71 return m_itemList.size(); 72 } 73 74 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObject::item(unsigned long index) 75 { 76 if (index >= length()) 77 return 0; 78 return m_itemList[index]; 79 } 80 81 void ChromiumDataObject::deleteItem(unsigned long index) 82 { 83 if (index >= length()) 84 return; 85 m_itemList.remove(index); 86 } 87 88 void ChromiumDataObject::clearAll() 89 { 90 m_itemList.clear(); 91 } 92 93 void ChromiumDataObject::add(const String& data, const String& type, ExceptionState& es) 94 { 95 if (!internalAddStringItem(ChromiumDataObjectItem::createFromString(type, data))) 96 es.throwDOMException(NotSupportedError); 97 } 98 99 void ChromiumDataObject::add(PassRefPtr<File> file, ScriptExecutionContext* context) 100 { 101 if (!file) 102 return; 103 104 m_itemList.append(ChromiumDataObjectItem::createFromFile(file)); 105 } 106 107 void ChromiumDataObject::clearData(const String& type) 108 { 109 for (size_t i = 0; i < m_itemList.size(); ++i) { 110 if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == type) { 111 // Per the spec, type must be unique among all items of kind 'string'. 112 m_itemList.remove(i); 113 return; 114 } 115 } 116 } 117 118 void ChromiumDataObject::clearAllExceptFiles() 119 { 120 for (size_t i = 0; i < m_itemList.size(); ) { 121 if (m_itemList[i]->kind() != DataTransferItem::kindFile) { 122 m_itemList.remove(i); 123 continue; 124 } 125 ++i; 126 } 127 } 128 129 ListHashSet<String> ChromiumDataObject::types() const 130 { 131 ListHashSet<String> results; 132 bool containsFiles = false; 133 for (size_t i = 0; i < m_itemList.size(); ++i) { 134 if (m_itemList[i]->kind() == DataTransferItem::kindString) 135 results.add(m_itemList[i]->type()); 136 else if (m_itemList[i]->kind() == DataTransferItem::kindFile) 137 containsFiles = true; 138 else 139 ASSERT_NOT_REACHED(); 140 } 141 if (containsFiles) 142 results.add(mimeTypeFiles); 143 return results; 144 } 145 146 String ChromiumDataObject::getData(const String& type) const 147 { 148 for (size_t i = 0; i < m_itemList.size(); ++i) { 149 if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == type) 150 return m_itemList[i]->internalGetAsString(); 151 } 152 return String(); 153 } 154 155 bool ChromiumDataObject::setData(const String& type, const String& data) 156 { 157 clearData(type); 158 add(data, type, ASSERT_NO_EXCEPTION); 159 return true; 160 } 161 162 void ChromiumDataObject::urlAndTitle(String& url, String* title) const 163 { 164 RefPtr<ChromiumDataObjectItem> item = findStringItem(mimeTypeTextURIList); 165 if (!item) 166 return; 167 url = convertURIListToURL(item->internalGetAsString()); 168 if (title) 169 *title = item->title(); 170 } 171 172 void ChromiumDataObject::setURLAndTitle(const String& url, const String& title) 173 { 174 clearData(mimeTypeTextURIList); 175 internalAddStringItem(ChromiumDataObjectItem::createFromURL(url, title)); 176 } 177 178 void ChromiumDataObject::htmlAndBaseURL(String& html, KURL& baseURL) const 179 { 180 RefPtr<ChromiumDataObjectItem> item = findStringItem(mimeTypeTextHTML); 181 if (!item) 182 return; 183 html = item->internalGetAsString(); 184 baseURL = item->baseURL(); 185 } 186 187 void ChromiumDataObject::setHTMLAndBaseURL(const String& html, const KURL& baseURL) 188 { 189 clearData(mimeTypeTextHTML); 190 internalAddStringItem(ChromiumDataObjectItem::createFromHTML(html, baseURL)); 191 } 192 193 bool ChromiumDataObject::containsFilenames() const 194 { 195 for (size_t i = 0; i < m_itemList.size(); ++i) 196 if (m_itemList[i]->isFilename()) 197 return true; 198 return false; 199 } 200 201 Vector<String> ChromiumDataObject::filenames() const 202 { 203 Vector<String> results; 204 for (size_t i = 0; i < m_itemList.size(); ++i) 205 if (m_itemList[i]->isFilename()) 206 results.append(static_cast<File*>(m_itemList[i]->getAsFile().get())->path()); 207 return results; 208 } 209 210 void ChromiumDataObject::addFilename(const String& filename, const String& displayName) 211 { 212 internalAddFileItem(ChromiumDataObjectItem::createFromFile(File::createWithName(filename, displayName, File::AllContentTypes))); 213 } 214 215 void ChromiumDataObject::addSharedBuffer(const String& name, PassRefPtr<SharedBuffer> buffer) 216 { 217 internalAddFileItem(ChromiumDataObjectItem::createFromSharedBuffer(name, buffer)); 218 } 219 220 ChromiumDataObject::ChromiumDataObject() 221 : m_modifierKeyState(0) 222 { 223 } 224 225 ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other) 226 : RefCounted<ChromiumDataObject>() 227 , m_itemList(other.m_itemList) 228 , m_modifierKeyState(0) 229 { 230 } 231 232 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObject::findStringItem(const String& type) const 233 { 234 for (size_t i = 0; i < m_itemList.size(); ++i) { 235 if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == type) 236 return m_itemList[i]; 237 } 238 return 0; 239 } 240 241 bool ChromiumDataObject::internalAddStringItem(PassRefPtr<ChromiumDataObjectItem> item) 242 { 243 ASSERT(item->kind() == DataTransferItem::kindString); 244 for (size_t i = 0; i < m_itemList.size(); ++i) 245 if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == item->type()) 246 return false; 247 248 m_itemList.append(item); 249 return true; 250 } 251 252 void ChromiumDataObject::internalAddFileItem(PassRefPtr<ChromiumDataObjectItem> item) 253 { 254 ASSERT(item->kind() == DataTransferItem::kindFile); 255 m_itemList.append(item); 256 } 257 258 } // namespace WebCore 259