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