841b24f63910454e1619ce349f73a96e6e492f18
[WebKit-https.git] / Source / WebCore / platform / mac / PasteboardMac.mm
1 /*
2  * Copyright (C) 2006 Apple Computer, 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 "Pasteboard.h"
28
29 #import "CachedResource.h"
30 #import "ClipboardMac.h"
31 #import "DOMRangeInternal.h"
32 #import "Document.h"
33 #import "DocumentFragment.h"
34 #import "DocumentLoader.h"
35 #import "Editor.h"
36 #import "EditorClient.h"
37 #import "ExceptionCodePlaceholder.h"
38 #import "Frame.h"
39 #import "FrameView.h"
40 #import "FrameLoaderClient.h"
41 #import "HitTestResult.h"
42 #import "HTMLAnchorElement.h"
43 #import "HTMLConverter.h"
44 #import "htmlediting.h"
45 #import "HTMLNames.h"
46 #import "Image.h"
47 #import "KURL.h"
48 #import "LegacyWebArchive.h"
49 #import "LoaderNSURLExtras.h"
50 #import "MIMETypeRegistry.h"
51 #import "Page.h"
52 #import "RenderImage.h"
53 #import "ResourceBuffer.h"
54 #import "Text.h"
55 #import "WebCoreNSStringExtras.h"
56 #import "WebNSAttributedStringExtras.h"
57 #import "markup.h"
58 #import <wtf/StdLibExtras.h>
59 #import <wtf/RetainPtr.h>
60 #import <wtf/UnusedParam.h>
61 #import <wtf/text/StringBuilder.h>
62 #import <wtf/unicode/CharacterNames.h>
63
64 #if USE(PLATFORM_STRATEGIES)
65 #include "PasteboardStrategy.h"
66 #include "PlatformStrategies.h"
67 #endif
68
69 namespace WebCore {
70
71 // FIXME: It's not great to have these both here and in WebKit.
72 const char* WebArchivePboardType = "Apple Web Archive pasteboard type";
73 const char* WebSmartPastePboardType = "NeXT smart paste pasteboard type";
74 const char* WebURLNamePboardType = "public.url-name";
75 const char* WebURLPboardType = "public.url";
76 const char* WebURLsWithTitlesPboardType = "WebURLsWithTitlesPboardType";
77
78 static Vector<String> selectionPasteboardTypes(bool canSmartCopyOrDelete, bool selectionContainsAttachments)
79 {
80     Vector<String> types;
81     if (canSmartCopyOrDelete)
82         types.append(WebSmartPastePboardType);
83     types.append(WebArchivePboardType);
84     if (selectionContainsAttachments)
85         types.append(String(NSRTFDPboardType));
86     types.append(String(NSRTFPboardType));
87     types.append(String(NSStringPboardType));
88
89     return types;
90 }
91
92 static const Vector<String> writableTypesForURL()
93 {
94     Vector<String> types;
95     
96     types.append(WebURLsWithTitlesPboardType);
97     types.append(String(NSURLPboardType));
98     types.append(WebURLPboardType);
99     types.append(WebURLNamePboardType);
100     types.append(String(NSStringPboardType));        
101     return types;
102 }
103
104 static inline Vector<String> createWritableTypesForImage()
105 {
106     Vector<String> types;
107     
108     types.append(String(NSTIFFPboardType));
109     types.append(writableTypesForURL());
110     types.append(String(NSRTFDPboardType));
111     return types;
112 }
113
114 static Vector<String> writableTypesForImage()
115 {
116     Vector<String> types;
117     types.append(createWritableTypesForImage());
118     return types;
119 }
120
121 Pasteboard* Pasteboard::generalPasteboard() 
122 {
123     static Pasteboard* pasteboard = new Pasteboard(NSGeneralPboard);
124     return pasteboard;
125 }
126
127 Pasteboard::Pasteboard(const String& pasteboardName)
128     : m_pasteboardName(pasteboardName)
129 {
130     ASSERT(pasteboardName);
131 }
132
133 void Pasteboard::clear()
134 {
135     platformStrategies()->pasteboardStrategy()->setTypes(Vector<String>(), m_pasteboardName);
136 }
137
138 String Pasteboard::getStringSelection(Frame* frame)
139 {
140     String text = frame->editor()->selectedText();
141     text.replace(noBreakSpace, ' ');
142     return text;
143 }
144
145 PassRefPtr<SharedBuffer> Pasteboard::getDataSelection(Frame* frame, const String& pasteboardType)
146 {
147     if (pasteboardType == WebArchivePboardType) {
148         RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
149         RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
150         return SharedBuffer::wrapNSData((NSData *)data.get());
151     }
152
153     RefPtr<Range> range = frame->editor()->selectedRange();
154     Node* commonAncestor = range->commonAncestorContainer(IGNORE_EXCEPTION);
155     ASSERT(commonAncestor);
156     Node* enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(commonAncestor), HTMLNames::aTag);
157     if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(range->startPosition().anchorNode()), range->startPosition()) >= 0)
158         range->setStart(enclosingAnchor, 0, IGNORE_EXCEPTION);
159     
160     NSAttributedString* attributedString = nil;
161     RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(range.get())]);
162     if (converter)
163         attributedString = [converter.get() attributedString];
164     
165     if (pasteboardType == String(NSRTFDPboardType)) {
166         NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
167         return SharedBuffer::wrapNSData((NSData *)RTFDData);
168     }
169     if (pasteboardType == String(NSRTFPboardType)) {
170         if ([attributedString containsAttachments])
171             attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
172         NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
173         return SharedBuffer::wrapNSData((NSData *)RTFData);
174     }
175     return 0;
176 }
177
178 void Pasteboard::writeSelectionForTypes(const Vector<String>& pasteboardTypes, bool canSmartCopyOrDelete, Frame* frame)
179 {
180     NSAttributedString* attributedString = nil;
181     RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(frame->editor()->selectedRange().get())]);
182     if (converter)
183         attributedString = [converter.get() attributedString];
184     
185     Vector<String> types = !pasteboardTypes.isEmpty() ? pasteboardTypes : selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
186
187     Vector<String> clientTypes;
188     Vector<RefPtr<SharedBuffer> > clientData;
189     frame->editor()->client()->getClientPasteboardDataForRange(frame->editor()->selectedRange().get(), clientTypes, clientData);
190     types.append(clientTypes);
191
192     platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
193     frame->editor()->client()->didSetSelectionTypesForPasteboard();
194
195     for (size_t i = 0; i < clientTypes.size(); ++i)
196         platformStrategies()->pasteboardStrategy()->setBufferForType(clientData[i], clientTypes[i], m_pasteboardName);
197
198     // Put HTML on the pasteboard.
199     if (types.contains(WebArchivePboardType))
200         platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, WebArchivePboardType), WebArchivePboardType, m_pasteboardName);
201     
202     // Put the attributed string on the pasteboard (RTF/RTFD format).
203     if (types.contains(String(NSRTFDPboardType)))
204         platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, NSRTFDPboardType), NSRTFDPboardType, m_pasteboardName);
205
206     if (types.contains(String(NSRTFPboardType)))
207         platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, NSRTFPboardType), NSRTFPboardType, m_pasteboardName);
208     
209     // Put plain string on the pasteboard.
210     if (types.contains(String(NSStringPboardType)))
211         platformStrategies()->pasteboardStrategy()->setStringForType(getStringSelection(frame), NSStringPboardType, m_pasteboardName);
212     
213     if (types.contains(WebSmartPastePboardType))
214         platformStrategies()->pasteboardStrategy()->setBufferForType(0, WebSmartPastePboardType, m_pasteboardName);
215 }
216
217 void Pasteboard::writePlainText(const String& text, SmartReplaceOption smartReplaceOption)
218 {
219     Vector<String> types;
220     types.append(NSStringPboardType);
221     if (smartReplaceOption == CanSmartReplace)
222         types.append(WebSmartPastePboardType);
223
224     platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
225     platformStrategies()->pasteboardStrategy()->setStringForType(text, NSStringPboardType, m_pasteboardName);
226     if (smartReplaceOption == CanSmartReplace)
227         platformStrategies()->pasteboardStrategy()->setBufferForType(0, WebSmartPastePboardType, m_pasteboardName);
228 }
229     
230 void Pasteboard::writeSelection(Range*, bool canSmartCopyOrDelete, Frame* frame)
231 {
232     writeSelectionForTypes(Vector<String>(), canSmartCopyOrDelete, frame);
233 }
234
235 static void writeURLForTypes(const Vector<String>& types, const String& pasteboardName, const KURL& url, const String& titleStr, Frame* frame)
236 {
237     platformStrategies()->pasteboardStrategy()->setTypes(types, pasteboardName);
238     
239     ASSERT(!url.isEmpty());
240     
241     NSURL *cocoaURL = url;
242     NSString *userVisibleString = frame->editor()->client()->userVisibleString(cocoaURL);
243     
244     NSString *title = (NSString*)titleStr;
245     if ([title length] == 0) {
246         title = [[cocoaURL path] lastPathComponent];
247         if ([title length] == 0)
248             title = userVisibleString;
249     }
250     if (types.contains(WebURLsWithTitlesPboardType)) {
251         Vector<String> paths;
252         paths.append([cocoaURL absoluteString]);
253         paths.append(titleStr.stripWhiteSpace());
254         platformStrategies()->pasteboardStrategy()->setPathnamesForType(paths, WebURLsWithTitlesPboardType, pasteboardName);
255     }
256     if (types.contains(String(NSURLPboardType)))
257         platformStrategies()->pasteboardStrategy()->setStringForType([cocoaURL absoluteString], NSURLPboardType, pasteboardName);
258     if (types.contains(WebURLPboardType))
259         platformStrategies()->pasteboardStrategy()->setStringForType(userVisibleString, WebURLPboardType, pasteboardName);
260     if (types.contains(WebURLNamePboardType))
261         platformStrategies()->pasteboardStrategy()->setStringForType(title, WebURLNamePboardType, pasteboardName);
262     if (types.contains(String(NSStringPboardType)))
263         platformStrategies()->pasteboardStrategy()->setStringForType(userVisibleString, NSStringPboardType, pasteboardName);
264 }
265     
266 void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
267 {
268     writeURLForTypes(writableTypesForURL(), m_pasteboardName, url, titleStr, frame);
269 }
270
271 static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url)
272 {
273     ResourceBuffer* coreData = resource->resourceBuffer();
274     NSData *data = [[[NSData alloc] initWithBytes:coreData->data() length:coreData->size()] autorelease];
275     NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];
276     String coreMIMEType = resource->response().mimeType();
277     NSString *MIMEType = nil;
278     if (!coreMIMEType.isNull())
279         MIMEType = coreMIMEType;
280     [wrapper setPreferredFilename:suggestedFilenameWithMIMEType(url, MIMEType)];
281     return wrapper;
282 }
283
284 static void writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper, const String& pasteboardName)
285 {
286     NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper];
287     
288     NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment];
289     [attachment release];
290     
291     NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil];
292     if (RTFDData)
293         platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData(RTFDData).get(), NSRTFDPboardType, pasteboardName);
294 }
295
296 void Pasteboard::writeImage(Node* node, const KURL& url, const String& title)
297 {
298     ASSERT(node);
299
300     if (!(node->renderer() && node->renderer()->isImage()))
301         return;
302
303     NSURL *cocoaURL = url;
304     ASSERT(cocoaURL);
305
306     RenderImage* renderer = toRenderImage(node->renderer());
307     CachedImage* cachedImage = renderer->cachedImage();
308     if (!cachedImage || cachedImage->errorOccurred())
309         return;
310
311     writeURLForTypes(writableTypesForImage(), m_pasteboardName, cocoaURL, nsStringNilIfEmpty(title), node->document()->frame());
312     
313     Image* image = cachedImage->imageForRenderer(renderer);
314     if (!image)
315         return;
316     NSData *imageData = (NSData *)[image->getNSImage() TIFFRepresentation];
317     if (!imageData)
318         return;
319     platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData(imageData), NSTIFFPboardType, m_pasteboardName);
320
321     String MIMEType = cachedImage->response().mimeType();
322     ASSERT(MIMETypeRegistry::isSupportedImageResourceMIMEType(MIMEType));
323
324     writeFileWrapperAsRTFDAttachment(fileWrapperForImage(cachedImage, cocoaURL), m_pasteboardName);
325 }
326
327 void Pasteboard::writeClipboard(Clipboard* clipboard)
328 {
329     platformStrategies()->pasteboardStrategy()->copy(static_cast<ClipboardMac*>(clipboard)->pasteboardName(), m_pasteboardName);
330 }
331
332 bool Pasteboard::canSmartReplace()
333 {
334     Vector<String> types;
335     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
336     return types.contains(WebSmartPastePboardType);
337 }
338
339 String Pasteboard::plainText(Frame* frame)
340 {
341     Vector<String> types;
342     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
343     
344     if (types.contains(String(NSStringPboardType)))
345         return [(NSString *)platformStrategies()->pasteboardStrategy()->stringForType(NSStringPboardType, m_pasteboardName) precomposedStringWithCanonicalMapping];
346     
347     NSAttributedString *attributedString = nil;
348     NSString *string;
349
350     if (types.contains(String(NSRTFDPboardType))) {
351         RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFDPboardType, m_pasteboardName);
352         if (data)
353             attributedString = [[NSAttributedString alloc] initWithRTFD:[data->createNSData() autorelease] documentAttributes:NULL];
354     }
355     if (attributedString == nil && types.contains(String(NSRTFPboardType))) {
356         RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFPboardType, m_pasteboardName);
357         if (data)
358             attributedString = [[NSAttributedString alloc] initWithRTF:[data->createNSData() autorelease] documentAttributes:NULL];
359     }
360     if (attributedString != nil) {
361         string = [[attributedString string] precomposedStringWithCanonicalMapping];
362         [attributedString release];
363         return string;
364     }
365     
366     if (types.contains(String(NSFilenamesPboardType))) {
367         Vector<String> pathnames;
368         platformStrategies()->pasteboardStrategy()->getPathnamesForType(pathnames, NSFilenamesPboardType, m_pasteboardName);
369         StringBuilder builder;
370         for (size_t i = 0; i < pathnames.size(); i++)
371             builder.append(i ? "\n" + pathnames[i] : pathnames[i]);
372         string = builder.toString();
373         return [string precomposedStringWithCanonicalMapping];
374     }
375     
376     string = platformStrategies()->pasteboardStrategy()->stringForType(NSURLPboardType, m_pasteboardName);
377     if ([string length]) {
378         // FIXME: using the editorClient to call into webkit, for now, since 
379         // calling _web_userVisibleString from WebCore involves migrating a sizable web of 
380         // helper code that should either be done in a separate patch or figured out in another way.
381         string = frame->editor()->client()->userVisibleString([NSURL URLWithString:string]);
382         if ([string length] > 0)
383             return [string precomposedStringWithCanonicalMapping];
384     }
385
386     
387     return String(); 
388 }
389     
390 static PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource)
391 {
392     if (!resource)
393         return 0;
394     
395     if (DocumentLoader* loader = frame->loader()->documentLoader())
396         loader->addArchiveResource(resource.get());
397
398     RefPtr<Element> imageElement = frame->document()->createElement(HTMLNames::imgTag, false);
399     if (!imageElement)
400         return 0;
401
402     NSURL *URL = resource->url();
403     imageElement->setAttribute(HTMLNames::srcAttr, [URL isFileURL] ? [URL absoluteString] : resource->url());
404     RefPtr<DocumentFragment> fragment = frame->document()->createDocumentFragment();
405     if (fragment) {
406         fragment->appendChild(imageElement, IGNORE_EXCEPTION);
407         return fragment.release();
408     }
409     return 0;
410 }
411
412 static PassRefPtr<DocumentFragment> documentFragmentWithRTF(Frame* frame, NSString *pasteboardType,const String& pastebordName)
413 {
414     if (!frame || !frame->document() || !frame->document()->isHTMLDocument())
415         return 0;
416
417     NSAttributedString *string = nil;
418     if (pasteboardType == NSRTFDPboardType) {
419         RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFDPboardType, pastebordName);
420         if (data)
421             string = [[NSAttributedString alloc] initWithRTFD:[data->createNSData() autorelease] documentAttributes:NULL];
422     }
423     if (string == nil) {
424         RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFPboardType, pastebordName);
425         if (data)
426             string = [[NSAttributedString alloc] initWithRTF:[data->createNSData() autorelease] documentAttributes:NULL];
427     }
428     if (string == nil)
429         return nil;
430
431     bool wasDeferringCallbacks = frame->page()->defersLoading();
432     if (!wasDeferringCallbacks)
433         frame->page()->setDefersLoading(true);
434
435     Vector<RefPtr<ArchiveResource> > resources;
436     RefPtr<DocumentFragment> fragment = frame->editor()->client()->documentFragmentFromAttributedString(string, resources);
437
438     size_t size = resources.size();
439     if (size) {
440         DocumentLoader* loader = frame->loader()->documentLoader();
441         for (size_t i = 0; i < size; ++i)
442             loader->addArchiveResource(resources[i]);    
443     }
444
445     if (!wasDeferringCallbacks)
446         frame->page()->setDefersLoading(false);
447
448     [string release];
449     return fragment.release();
450 }
451
452 #define WebDataProtocolScheme @"webkit-fake-url"
453
454 static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
455 {
456     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
457     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
458     CFRelease(UUIDRef);
459     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", WebDataProtocolScheme, UUIDString, relativePart]];
460     CFRelease(UUIDString);
461
462     return URL;
463 }
464
465 static PassRefPtr<DocumentFragment> fragmentFromWebArchive(Frame* frame, PassRefPtr<LegacyWebArchive> coreArchive)
466 {
467     RefPtr<ArchiveResource> mainResource = coreArchive->mainResource();
468     if (!mainResource)
469         return 0;
470
471     NSString *MIMEType = mainResource->mimeType();
472     if (!frame || !frame->document())
473         return 0;
474
475     if (frame->loader()->client()->canShowMIMETypeAsHTML(MIMEType)) {
476         RetainPtr<NSString> markupString(AdoptNS, [[NSString alloc] initWithData:[mainResource->data()->createNSData() autorelease] encoding:NSUTF8StringEncoding]);
477         // FIXME: seems poor form to do this as a side effect of getting a document fragment
478         if (DocumentLoader* loader = frame->loader()->documentLoader())
479             loader->addAllArchiveResources(coreArchive.get());
480         return createFragmentFromMarkup(frame->document(), markupString.get(), mainResource->url(), DisallowScriptingAndPluginContent);
481     }
482
483     if (MIMETypeRegistry::isSupportedImageMIMEType(MIMEType))
484         return documentFragmentWithImageResource(frame, mainResource);
485
486     return 0;
487 }
488
489 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText)
490 {
491     Vector<String> types;
492     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
493     RefPtr<DocumentFragment> fragment;
494     chosePlainText = false;
495
496     if (types.contains(WebArchivePboardType)) {
497         if (RefPtr<SharedBuffer> webArchiveBuffer = platformStrategies()->pasteboardStrategy()->bufferForType(WebArchivePboardType, m_pasteboardName)) {
498             if (RefPtr<LegacyWebArchive> coreArchive = LegacyWebArchive::create(KURL(), webArchiveBuffer.get())) {
499                 if ((fragment = fragmentFromWebArchive(frame, coreArchive)))
500                     return fragment.release();
501             }
502         }
503     }
504
505     if (types.contains(String(NSFilenamesPboardType))) {
506         Vector<String> paths;
507         platformStrategies()->pasteboardStrategy()->getPathnamesForType(paths, NSFilenamesPboardType, m_pasteboardName);
508         Vector< RefPtr<Node> > refNodesVector;
509         Vector<Node*> nodesVector;
510
511         for (size_t i = 0; i < paths.size(); i++) {
512             // Non-image file types; _web_userVisibleString is appropriate here because this will
513             // be pasted as visible text.
514             NSString *url = frame->editor()->client()->userVisibleString([NSURL fileURLWithPath:paths[i]]);
515             RefPtr<Node> textNode = frame->document()->createTextNode(url);
516             refNodesVector.append(textNode.get());
517             nodesVector.append(textNode.get());
518         }
519         fragment = createFragmentFromNodes(frame->document(), nodesVector);
520         if (fragment && fragment->firstChild())
521             return fragment.release();
522     }
523
524     if (types.contains(String(NSHTMLPboardType))) {
525         NSString *HTMLString = platformStrategies()->pasteboardStrategy()->stringForType(NSHTMLPboardType, m_pasteboardName);
526         // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
527         if ([HTMLString hasPrefix:@"Version:"]) {
528             NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
529             if (range.location != NSNotFound) {
530                 HTMLString = [HTMLString substringFromIndex:range.location];
531             }
532         }
533         if ([HTMLString length] != 0 &&
534             (fragment = createFragmentFromMarkup(frame->document(), HTMLString, "", DisallowScriptingAndPluginContent)))
535             return fragment.release();
536     }
537
538     if (types.contains(String(NSRTFDPboardType)) &&
539         (fragment = documentFragmentWithRTF(frame, NSRTFDPboardType, m_pasteboardName)))
540        return fragment.release();
541
542     if (types.contains(String(NSRTFPboardType)) &&
543         (fragment = documentFragmentWithRTF(frame, NSRTFPboardType, m_pasteboardName)))
544         return fragment.release();
545
546     if (types.contains(String(NSTIFFPboardType)) &&
547         (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(platformStrategies()->pasteboardStrategy()->bufferForType(NSTIFFPboardType, m_pasteboardName), uniqueURLWithRelativePart(@"image.tiff"), "image/tiff", "", ""))))
548         return fragment.release();
549
550     if (types.contains(String(NSPDFPboardType)) &&
551         (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(platformStrategies()->pasteboardStrategy()->bufferForType(NSPDFPboardType, m_pasteboardName).get(), uniqueURLWithRelativePart(@"application.pdf"), "application/pdf", "", ""))))
552         return fragment.release();
553
554     if (types.contains(String(kUTTypePNG)) &&
555         (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(platformStrategies()->pasteboardStrategy()->bufferForType(String(kUTTypePNG), m_pasteboardName), uniqueURLWithRelativePart(@"image.png"), "image/png", "", ""))))
556         return fragment.release();
557
558     if (types.contains(String(NSURLPboardType))) {
559         NSURL *URL = platformStrategies()->pasteboardStrategy()->url(m_pasteboardName);
560         Document* document = frame->document();
561         ASSERT(document);
562         if (!document)
563             return 0;
564         RefPtr<Element> anchor = document->createElement(HTMLNames::aTag, false);
565         NSString *URLString = [URL absoluteString]; // Original data is ASCII-only, so there is no need to precompose.
566         if ([URLString length] == 0)
567             return nil;
568         NSString *URLTitleString = [platformStrategies()->pasteboardStrategy()->stringForType(WebURLNamePboardType, m_pasteboardName) precomposedStringWithCanonicalMapping];
569         anchor->setAttribute(HTMLNames::hrefAttr, URLString);
570         anchor->appendChild(document->createTextNode(URLTitleString), IGNORE_EXCEPTION);
571         fragment = document->createDocumentFragment();
572         if (fragment) {
573             fragment->appendChild(anchor, IGNORE_EXCEPTION);
574             return fragment.release();
575         }
576     }
577
578     if (allowPlainText && types.contains(String(NSStringPboardType))) {
579         chosePlainText = true;
580         fragment = createFragmentFromText(context.get(), [platformStrategies()->pasteboardStrategy()->stringForType(NSStringPboardType, m_pasteboardName) precomposedStringWithCanonicalMapping]);
581         return fragment.release();
582     }
583
584     return 0;
585 }
586
587 }