Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1210)

Side by Side Diff: Source/WebCore/platform/mac/ClipboardMac.mm

Issue 13713003: Remove all of WebCore/platform/mac which is not mentioned in WebCore.gypi. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Added back a couple needed headers Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2004, 2005, 2006, 2008, 2010 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 #import "config.h"
27 #import "ClipboardMac.h"
28
29 #import "CachedImage.h"
30 #import "CachedImageClient.h"
31 #import "DOMElementInternal.h"
32 #import "DragClient.h"
33 #import "DragController.h"
34 #import "DragData.h"
35 #import "Editor.h"
36 #import "FileList.h"
37 #import "Frame.h"
38 #import "Image.h"
39 #import "Page.h"
40 #import "Pasteboard.h"
41 #import "PasteboardStrategy.h"
42 #import "PlatformStrategies.h"
43 #import "RenderImage.h"
44 #import "ScriptExecutionContext.h"
45 #import "SecurityOrigin.h"
46 #import "WebCoreSystemInterface.h"
47
48
49 namespace WebCore {
50
51 #if ENABLE(DRAG_SUPPORT)
52 PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
53 {
54 return ClipboardMac::create(DragAndDrop, dragData->pasteboardName(), policy, dragData->containsFiles() ? ClipboardMac::DragAndDropFiles : ClipboardMac::Drag AndDropData, frame);
55 }
56 #endif
57
58 ClipboardMac::ClipboardMac(ClipboardType clipboardType, const String& pasteboard Name, ClipboardAccessPolicy policy, ClipboardContents clipboardContents, Frame * frame)
59 : Clipboard(policy, clipboardType)
60 , m_pasteboardName(pasteboardName)
61 , m_clipboardContents(clipboardContents)
62 , m_frame(frame)
63 {
64 m_changeCount = platformStrategies()->pasteboardStrategy()->changeCount(m_pa steboardName);
65 }
66
67 ClipboardMac::~ClipboardMac()
68 {
69 if (m_dragImage)
70 m_dragImage->removeClient(this);
71 }
72
73 bool ClipboardMac::hasData()
74 {
75 Vector<String> types;
76 platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName );
77 return !types.isEmpty();
78 }
79
80 static String cocoaTypeFromHTMLClipboardType(const String& type)
81 {
82 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dom- datatransfer-setdata
83 String qType = type.lower();
84
85 if (qType == "text")
86 qType = "text/plain";
87 if (qType == "url")
88 qType = "text/uri-list";
89
90 // Ignore any trailing charset - JS strings are Unicode, which encapsulates the charset issue
91 if (qType == "text/plain" || qType.startsWith("text/plain;"))
92 return String(NSStringPboardType);
93 if (qType == "text/uri-list")
94 // special case because UTI doesn't work with Cocoa's URL type
95 return String(NSURLPboardType); // note special case in getData to read NSFilenamesType
96
97 // Blacklist types that might contain subframe information
98 if (qType == "text/rtf" || qType == "public.rtf" || qType == "com.apple.trad itional-mac-plain-text")
99 return String();
100
101 // Try UTI now
102 String mimeType = qType;
103 if (RetainPtr<CFStringRef> utiType = adoptCF(UTTypeCreatePreferredIdentifier ForTag(kUTTagClassMIMEType, mimeType.createCFString().get(), NULL))) {
104 RetainPtr<CFStringRef> pbType = adoptCF(UTTypeCopyPreferredTagWithClass( utiType.get(), kUTTagClassNSPboardType));
105 if (pbType)
106 return pbType.get();
107 }
108
109 // No mapping, just pass the whole string though
110 return qType;
111 }
112
113 static String utiTypeFromCocoaType(const String& type)
114 {
115 if (RetainPtr<CFStringRef> utiType = adoptCF(UTTypeCreatePreferredIdentifier ForTag(kUTTagClassNSPboardType, type.createCFString().get(), 0))) {
116 if (RetainPtr<CFStringRef> mimeType = adoptCF(UTTypeCopyPreferredTagWith Class(utiType.get(), kUTTagClassMIMEType)))
117 return String(mimeType.get());
118 }
119 return String();
120 }
121
122 static void addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType, const String& pasteboardName)
123 {
124 // UTI may not do these right, so make sure we get the right, predictable re sult
125 if (cocoaType == String(NSStringPboardType)) {
126 resultTypes.add("text/plain");
127 return;
128 }
129 if (cocoaType == String(NSURLPboardType)) {
130 resultTypes.add("text/uri-list");
131 return;
132 }
133 if (cocoaType == String(NSFilenamesPboardType)) {
134 // If file list is empty, add nothing.
135 // Note that there is a chance that the file list count could have chang ed since we grabbed the types array.
136 // However, this is not really an issue for us doing a sanity check here .
137 Vector<String> fileList;
138 platformStrategies()->pasteboardStrategy()->getPathnamesForType(fileList , String(NSFilenamesPboardType), pasteboardName);
139 if (!fileList.isEmpty()) {
140 // It is unknown if NSFilenamesPboardType always implies NSURLPboard Type in Cocoa,
141 // but NSFilenamesPboardType should imply both 'text/uri-list' and ' Files'
142 resultTypes.add("text/uri-list");
143 resultTypes.add("Files");
144 }
145 return;
146 }
147 String utiType = utiTypeFromCocoaType(cocoaType);
148 if (!utiType.isEmpty()) {
149 resultTypes.add(utiType);
150 return;
151 }
152 // No mapping, just pass the whole string though
153 resultTypes.add(cocoaType);
154 }
155
156 void ClipboardMac::clearData(const String& type)
157 {
158 if (!canWriteData())
159 return;
160
161 // note NSPasteboard enforces changeCount itself on writing - can't write if not the owner
162
163 String cocoaType = cocoaTypeFromHTMLClipboardType(type);
164 if (!cocoaType.isEmpty())
165 platformStrategies()->pasteboardStrategy()->setStringForType("", cocoaTy pe, m_pasteboardName);
166 }
167
168 void ClipboardMac::clearAllData()
169 {
170 if (!canWriteData())
171 return;
172
173 // note NSPasteboard enforces changeCount itself on writing - can't write if not the owner
174
175 Pasteboard pasteboard(m_pasteboardName);
176 pasteboard.clear();
177 }
178
179 static Vector<String> absoluteURLsFromPasteboardFilenames(const String& pasteboa rdName, bool onlyFirstURL = false)
180 {
181 Vector<String> fileList;
182 platformStrategies()->pasteboardStrategy()->getPathnamesForType(fileList, St ring(NSFilenamesPboardType), pasteboardName);
183
184 if (fileList.isEmpty())
185 return fileList;
186
187 size_t count = onlyFirstURL ? 1 : fileList.size();
188 Vector<String> urls;
189 for (size_t i = 0; i < count; i++) {
190 NSURL *url = [NSURL fileURLWithPath:fileList[i]];
191 urls.append(String([url absoluteString]));
192 }
193 return urls;
194 }
195
196 static Vector<String> absoluteURLsFromPasteboard(const String& pasteboardName, b ool onlyFirstURL = false)
197 {
198 // NOTE: We must always check [availableTypes containsObject:] before access ing pasteboard data
199 // or CoreFoundation will printf when there is not data of the corresponding type.
200 Vector<String> availableTypes;
201 Vector<String> absoluteURLs;
202 platformStrategies()->pasteboardStrategy()->getTypes(availableTypes, pastebo ardName);
203
204 // Try NSFilenamesPboardType because it contains a list
205 if (availableTypes.contains(String(NSFilenamesPboardType))) {
206 absoluteURLs = absoluteURLsFromPasteboardFilenames(pasteboardName, onlyF irstURL);
207 if (!absoluteURLs.isEmpty())
208 return absoluteURLs;
209 }
210
211 // Fallback to NSURLPboardType (which is a single URL)
212 if (availableTypes.contains(String(NSURLPboardType))) {
213 absoluteURLs.append(platformStrategies()->pasteboardStrategy()->stringFo rType(String(NSURLPboardType), pasteboardName));
214 return absoluteURLs;
215 }
216
217 // No file paths on the pasteboard, return nil
218 return Vector<String>();
219 }
220
221 String ClipboardMac::getData(const String& type) const
222 {
223 if (!canReadData() || m_clipboardContents == DragAndDropFiles)
224 return String();
225
226 const String& cocoaType = cocoaTypeFromHTMLClipboardType(type);
227 String cocoaValue;
228
229 // Grab the value off the pasteboard corresponding to the cocoaType
230 if (cocoaType == String(NSURLPboardType)) {
231 // "url" and "text/url-list" both map to NSURLPboardType in cocoaTypeFro mHTMLClipboardType(), "url" only wants the first URL
232 bool onlyFirstURL = (equalIgnoringCase(type, "url"));
233 Vector<String> absoluteURLs = absoluteURLsFromPasteboard(m_pasteboardNam e, onlyFirstURL);
234 for (size_t i = 0; i < absoluteURLs.size(); i++)
235 cocoaValue = i ? "\n" + absoluteURLs[i]: absoluteURLs[i];
236 } else if (cocoaType == String(NSStringPboardType))
237 cocoaValue = [platformStrategies()->pasteboardStrategy()->stringForType( cocoaType, m_pasteboardName) precomposedStringWithCanonicalMapping];
238 else if (!cocoaType.isEmpty())
239 cocoaValue = platformStrategies()->pasteboardStrategy()->stringForType(c ocoaType, m_pasteboardName);
240
241 // Enforce changeCount ourselves for security. We check after reading inste ad of before to be
242 // sure it doesn't change between our testing the change count and accessing the data.
243 if (!cocoaValue.isEmpty() && m_changeCount == platformStrategies()->pasteboa rdStrategy()->changeCount(m_pasteboardName)) {
244 return cocoaValue;
245 }
246
247 return String();
248 }
249
250 bool ClipboardMac::setData(const String &type, const String &data)
251 {
252 if (!canWriteData() || m_clipboardContents == DragAndDropFiles)
253 return false;
254 // note NSPasteboard enforces changeCount itself on writing - can't write if not the owner
255
256 const String& cocoaType = cocoaTypeFromHTMLClipboardType(type);
257 String cocoaData = data;
258
259 if (cocoaType == String(NSURLPboardType) || cocoaType == String(kUTTypeFileU RL)) {
260 NSURL *url = [NSURL URLWithString:cocoaData];
261 if ([url isFileURL])
262 return false;
263
264 Vector<String> types;
265 types.append(cocoaType);
266 platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboard Name);
267 platformStrategies()->pasteboardStrategy()->setStringForType(cocoaData, cocoaType, m_pasteboardName);
268
269 return true;
270 }
271
272 if (!cocoaType.isEmpty()) {
273 // everything else we know of goes on the pboard as a string
274 Vector<String> types;
275 types.append(cocoaType);
276 platformStrategies()->pasteboardStrategy()->addTypes(types, m_pasteboard Name);
277 platformStrategies()->pasteboardStrategy()->setStringForType(cocoaData, cocoaType, m_pasteboardName);
278 return true;
279 }
280
281 return false;
282 }
283
284 ListHashSet<String> ClipboardMac::types() const
285 {
286 if (!canReadTypes())
287 return ListHashSet<String>();
288
289 Vector<String> types;
290 platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName );
291
292 // Enforce changeCount ourselves for security. We check after reading inste ad of before to be
293 // sure it doesn't change between our testing the change count and accessing the data.
294 if (m_changeCount != platformStrategies()->pasteboardStrategy()->changeCount (m_pasteboardName))
295 return ListHashSet<String>();
296
297 ListHashSet<String> result;
298 // FIXME: This loop could be split into two stages. One which adds all the H TML5 specified types
299 // and a second which adds all the extra types from the cocoa clipboard (whi ch is Mac-only behavior).
300 for (size_t i = 0; i < types.size(); i++) {
301 if (types[i] == "NeXT plain ascii pasteboard type")
302 continue; // skip this ancient type that gets auto-supplied by som e system conversion
303
304 addHTMLClipboardTypesForCocoaType(result, types[i], m_pasteboardName);
305 }
306
307 return result;
308 }
309
310 // FIXME: We could cache the computed fileList if necessary
311 // Currently each access gets a new copy, setData() modifications to the
312 // clipboard are not reflected in any FileList objects the page has accessed and stored
313 PassRefPtr<FileList> ClipboardMac::files() const
314 {
315 if (!canReadData() || m_clipboardContents == DragAndDropData)
316 return FileList::create();
317
318 Vector<String> absoluteURLs = absoluteURLsFromPasteboardFilenames(m_pasteboa rdName);
319
320 RefPtr<FileList> fileList = FileList::create();
321 for (size_t i = 0; i < absoluteURLs.size(); i++) {
322 NSURL *absoluteURL = [NSURL URLWithString:absoluteURLs[i]];
323 ASSERT([absoluteURL isFileURL]);
324 fileList->append(File::create([absoluteURL path], File::AllContentTypes) );
325 }
326 return fileList.release(); // We will always return a FileList, sometimes em pty
327 }
328
329 // The rest of these getters don't really have any impact on security, so for no w make no checks
330
331 void ClipboardMac::setDragImage(CachedImage* img, const IntPoint &loc)
332 {
333 setDragImage(img, 0, loc);
334 }
335
336 void ClipboardMac::setDragImageElement(Node *node, const IntPoint &loc)
337 {
338 setDragImage(0, node, loc);
339 }
340
341 void ClipboardMac::setDragImage(CachedImage* image, Node *node, const IntPoint & loc)
342 {
343 if (canSetDragImage()) {
344 if (m_dragImage)
345 m_dragImage->removeClient(this);
346 m_dragImage = image;
347 if (m_dragImage)
348 m_dragImage->addClient(this);
349
350 m_dragLoc = loc;
351 m_dragImageElement = node;
352
353 if (dragStarted() && m_changeCount == platformStrategies()->pasteboardSt rategy()->changeCount(m_pasteboardName)) {
354 NSPoint cocoaLoc;
355 NSImage* cocoaImage = dragNSImage(cocoaLoc);
356 if (cocoaImage) {
357 // Dashboard wants to be able to set the drag image during dragg ing, but Cocoa does not allow this.
358 // Instead we must drop down to the CoreGraphics API.
359 wkSetDragImage(cocoaImage, cocoaLoc);
360
361 // Hack: We must post an event to wake up the NSDragManager, whi ch is sitting in a nextEvent call
362 // up the stack from us because the CoreFoundation drag manager does not use the run loop by itself.
363 // This is the most innocuous event to use, per Kristen Forster.
364 NSEvent* ev = [NSEvent mouseEventWithType:NSMouseMoved location: NSZeroPoint
365 modifierFlags:0 timestamp:0 windowNumber:0 context:nil event Number:0 clickCount:0 pressure:0];
366 [NSApp postEvent:ev atStart:YES];
367 }
368 }
369 // Else either 1) we haven't started dragging yet, so we rely on the par t to install this drag image
370 // as part of getting the drag kicked off, or 2) Someone kept a ref to t he clipboard and is trying to
371 // set the image way too late.
372 }
373 }
374
375 void ClipboardMac::writeRange(Range* range, Frame* frame)
376 {
377 ASSERT(range);
378 ASSERT(frame);
379 Pasteboard pasteboard(m_pasteboardName);
380 pasteboard.writeSelection(range, frame->editor()->smartInsertDeleteEnabled() && frame->selection()->granularity() == WordGranularity, frame, IncludeImageAlt TextForClipboard);
381 }
382
383 void ClipboardMac::writePlainText(const String& text)
384 {
385 Pasteboard pasteboard(m_pasteboardName);
386 pasteboard.writePlainText(text, Pasteboard::CannotSmartReplace);
387 }
388
389 void ClipboardMac::writeURL(const KURL& url, const String& title, Frame* frame)
390 {
391 ASSERT(frame);
392 ASSERT(m_pasteboardName);
393 Pasteboard pasteboard(m_pasteboardName);
394 pasteboard.writeURL(url, title, frame);
395 }
396
397 #if ENABLE(DRAG_SUPPORT)
398 void ClipboardMac::declareAndWriteDragImage(Element* element, const KURL& url, c onst String& title, Frame* frame)
399 {
400 ASSERT(frame);
401 if (Page* page = frame->page())
402 page->dragController()->client()->declareAndWriteDragImage(m_pasteboardN ame, kit(element), url, title, frame);
403 }
404 #endif // ENABLE(DRAG_SUPPORT)
405
406 DragImageRef ClipboardMac::createDragImage(IntPoint& loc) const
407 {
408 NSPoint nsloc = NSMakePoint(loc.x(), loc.y());
409 DragImageRef result = dragNSImage(nsloc);
410 loc = (IntPoint)nsloc;
411 return result;
412 }
413
414 NSImage *ClipboardMac::dragNSImage(NSPoint& loc) const
415 {
416 NSImage *result = nil;
417 if (m_dragImageElement) {
418 if (m_frame) {
419 NSRect imageRect;
420 NSRect elementRect;
421 result = m_frame->snapshotDragImage(m_dragImageElement.get(), &image Rect, &elementRect);
422 // Client specifies point relative to element, not the whole image, which may include child
423 // layers spread out all over the place.
424 loc.x = elementRect.origin.x - imageRect.origin.x + m_dragLoc.x();
425 loc.y = elementRect.origin.y - imageRect.origin.y + m_dragLoc.y();
426 loc.y = imageRect.size.height - loc.y;
427 }
428 } else if (m_dragImage) {
429 result = m_dragImage->image()->getNSImage();
430
431 loc = m_dragLoc;
432 loc.y = [result size].height - loc.y;
433 }
434 return result;
435 }
436
437 }
OLDNEW
« no previous file with comments | « Source/WebCore/platform/mac/ClipboardMac.h ('k') | Source/WebCore/platform/mac/ContentFilterMac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698