1 /* 2 * Copyright (C) 2006, 2007, 2008 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "core/dom/Clipboard.h" 28 29 #include "core/fileapi/FileList.h" 30 #include "core/loader/cache/ImageResource.h" 31 32 namespace WebCore { 33 34 Clipboard::Clipboard(ClipboardAccessPolicy policy, ClipboardType clipboardType) 35 : m_policy(policy) 36 , m_dropEffect("uninitialized") 37 , m_effectAllowed("uninitialized") 38 , m_dragStarted(false) 39 , m_clipboardType(clipboardType) 40 , m_dragImage(0) 41 { 42 ScriptWrappable::init(this); 43 } 44 45 void Clipboard::setAccessPolicy(ClipboardAccessPolicy policy) 46 { 47 // once you go numb, can never go back 48 ASSERT(m_policy != ClipboardNumb || policy == ClipboardNumb); 49 m_policy = policy; 50 } 51 52 bool Clipboard::canReadTypes() const 53 { 54 return m_policy == ClipboardReadable || m_policy == ClipboardTypesReadable || m_policy == ClipboardWritable; 55 } 56 57 bool Clipboard::canReadData() const 58 { 59 return m_policy == ClipboardReadable || m_policy == ClipboardWritable; 60 } 61 62 bool Clipboard::canWriteData() const 63 { 64 return m_policy == ClipboardWritable; 65 } 66 67 bool Clipboard::canSetDragImage() const 68 { 69 return m_policy == ClipboardImageWritable || m_policy == ClipboardWritable; 70 } 71 72 // These "conversion" methods are called by both WebCore and WebKit, and never make sense to JS, so we don't 73 // worry about security for these. They don't allow access to the pasteboard anyway. 74 75 static DragOperation dragOpFromIEOp(const String& op) 76 { 77 // yep, it's really just this fixed set 78 if (op == "uninitialized") 79 return DragOperationEvery; 80 if (op == "none") 81 return DragOperationNone; 82 if (op == "copy") 83 return DragOperationCopy; 84 if (op == "link") 85 return DragOperationLink; 86 if (op == "move") 87 return (DragOperation)(DragOperationGeneric | DragOperationMove); 88 if (op == "copyLink") 89 return (DragOperation)(DragOperationCopy | DragOperationLink); 90 if (op == "copyMove") 91 return (DragOperation)(DragOperationCopy | DragOperationGeneric | DragOperationMove); 92 if (op == "linkMove") 93 return (DragOperation)(DragOperationLink | DragOperationGeneric | DragOperationMove); 94 if (op == "all") 95 return DragOperationEvery; 96 return DragOperationPrivate; // really a marker for "no conversion" 97 } 98 99 static String IEOpFromDragOp(DragOperation op) 100 { 101 bool moveSet = !!((DragOperationGeneric | DragOperationMove) & op); 102 103 if ((moveSet && (op & DragOperationCopy) && (op & DragOperationLink)) 104 || (op == DragOperationEvery)) 105 return "all"; 106 if (moveSet && (op & DragOperationCopy)) 107 return "copyMove"; 108 if (moveSet && (op & DragOperationLink)) 109 return "linkMove"; 110 if ((op & DragOperationCopy) && (op & DragOperationLink)) 111 return "copyLink"; 112 if (moveSet) 113 return "move"; 114 if (op & DragOperationCopy) 115 return "copy"; 116 if (op & DragOperationLink) 117 return "link"; 118 return "none"; 119 } 120 121 DragOperation Clipboard::sourceOperation() const 122 { 123 DragOperation op = dragOpFromIEOp(m_effectAllowed); 124 ASSERT(op != DragOperationPrivate); 125 return op; 126 } 127 128 DragOperation Clipboard::destinationOperation() const 129 { 130 DragOperation op = dragOpFromIEOp(m_dropEffect); 131 ASSERT(op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == (DragOperation)(DragOperationGeneric | DragOperationMove) || op == DragOperationEvery); 132 return op; 133 } 134 135 void Clipboard::setSourceOperation(DragOperation op) 136 { 137 ASSERT_ARG(op, op != DragOperationPrivate); 138 m_effectAllowed = IEOpFromDragOp(op); 139 } 140 141 void Clipboard::setDestinationOperation(DragOperation op) 142 { 143 ASSERT_ARG(op, op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == DragOperationGeneric || op == DragOperationMove || op == (DragOperation)(DragOperationGeneric | DragOperationMove)); 144 m_dropEffect = IEOpFromDragOp(op); 145 } 146 147 bool Clipboard::hasFileOfType(const String& type) const 148 { 149 if (!canReadTypes()) 150 return false; 151 152 RefPtr<FileList> fileList = files(); 153 if (fileList->isEmpty()) 154 return false; 155 156 for (unsigned int f = 0; f < fileList->length(); f++) { 157 if (equalIgnoringCase(fileList->item(f)->type(), type)) 158 return true; 159 } 160 return false; 161 } 162 163 bool Clipboard::hasStringOfType(const String& type) const 164 { 165 if (!canReadTypes()) 166 return false; 167 168 return types().contains(type); 169 } 170 171 void Clipboard::setDropEffect(const String &effect) 172 { 173 if (!isForDragAndDrop()) 174 return; 175 176 // The attribute must ignore any attempts to set it to a value other than none, copy, link, and move. 177 if (effect != "none" && effect != "copy" && effect != "link" && effect != "move") 178 return; 179 180 // FIXME: The spec actually allows this in all circumstances, even though there's no point in 181 // setting the drop effect when this condition is not true. 182 if (canReadTypes()) 183 m_dropEffect = effect; 184 } 185 186 void Clipboard::setEffectAllowed(const String &effect) 187 { 188 if (!isForDragAndDrop()) 189 return; 190 191 if (dragOpFromIEOp(effect) == DragOperationPrivate) { 192 // This means that there was no conversion, and the effectAllowed that 193 // we are passed isn't a valid effectAllowed, so we should ignore it, 194 // and not set m_effectAllowed. 195 196 // The attribute must ignore any attempts to set it to a value other than 197 // none, copy, copyLink, copyMove, link, linkMove, move, all, and uninitialized. 198 return; 199 } 200 201 202 if (canWriteData()) 203 m_effectAllowed = effect; 204 } 205 206 DragOperation convertDropZoneOperationToDragOperation(const String& dragOperation) 207 { 208 if (dragOperation == "copy") 209 return DragOperationCopy; 210 if (dragOperation == "move") 211 return DragOperationMove; 212 if (dragOperation == "link") 213 return DragOperationLink; 214 return DragOperationNone; 215 } 216 217 String convertDragOperationToDropZoneOperation(DragOperation operation) 218 { 219 switch (operation) { 220 case DragOperationCopy: 221 return String("copy"); 222 case DragOperationMove: 223 return String("move"); 224 case DragOperationLink: 225 return String("link"); 226 default: 227 return String("copy"); 228 } 229 } 230 231 bool Clipboard::hasDropZoneType(const String& keyword) 232 { 233 if (keyword.startsWith("file:")) 234 return hasFileOfType(keyword.substring(5)); 235 236 if (keyword.startsWith("string:")) 237 return hasStringOfType(keyword.substring(7)); 238 239 return false; 240 } 241 242 } // namespace WebCore 243