Data store should be readable in dragstart/copy/cut events
[WebKit-https.git] / Source / WebCore / dom / Clipboard.cpp
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 "Clipboard.h"
28
29 #include "CachedImage.h"
30 #include "FileList.h"
31 #include "Frame.h"
32 #include "FrameLoader.h"
33 #include "Image.h"
34
35 namespace WebCore {
36
37 Clipboard::Clipboard(ClipboardAccessPolicy policy, ClipboardType clipboardType) 
38     : m_policy(policy)
39     , m_dropEffect("uninitialized")
40     , m_effectAllowed("uninitialized")
41     , m_dragStarted(false)
42     , m_clipboardType(clipboardType)
43     , m_dragImage(0)
44 {
45 }
46     
47 void Clipboard::setAccessPolicy(ClipboardAccessPolicy policy)
48 {
49     // once you go numb, can never go back
50     ASSERT(m_policy != ClipboardNumb || policy == ClipboardNumb);
51     m_policy = policy;
52 }
53
54 bool Clipboard::canReadTypes() const
55 {
56     return m_policy == ClipboardReadable || m_policy == ClipboardTypesReadable || m_policy == ClipboardWritable;
57 }
58
59 bool Clipboard::canReadData() const
60 {
61     return m_policy == ClipboardReadable || m_policy == ClipboardWritable;
62 }
63
64 bool Clipboard::canWriteData() const
65 {
66     return m_policy == ClipboardWritable;
67 }
68
69 bool Clipboard::canSetDragImage() const
70 {
71     return m_policy == ClipboardImageWritable || m_policy == ClipboardWritable;
72 }
73
74 // These "conversion" methods are called by both WebCore and WebKit, and never make sense to JS, so we don't
75 // worry about security for these. They don't allow access to the pasteboard anyway.
76
77 static DragOperation dragOpFromIEOp(const String& op)
78 {
79     // yep, it's really just this fixed set
80     if (op == "uninitialized")
81         return DragOperationEvery;
82     if (op == "none")
83         return DragOperationNone;
84     if (op == "copy")
85         return DragOperationCopy;
86     if (op == "link")
87         return DragOperationLink;
88     if (op == "move")
89         return (DragOperation)(DragOperationGeneric | DragOperationMove);
90     if (op == "copyLink")
91         return (DragOperation)(DragOperationCopy | DragOperationLink);
92     if (op == "copyMove")
93         return (DragOperation)(DragOperationCopy | DragOperationGeneric | DragOperationMove);
94     if (op == "linkMove")
95         return (DragOperation)(DragOperationLink | DragOperationGeneric | DragOperationMove);
96     if (op == "all")
97         return DragOperationEvery;
98     return DragOperationPrivate;  // really a marker for "no conversion"
99 }
100
101 static String IEOpFromDragOp(DragOperation op)
102 {
103     bool moveSet = !!((DragOperationGeneric | DragOperationMove) & op);
104     
105     if ((moveSet && (op & DragOperationCopy) && (op & DragOperationLink))
106         || (op == DragOperationEvery))
107         return "all";
108     if (moveSet && (op & DragOperationCopy))
109         return "copyMove";
110     if (moveSet && (op & DragOperationLink))
111         return "linkMove";
112     if ((op & DragOperationCopy) && (op & DragOperationLink))
113         return "copyLink";
114     if (moveSet)
115         return "move";
116     if (op & DragOperationCopy)
117         return "copy";
118     if (op & DragOperationLink)
119         return "link";
120     return "none";
121 }
122
123 DragOperation Clipboard::sourceOperation() const
124 {
125     DragOperation op = dragOpFromIEOp(m_effectAllowed);
126     ASSERT(op != DragOperationPrivate);
127     return op;
128 }
129
130 DragOperation Clipboard::destinationOperation() const
131 {
132     DragOperation op = dragOpFromIEOp(m_dropEffect);
133     ASSERT(op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == (DragOperation)(DragOperationGeneric | DragOperationMove) || op == DragOperationEvery);
134     return op;
135 }
136
137 void Clipboard::setSourceOperation(DragOperation op)
138 {
139     ASSERT_ARG(op, op != DragOperationPrivate);
140     m_effectAllowed = IEOpFromDragOp(op);
141 }
142
143 void Clipboard::setDestinationOperation(DragOperation op)
144 {
145     ASSERT_ARG(op, op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == DragOperationGeneric || op == DragOperationMove || op == (DragOperation)(DragOperationGeneric | DragOperationMove));
146     m_dropEffect = IEOpFromDragOp(op);
147 }
148
149 bool Clipboard::hasFileOfType(const String& type) const
150 {
151     if (!canReadTypes())
152         return false;
153     
154     RefPtr<FileList> fileList = files();
155     if (fileList->isEmpty())
156         return false;
157     
158     for (unsigned int f = 0; f < fileList->length(); f++) {
159         if (equalIgnoringCase(fileList->item(f)->type(), type))
160             return true;
161     }
162     return false;
163 }
164
165 bool Clipboard::hasStringOfType(const String& type) const
166 {
167     if (!canReadTypes())
168         return false;
169     
170     return types().contains(type); 
171 }
172     
173 void Clipboard::setDropEffect(const String &effect)
174 {
175     if (!isForDragAndDrop())
176         return;
177
178     // The attribute must ignore any attempts to set it to a value other than none, copy, link, and move. 
179     if (effect != "none" && effect != "copy"  && effect != "link" && effect != "move")
180         return;
181
182     // FIXME: The spec actually allows this in all circumstances, even though there's no point in
183     // setting the drop effect when this condition is not true.
184     if (canReadTypes())
185         m_dropEffect = effect;
186 }
187
188 void Clipboard::setEffectAllowed(const String &effect)
189 {
190     if (!isForDragAndDrop())
191         return;
192
193     if (dragOpFromIEOp(effect) == DragOperationPrivate) {
194         // This means that there was no conversion, and the effectAllowed that
195         // we are passed isn't a valid effectAllowed, so we should ignore it,
196         // and not set m_effectAllowed.
197
198         // The attribute must ignore any attempts to set it to a value other than 
199         // none, copy, copyLink, copyMove, link, linkMove, move, all, and uninitialized.
200         return;
201     }
202
203
204     if (canWriteData())
205         m_effectAllowed = effect;
206 }
207     
208 DragOperation convertDropZoneOperationToDragOperation(const String& dragOperation)
209 {
210     if (dragOperation == "copy")
211         return DragOperationCopy;
212     if (dragOperation == "move")
213         return DragOperationMove;
214     if (dragOperation == "link")
215         return DragOperationLink;
216     return DragOperationNone;
217 }
218
219 String convertDragOperationToDropZoneOperation(DragOperation operation)
220 {
221     switch (operation) {
222     case DragOperationCopy:
223         return String("copy");
224     case DragOperationMove:
225         return String("move");
226     case DragOperationLink:
227         return String("link");
228     default:
229         return String("copy");
230     }
231 }
232
233 bool Clipboard::hasDropZoneType(const String& keyword)
234 {
235     if (keyword.startsWith("file:"))
236         return hasFileOfType(keyword.substring(5));
237
238     if (keyword.startsWith("string:"))
239         return hasStringOfType(keyword.substring(7));
240
241     return false;
242 }
243
244 } // namespace WebCore