75d50bceb30ac99ed9c86b31c663059e052dc8f2
[WebKit-https.git] / Source / WebCore / platform / mac / DragDataMac.mm
1 /*
2  * Copyright (C) 2007 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 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 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 #import "config.h"
27 #import "DragData.h"
28
29 #if ENABLE(DRAG_SUPPORT)
30 #import "MIMETypeRegistry.h"
31 #import "Pasteboard.h"
32 #import "PasteboardStrategy.h"
33 #import "PlatformStrategies.h"
34 #import "WebCoreNSURLExtras.h"
35
36 namespace WebCore {
37
38 DragData::DragData(DragDataRef data, const IntPoint& clientPosition, const IntPoint& globalPosition, 
39     DragOperation sourceOperationMask, DragApplicationFlags flags)
40     : m_clientPosition(clientPosition)
41     , m_globalPosition(globalPosition)
42     , m_platformDragData(data)
43     , m_draggingSourceOperationMask(sourceOperationMask)
44     , m_applicationFlags(flags)
45     , m_pasteboardName([[m_platformDragData draggingPasteboard] name])
46 {
47 }
48
49 DragData::DragData(const String& dragStorageName, const IntPoint& clientPosition, const IntPoint& globalPosition,
50     DragOperation sourceOperationMask, DragApplicationFlags flags)
51     : m_clientPosition(clientPosition)
52     , m_globalPosition(globalPosition)
53     , m_platformDragData(0)
54     , m_draggingSourceOperationMask(sourceOperationMask)
55     , m_applicationFlags(flags)
56     , m_pasteboardName(dragStorageName)
57 {
58 }
59     
60 bool DragData::canSmartReplace() const
61 {
62     return Pasteboard(m_pasteboardName).canSmartReplace();
63 }
64
65 bool DragData::containsColor() const
66 {
67     Vector<String> types;
68     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
69     return types.contains(String(NSColorPboardType));
70 }
71
72 bool DragData::containsFiles() const
73 {
74     Vector<String> types;
75     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
76     return types.contains(String(NSFilenamesPboardType)) || types.contains(String(NSFilesPromisePboardType));
77 }
78
79 unsigned DragData::numberOfFiles() const
80 {
81     Vector<String> files;
82     platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilenamesPboardType), m_pasteboardName);
83     if (!files.size())
84         platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilesPromisePboardType), m_pasteboardName);
85     return files.size();
86 }
87
88 void DragData::asFilenames(Vector<String>& result) const
89 {
90     platformStrategies()->pasteboardStrategy()->getPathnamesForType(result, String(NSFilenamesPboardType), m_pasteboardName);
91     if (!result.size())
92         result = fileNames();
93 }
94
95 bool DragData::containsPlainText() const
96 {
97     Vector<String> types;
98     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
99
100     return types.contains(String(NSStringPboardType))
101         || types.contains(String(NSRTFDPboardType))
102         || types.contains(String(NSRTFPboardType))
103         || types.contains(String(NSFilenamesPboardType))
104         || platformStrategies()->pasteboardStrategy()->stringForType(String(NSURLPboardType), m_pasteboardName).length();
105 }
106
107 String DragData::asPlainText() const
108 {
109     Pasteboard pasteboard(m_pasteboardName);
110     PasteboardPlainText text;
111     pasteboard.read(text);
112     String string = text.text;
113
114     // FIXME: It's not clear this is 100% correct since we know -[NSURL URLWithString:] does not handle
115     // all the same cases we handle well in the URL code for creating an NSURL.
116     if (text.isURL)
117         return userVisibleString([NSURL URLWithString:string]);
118
119     // FIXME: WTF should offer a non-Mac-specific way to convert string to precomposed form so we can do it for all platforms.
120     return [(NSString *)string precomposedStringWithCanonicalMapping];
121 }
122
123 Color DragData::asColor() const
124 {
125     return platformStrategies()->pasteboardStrategy()->color(m_pasteboardName);
126 }
127
128 bool DragData::containsCompatibleContent() const
129 {
130     Vector<String> types;
131     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
132     return types.contains(String(WebArchivePboardType))
133         || types.contains(String(NSHTMLPboardType))
134         || types.contains(String(NSFilenamesPboardType))
135         || types.contains(String(NSFilesPromisePboardType))
136         || types.contains(String(NSTIFFPboardType))
137         || types.contains(String(NSPDFPboardType))
138         || types.contains(String(NSURLPboardType))
139         || types.contains(String(NSRTFDPboardType))
140         || types.contains(String(NSRTFPboardType))
141         || types.contains(String(NSStringPboardType))
142         || types.contains(String(NSColorPboardType))
143         || types.contains(String(kUTTypePNG));
144 }
145
146 bool DragData::containsPromise() const
147 {
148     Vector<String> files;
149     platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilesPromisePboardType), m_pasteboardName);
150     return files.size() == 1;
151 }
152
153 bool DragData::containsURL(FilenameConversionPolicy filenamePolicy) const
154 {
155     return !asURL(filenamePolicy).isEmpty();
156 }
157
158 String DragData::asURL(FilenameConversionPolicy, String* title) const
159 {
160     // FIXME: Use filenamePolicy.
161
162     if (title) {
163         String URLTitleString = platformStrategies()->pasteboardStrategy()->stringForType(String(WebURLNamePboardType), m_pasteboardName);
164         if (!URLTitleString.isEmpty())
165             *title = URLTitleString;
166     }
167     
168     Vector<String> types;
169     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
170
171     if (types.contains(String(NSURLPboardType))) {
172         NSURL *URLFromPasteboard = [NSURL URLWithString:platformStrategies()->pasteboardStrategy()->stringForType(String(NSURLPboardType), m_pasteboardName)];
173         NSString *scheme = [URLFromPasteboard scheme];
174         // Cannot drop other schemes unless <rdar://problem/10562662> and <rdar://problem/11187315> are fixed.
175         if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"])
176             return [URLByCanonicalizingURL(URLFromPasteboard) absoluteString];
177     }
178     
179     if (types.contains(String(NSStringPboardType))) {
180         NSURL *URLFromPasteboard = [NSURL URLWithString:platformStrategies()->pasteboardStrategy()->stringForType(String(NSStringPboardType), m_pasteboardName)];
181         NSString *scheme = [URLFromPasteboard scheme];
182         // Pasteboard content is not trusted, because JavaScript code can modify it. We can sanitize it for URLs and other typed content, but not for strings.
183         // The result of this function is used to initiate navigation, so we shouldn't allow arbitrary file URLs.
184         // FIXME: Should we allow only http family schemes, or anything non-local?
185         if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"])
186             return [URLByCanonicalizingURL(URLFromPasteboard) absoluteString];
187     }
188     
189     if (types.contains(String(NSFilenamesPboardType))) {
190         Vector<String> files;
191         platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilenamesPboardType), m_pasteboardName);
192         if (files.size() == 1) {
193             BOOL isDirectory;
194             if ([[NSFileManager defaultManager] fileExistsAtPath:files[0] isDirectory:&isDirectory] && isDirectory)
195                 return String();
196             return [URLByCanonicalizingURL([NSURL fileURLWithPath:files[0]]) absoluteString];
197         }
198     }
199
200     if (types.contains(String(NSFilesPromisePboardType)) && fileNames().size() == 1)
201         return [URLByCanonicalizingURL([NSURL fileURLWithPath:fileNames()[0]]) absoluteString];
202
203     return String();        
204 }
205
206 } // namespace WebCore
207
208 #endif // ENABLE(DRAG_SUPPORT)