Unreviewed, rolling out r107435.
[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 "Frame.h"
38 #import "FrameView.h"
39 #import "FrameLoaderClient.h"
40 #import "HitTestResult.h"
41 #import "HTMLAnchorElement.h"
42 #import "HTMLConverter.h"
43 #import "htmlediting.h"
44 #import "HTMLNames.h"
45 #import "Image.h"
46 #import "KURL.h"
47 #import "LegacyWebArchive.h"
48 #import "LoaderNSURLExtras.h"
49 #import "MIMETypeRegistry.h"
50 #import "Page.h"
51 #import "RenderImage.h"
52 #import "Text.h"
53 #import "WebCoreNSStringExtras.h"
54 #import "WebNSAttributedStringExtras.h"
55 #import "markup.h"
56 #import <wtf/StdLibExtras.h>
57 #import <wtf/RetainPtr.h>
58 #import <wtf/UnusedParam.h>
59 #import <wtf/unicode/CharacterNames.h>
60
61 @interface NSAttributedString (AppKitSecretsIKnowAbout)
62 - (id)_initWithDOMRange:(DOMRange *)domRange;
63 @end
64 namespace WebCore {
65
66 // FIXME: It's not great to have these both here and in WebKit.
67 NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type";
68 NSString *WebSmartPastePboardType = @"NeXT smart paste pasteboard type";
69 NSString *WebURLNamePboardType = @"public.url-name";
70 NSString *WebURLPboardType = @"public.url";
71 NSString *WebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";
72
73 static NSArray* selectionPasteboardTypes(bool canSmartCopyOrDelete, bool selectionContainsAttachments)
74 {
75     if (selectionContainsAttachments) {
76         if (canSmartCopyOrDelete)
77             return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
78         else
79             return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
80     } else { // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
81         if (canSmartCopyOrDelete)
82             return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
83         else
84             return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
85     }
86 }
87
88 static NSArray* writableTypesForURL()
89 {
90     DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, ([[NSArray alloc] initWithObjects:
91             WebURLsWithTitlesPboardType,
92             NSURLPboardType,
93             WebURLPboardType,
94             WebURLNamePboardType,
95             NSStringPboardType,
96             nil]));
97     return types.get();
98 }
99
100 static inline NSArray* createWritableTypesForImage()
101 {
102     NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
103     [types addObjectsFromArray:writableTypesForURL()];
104     [types addObject:NSRTFDPboardType];
105     return types;
106 }
107
108 static NSArray* writableTypesForImage()
109 {
110     DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (createWritableTypesForImage()));
111     return types.get();
112 }
113
114 Pasteboard* Pasteboard::generalPasteboard() 
115 {
116     static Pasteboard* pasteboard = new Pasteboard(NSGeneralPboard);
117     return pasteboard;
118 }
119
120 Pasteboard::Pasteboard(const String& pasteboardName)
121     : m_pasteboard([NSPasteboard pasteboardWithName:pasteboardName])
122 {
123     ASSERT(pasteboardName);
124 }
125
126 void Pasteboard::clear()
127 {
128     [m_pasteboard.get() declareTypes:[NSArray array] owner:nil];
129 }
130
131 void Pasteboard::writeSelectionForTypes(NSArray* pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
132 {
133     if (!WebArchivePboardType)
134         Pasteboard::generalPasteboard(); // Initializes pasteboard types.
135     ASSERT(selectedRange);
136     
137     // If the selection is at the beginning of content inside an anchor tag
138     // we move the selection start to include the anchor.
139     // This way the attributed string will contain the url attribute as well.
140     // See <rdar://problem/9084267>.
141     ExceptionCode ec;
142     Node* commonAncestor = selectedRange->commonAncestorContainer(ec);
143     ASSERT(commonAncestor);
144     Node* enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(commonAncestor), HTMLNames::aTag);
145     if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(selectedRange->startPosition().anchorNode()), selectedRange->startPosition()) >= 0)
146         selectedRange->setStart(enclosingAnchor, 0, ec);
147
148     // Using different API for WebKit and WebKit2.
149     NSAttributedString *attributedString = nil;
150     if (frame->view()->platformWidget())
151         attributedString = [[[NSAttributedString alloc] _initWithDOMRange:kit(selectedRange)] autorelease];
152 #ifndef BUILDING_ON_LEOPARD
153     else {
154         // In WebKit2 we are using a different way to create the NSAttributedString from the DOMrange that doesn't require access to the WebView.
155         RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(selectedRange)]);
156         if (converter)
157             attributedString = [converter.get() attributedString];
158     }
159 #endif
160
161     NSArray *types = pasteboardTypes ? pasteboardTypes : selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
162     [m_pasteboard.get() declareTypes:types owner:nil];
163     frame->editor()->client()->didSetSelectionTypesForPasteboard();
164     
165     // Put HTML on the pasteboard.
166     if ([types containsObject:WebArchivePboardType]) {
167         RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
168         RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
169         [m_pasteboard.get() setData:(NSData *)data.get() forType:WebArchivePboardType];
170     }
171     
172     // Put the attributed string on the pasteboard (RTF/RTFD format).
173     if ([types containsObject:NSRTFDPboardType]) {
174         NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
175         [m_pasteboard.get() setData:RTFDData forType:NSRTFDPboardType];
176     }
177     if ([types containsObject:NSRTFPboardType]) {
178         if ([attributedString containsAttachments])
179             attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
180         NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
181         [m_pasteboard.get() setData:RTFData forType:NSRTFPboardType];
182     }
183     
184     // Put plain string on the pasteboard.
185     if ([types containsObject:NSStringPboardType]) {
186         // Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
187         // and because HTML forces you to do this any time you want two spaces in a row.
188         String text = frame->editor()->selectedText();
189         NSMutableString *s = [[[(NSString*)text copy] autorelease] mutableCopy];
190         
191         NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
192         [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
193         [m_pasteboard.get() setString:s forType:NSStringPboardType];
194         [s release];
195     }
196     
197     if ([types containsObject:WebSmartPastePboardType]) {
198         [m_pasteboard.get() setData:nil forType:WebSmartPastePboardType];
199     }
200 }
201
202 void Pasteboard::writePlainText(const String& text)
203 {
204     [m_pasteboard.get() declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
205     [m_pasteboard.get() setString:text forType:NSStringPboardType];
206 }
207     
208 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
209 {
210     writeSelectionForTypes(nil, selectedRange, canSmartCopyOrDelete, frame);
211 }
212
213 static void writeURLForTypes(NSArray* types, NSPasteboard* pasteboard, const KURL& url, const String& titleStr, Frame* frame)
214 {
215     [pasteboard declareTypes:types owner:nil];
216     
217     ASSERT(!url.isEmpty());
218     
219     NSURL *cocoaURL = url;
220     NSString *userVisibleString = frame->editor()->client()->userVisibleString(cocoaURL);
221     
222     NSString *title = (NSString*)titleStr;
223     if ([title length] == 0) {
224         title = [[cocoaURL path] lastPathComponent];
225         if ([title length] == 0)
226             title = userVisibleString;
227     }
228         
229     if ([types containsObject:WebURLsWithTitlesPboardType])
230         [pasteboard setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString], 
231                                      [NSArray arrayWithObject:(NSString*)titleStr.stripWhiteSpace()], 
232                                      nil]
233                             forType:WebURLsWithTitlesPboardType];
234     if ([types containsObject:NSURLPboardType])
235         [cocoaURL writeToPasteboard:pasteboard];
236     if ([types containsObject:WebURLPboardType])
237         [pasteboard setString:userVisibleString forType:WebURLPboardType];
238     if ([types containsObject:WebURLNamePboardType])
239         [pasteboard setString:title forType:WebURLNamePboardType];
240     if ([types containsObject:NSStringPboardType])
241         [pasteboard setString:userVisibleString forType:NSStringPboardType];
242 }
243     
244 void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
245 {
246     writeURLForTypes(writableTypesForURL(), m_pasteboard.get(), url, titleStr, frame);
247 }
248
249 static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url)
250 {
251     SharedBuffer* coreData = resource->data();
252     NSData *data = [[[NSData alloc] initWithBytes:coreData->data() length:coreData->size()] autorelease];
253     NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];
254     String coreMIMEType = resource->response().mimeType();
255     NSString *MIMEType = nil;
256     if (!coreMIMEType.isNull())
257         MIMEType = coreMIMEType;
258     [wrapper setPreferredFilename:suggestedFilenameWithMIMEType(url, MIMEType)];
259     return wrapper;
260 }
261
262 static void writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper, NSPasteboard* pasteboard)
263 {
264     NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper];
265     
266     NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment];
267     [attachment release];
268     
269     NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil];
270     [pasteboard setData:RTFDData forType:NSRTFDPboardType];
271 }
272
273 void Pasteboard::writeImage(Node* node, const KURL& url, const String& title)
274 {
275     ASSERT(node);
276
277     if (!(node->renderer() && node->renderer()->isImage()))
278         return;
279
280     Frame* frame = node->document()->frame();
281
282     NSURL *cocoaURL = url;
283     ASSERT(cocoaURL);
284
285     RenderImage* renderer = toRenderImage(node->renderer());
286     CachedImage* cachedImage = renderer->cachedImage();
287     if (!cachedImage || cachedImage->errorOccurred())
288         return;
289
290     writeURLForTypes(writableTypesForImage(), m_pasteboard.get(), cocoaURL, nsStringNilIfEmpty(title), frame);
291     
292     Image* image = cachedImage->imageForRenderer(renderer);
293     ASSERT(image);
294     
295     [m_pasteboard.get() setData:[image->getNSImage() TIFFRepresentation] forType:NSTIFFPboardType];
296
297     String MIMEType = cachedImage->response().mimeType();
298     ASSERT(MIMETypeRegistry::isSupportedImageResourceMIMEType(MIMEType));
299
300     writeFileWrapperAsRTFDAttachment(fileWrapperForImage(cachedImage, cocoaURL), m_pasteboard.get());
301 }
302
303 void Pasteboard::writeClipboard(Clipboard* clipboard)
304 {
305     NSPasteboard* pasteboard = static_cast<ClipboardMac*>(clipboard)->pasteboard();
306     NSArray* types = [pasteboard types];
307
308     [m_pasteboard.get() addTypes:types owner:nil];
309     for (NSUInteger i = 0; i < [types count]; i++) {
310         NSString* type = [types objectAtIndex:i];
311         [m_pasteboard.get() setData:[pasteboard dataForType:type] forType:type];
312     }
313 }
314
315 bool Pasteboard::canSmartReplace()
316 {
317     return [[m_pasteboard.get() types] containsObject:WebSmartPastePboardType];
318 }
319
320 String Pasteboard::plainText(Frame* frame)
321 {
322     NSArray *types = [m_pasteboard.get() types];
323     
324     if ([types containsObject:NSStringPboardType])
325         return [[m_pasteboard.get() stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping];
326     
327     NSAttributedString *attributedString = nil;
328     NSString *string;
329
330     if ([types containsObject:NSRTFDPboardType])
331         attributedString = [[NSAttributedString alloc] initWithRTFD:[m_pasteboard.get() dataForType:NSRTFDPboardType] documentAttributes:NULL];
332     if (attributedString == nil && [types containsObject:NSRTFPboardType])
333         attributedString = [[NSAttributedString alloc] initWithRTF:[m_pasteboard.get() dataForType:NSRTFPboardType] documentAttributes:NULL];
334     if (attributedString != nil) {
335         string = [[attributedString string] precomposedStringWithCanonicalMapping];
336         [attributedString release];
337         return string;
338     }
339     
340     if ([types containsObject:NSFilenamesPboardType]) {
341         string = [[[m_pasteboard.get() propertyListForType:NSFilenamesPboardType] componentsJoinedByString:@"\n"] precomposedStringWithCanonicalMapping];
342         if (string != nil)
343             return string;
344     }
345     
346     
347     if (NSURL *url = [NSURL URLFromPasteboard:m_pasteboard.get()]) {
348         // FIXME: using the editorClient to call into webkit, for now, since 
349         // calling _web_userVisibleString from WebCore involves migrating a sizable web of 
350         // helper code that should either be done in a separate patch or figured out in another way.
351         string = frame->editor()->client()->userVisibleString(url);
352         if ([string length] > 0)
353             return [string precomposedStringWithCanonicalMapping];
354     }
355
356     
357     return String(); 
358 }
359     
360 static PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource)
361 {
362     if (DocumentLoader* loader = frame->loader()->documentLoader())
363         loader->addArchiveResource(resource.get());
364
365     RefPtr<Element> imageElement = frame->document()->createElement(HTMLNames::imgTag, false);
366     if (!imageElement)
367         return 0;
368
369     NSURL *URL = resource->url();
370     imageElement->setAttribute(HTMLNames::srcAttr, [URL isFileURL] ? [URL absoluteString] : resource->url());
371     RefPtr<DocumentFragment> fragment = frame->document()->createDocumentFragment();
372     if (fragment) {
373         ExceptionCode ec;
374         fragment->appendChild(imageElement, ec);
375         return fragment.release();       
376     }
377     return 0;
378 }
379
380 static PassRefPtr<DocumentFragment> documentFragmentWithRTF(Frame* frame, NSString *pasteboardType, NSPasteboard *pasteboard)
381 {
382     if (!frame || !frame->document() || !frame->document()->isHTMLDocument())
383         return 0;
384
385     NSAttributedString *string = nil;
386     if (pasteboardType == NSRTFDPboardType)
387         string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
388     if (string == nil)
389         string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
390     if (string == nil)
391         return nil;
392
393     bool wasDeferringCallbacks = frame->page()->defersLoading();
394     if (!wasDeferringCallbacks)
395         frame->page()->setDefersLoading(true);
396
397     Vector<RefPtr<ArchiveResource> > resources;
398     RefPtr<DocumentFragment> fragment = frame->editor()->client()->documentFragmentFromAttributedString(string, resources);
399
400     size_t size = resources.size();
401     if (size) {
402         DocumentLoader* loader = frame->loader()->documentLoader();
403         for (size_t i = 0; i < size; ++i)
404             loader->addArchiveResource(resources[i]);    
405     }
406
407     if (!wasDeferringCallbacks)
408         frame->page()->setDefersLoading(false);
409
410     [string release];
411     return fragment.release();
412 }
413
414 #define WebDataProtocolScheme @"webkit-fake-url"
415
416 static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
417 {
418     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
419     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
420     CFRelease(UUIDRef);
421     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", WebDataProtocolScheme, UUIDString, relativePart]];
422     CFRelease(UUIDString);
423
424     return URL;
425 }
426
427 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText)
428 {
429     NSArray *types = [m_pasteboard.get() types];
430     RefPtr<DocumentFragment> fragment;
431     chosePlainText = false;
432
433     if ([types containsObject:WebArchivePboardType]) {
434         RefPtr<LegacyWebArchive> coreArchive = LegacyWebArchive::create(KURL(), SharedBuffer::wrapNSData([m_pasteboard.get() dataForType:WebArchivePboardType]).get());
435         if (coreArchive) {
436             RefPtr<ArchiveResource> mainResource = coreArchive->mainResource();
437             if (mainResource) {
438                 NSString *MIMEType = mainResource->mimeType();
439                 if (!frame || !frame->document())
440                     return 0;
441                 if (frame->loader()->client()->canShowMIMETypeAsHTML(MIMEType)) {
442                     NSString *markupString = [[NSString alloc] initWithData:[mainResource->data()->createNSData() autorelease] encoding:NSUTF8StringEncoding];
443                     // FIXME: seems poor form to do this as a side effect of getting a document fragment
444                     if (DocumentLoader* loader = frame->loader()->documentLoader())
445                         loader->addAllArchiveResources(coreArchive.get());
446                     
447                     fragment = createFragmentFromMarkup(frame->document(), markupString, mainResource->url(), FragmentScriptingNotAllowed);
448                     [markupString release];
449                 } else if (MIMETypeRegistry::isSupportedImageMIMEType(MIMEType))
450                    fragment = documentFragmentWithImageResource(frame, mainResource);                    
451             }
452         }
453         if (fragment)
454             return fragment.release();
455     } 
456
457     if ([types containsObject:NSFilenamesPboardType]) {
458         NSArray* paths = [m_pasteboard.get() propertyListForType:NSFilenamesPboardType];
459         NSEnumerator* enumerator = [paths objectEnumerator];
460         NSString* path;
461         Vector< RefPtr<Node> > refNodesVector;
462         Vector<Node*> nodesVector;
463
464         while ((path = [enumerator nextObject]) != nil) {
465             // Non-image file types; _web_userVisibleString is appropriate here because this will
466             // be pasted as visible text.
467             NSString *url = frame->editor()->client()->userVisibleString([NSURL fileURLWithPath:path]);
468             RefPtr<Node> textNode = frame->document()->createTextNode(url);
469             refNodesVector.append(textNode.get());
470             nodesVector.append(textNode.get());
471         }
472         fragment = createFragmentFromNodes(frame->document(), nodesVector);
473         if (fragment && fragment->firstChild())
474             return fragment.release();
475     }
476
477     if ([types containsObject:NSHTMLPboardType]) {
478         NSString *HTMLString = [m_pasteboard.get() stringForType:NSHTMLPboardType];
479         // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
480         if ([HTMLString hasPrefix:@"Version:"]) {
481             NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
482             if (range.location != NSNotFound) {
483                 HTMLString = [HTMLString substringFromIndex:range.location];
484             }
485         }
486         if ([HTMLString length] != 0 &&
487             (fragment = createFragmentFromMarkup(frame->document(), HTMLString, "", FragmentScriptingNotAllowed)))
488             return fragment.release();
489     }
490
491     if ([types containsObject:NSRTFDPboardType] &&
492         (fragment = documentFragmentWithRTF(frame, NSRTFDPboardType, m_pasteboard.get())))
493        return fragment.release();
494
495     if ([types containsObject:NSRTFPboardType] &&
496         (fragment = documentFragmentWithRTF(frame, NSRTFPboardType, m_pasteboard.get())))
497         return fragment.release();
498
499     if ([types containsObject:NSTIFFPboardType] &&
500         (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:NSTIFFPboardType] copy] autorelease]), uniqueURLWithRelativePart(@"image.tiff"), "image/tiff", "", ""))))
501         return fragment.release();
502
503     if ([types containsObject:NSPDFPboardType] &&
504         (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:NSPDFPboardType] copy] autorelease]), uniqueURLWithRelativePart(@"application.pdf"), "application/pdf", "", ""))))
505         return fragment.release();
506
507 #ifdef BUILDING_ON_LEOPARD
508     if ([types containsObject:NSPICTPboardType] &&
509         (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:NSPICTPboardType] copy] autorelease]), uniqueURLWithRelativePart(@"image.pict"), "image/pict", "", ""))))
510         return fragment.release();
511 #endif
512
513     // Only 10.5 and higher support setting and retrieving pasteboard types with UTIs, but we don't believe
514     // that any applications on Tiger put types for which we only have a UTI, like PNG, on the pasteboard.
515     if ([types containsObject:(NSString*)kUTTypePNG] &&
516         (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:(NSString*)kUTTypePNG] copy] autorelease]), uniqueURLWithRelativePart(@"image.png"), "image/png", "", ""))))
517         return fragment.release();
518
519     if ([types containsObject:NSURLPboardType]) {
520         NSURL *URL = [NSURL URLFromPasteboard:m_pasteboard.get()];
521         Document* document = frame->document();
522         ASSERT(document);
523         if (!document)
524             return 0;
525         RefPtr<Element> anchor = document->createElement(HTMLNames::aTag, false);
526         NSString *URLString = [URL absoluteString]; // Original data is ASCII-only, so there is no need to precompose.
527         if ([URLString length] == 0)
528             return nil;
529         NSString *URLTitleString = [[m_pasteboard.get() stringForType:WebURLNamePboardType] precomposedStringWithCanonicalMapping];
530         ExceptionCode ec;
531         anchor->setAttribute(HTMLNames::hrefAttr, URLString);
532         anchor->appendChild(document->createTextNode(URLTitleString), ec);
533         fragment = document->createDocumentFragment();
534         if (fragment) {
535             fragment->appendChild(anchor, ec);
536             return fragment.release();
537         }
538     }
539
540     if (allowPlainText && [types containsObject:NSStringPboardType]) {
541         chosePlainText = true;
542         fragment = createFragmentFromText(context.get(), [[m_pasteboard.get() stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping]);
543         return fragment.release();
544     }
545
546     return 0;
547 }
548
549 }