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