| OLD | NEW |
| (Empty) |
| 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 s
electionContainsAttachments) | |
| 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_pas
teboardName); | |
| 136 } | |
| 137 | |
| 138 String Pasteboard::getStringSelection(Frame* frame, ShouldSerializeSelectedTextF
orClipboard shouldSerializeSelectedTextForClipboard) | |
| 139 { | |
| 140 String text = shouldSerializeSelectedTextForClipboard == IncludeImageAltText
ForClipboard ? frame->editor()->selectedTextForClipboard() : frame->editor()->se
lectedText(); | |
| 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(commonAnces
tor), HTMLNames::aTag); | |
| 157 if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(range->s
tartPosition().anchorNode()), range->startPosition()) >= 0) | |
| 158 range->setStart(enclosingAnchor, 0, IGNORE_EXCEPTION); | |
| 159 | |
| 160 NSAttributedString* attributedString = nil; | |
| 161 RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] ini
tWithDOMRange:kit(range.get())]); | |
| 162 if (converter) | |
| 163 attributedString = [converter.get() attributedString]; | |
| 164 | |
| 165 if (pasteboardType == String(NSRTFDPboardType)) { | |
| 166 NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attri
butedString length]) documentAttributes:nil]; | |
| 167 return SharedBuffer::wrapNSData((NSData *)RTFDData); | |
| 168 } | |
| 169 if (pasteboardType == String(NSRTFPboardType)) { | |
| 170 if ([attributedString containsAttachments]) | |
| 171 attributedString = attributedStringByStrippingAttachmentCharacters(a
ttributedString); | |
| 172 NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attribu
tedString length]) documentAttributes:nil]; | |
| 173 return SharedBuffer::wrapNSData((NSData *)RTFData); | |
| 174 } | |
| 175 return 0; | |
| 176 } | |
| 177 | |
| 178 void Pasteboard::writeSelectionForTypes(const Vector<String>& pasteboardTypes, b
ool canSmartCopyOrDelete, Frame* frame, ShouldSerializeSelectedTextForClipboard
shouldSerializeSelectedTextForClipboard) | |
| 179 { | |
| 180 NSAttributedString* attributedString = nil; | |
| 181 RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] ini
tWithDOMRange:kit(frame->editor()->selectedRange().get())]); | |
| 182 if (converter) | |
| 183 attributedString = [converter.get() attributedString]; | |
| 184 | |
| 185 Vector<String> types = !pasteboardTypes.isEmpty() ? pasteboardTypes : select
ionPasteboardTypes(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(getDataSele
ction(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(getDataSele
ction(frame, NSRTFDPboardType), NSRTFDPboardType, m_pasteboardName); | |
| 205 | |
| 206 if (types.contains(String(NSRTFPboardType))) | |
| 207 platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSele
ction(frame, NSRTFPboardType), NSRTFPboardType, m_pasteboardName); | |
| 208 | |
| 209 // Put plain string on the pasteboard. | |
| 210 if (types.contains(String(NSStringPboardType))) | |
| 211 platformStrategies()->pasteboardStrategy()->setStringForType(getStringSe
lection(frame, shouldSerializeSelectedTextForClipboard), NSStringPboardType, m_p
asteboardName); | |
| 212 | |
| 213 if (types.contains(WebSmartPastePboardType)) | |
| 214 platformStrategies()->pasteboardStrategy()->setBufferForType(0, WebSmart
PastePboardType, m_pasteboardName); | |
| 215 } | |
| 216 | |
| 217 void Pasteboard::writePlainText(const String& text, SmartReplaceOption smartRepl
aceOption) | |
| 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, NSStringP
boardType, m_pasteboardName); | |
| 226 if (smartReplaceOption == CanSmartReplace) | |
| 227 platformStrategies()->pasteboardStrategy()->setBufferForType(0, WebSmart
PastePboardType, m_pasteboardName); | |
| 228 } | |
| 229 | |
| 230 void Pasteboard::writeSelection(Range*, bool canSmartCopyOrDelete, Frame* frame,
ShouldSerializeSelectedTextForClipboard shouldSerializeSelectedTextForClipboard
) | |
| 231 { | |
| 232 writeSelectionForTypes(Vector<String>(), canSmartCopyOrDelete, frame, should
SerializeSelectedTextForClipboard); | |
| 233 } | |
| 234 | |
| 235 static void writeURLForTypes(const Vector<String>& types, const String& pasteboa
rdName, 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(c
ocoaURL); | |
| 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, W
ebURLsWithTitlesPboardType, pasteboardName); | |
| 255 } | |
| 256 if (types.contains(String(NSURLPboardType))) | |
| 257 platformStrategies()->pasteboardStrategy()->setStringForType([cocoaURL a
bsoluteString], NSURLPboardType, pasteboardName); | |
| 258 if (types.contains(WebURLPboardType)) | |
| 259 platformStrategies()->pasteboardStrategy()->setStringForType(userVisible
String, WebURLPboardType, pasteboardName); | |
| 260 if (types.contains(WebURLNamePboardType)) | |
| 261 platformStrategies()->pasteboardStrategy()->setStringForType(title, WebU
RLNamePboardType, pasteboardName); | |
| 262 if (types.contains(String(NSStringPboardType))) | |
| 263 platformStrategies()->pasteboardStrategy()->setStringForType(userVisible
String, NSStringPboardType, pasteboardName); | |
| 264 } | |
| 265 | |
| 266 void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame) | |
| 267 { | |
| 268 writeURLForTypes(writableTypesForURL(), m_pasteboardName, url, titleStr, fra
me); | |
| 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:coreDa
ta->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 Strin
g& pasteboardName) | |
| 285 { | |
| 286 NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper
:wrapper]; | |
| 287 | |
| 288 NSAttributedString *string = [NSAttributedString attributedStringWithAttachm
ent:attachment]; | |
| 289 [attachment release]; | |
| 290 | |
| 291 NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) doc
umentAttributes:nil]; | |
| 292 if (RTFDData) | |
| 293 platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffe
r::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, nsStri
ngNilIfEmpty(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::w
rapNSData(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()->stringFo
rType(NSStringPboardType, m_pasteboardName) precomposedStringWithCanonicalMappin
g]; | |
| 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->c
reateNSData() 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->cr
eateNSData() autorelease] documentAttributes:NULL]; | |
| 359 } | |
| 360 if (attributedString != nil) { | |
| 361 string = [[attributedString string] precomposedStringWithCanonicalMappin
g]; | |
| 362 [attributedString release]; | |
| 363 return string; | |
| 364 } | |
| 365 | |
| 366 if (types.contains(String(NSFilenamesPboardType))) { | |
| 367 Vector<String> pathnames; | |
| 368 platformStrategies()->pasteboardStrategy()->getPathnamesForType(pathname
s, 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(NSURLPboa
rdType, 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 siza
ble 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 URLWithStri
ng:string]); | |
| 382 if ([string length] > 0) | |
| 383 return [string precomposedStringWithCanonicalMapping]; | |
| 384 } | |
| 385 | |
| 386 | |
| 387 return String(); | |
| 388 } | |
| 389 | |
| 390 static PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* fra
me, 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::i
mgTag, false); | |
| 399 if (!imageElement) | |
| 400 return 0; | |
| 401 | |
| 402 NSURL *URL = resource->url(); | |
| 403 imageElement->setAttribute(HTMLNames::srcAttr, [URL isFileURL] ? [URL absolu
teString] : resource->url()); | |
| 404 RefPtr<DocumentFragment> fragment = frame->document()->createDocumentFragmen
t(); | |
| 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, NSStri
ng *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->createNSDat
a() 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()->documentFragm
entFromAttributedString(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, U
UIDRef); | |
| 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, PassRef
Ptr<LegacyWebArchive> coreArchive) | |
| 466 { | |
| 467 RefPtr<ArchiveResource> mainResource = coreArchive->mainResource(); | |
| 468 if (!mainResource) | |
| 469 return 0; | |
| 470 | |
| 471 const String& 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:NSUTF8StringEncodin
g]); | |
| 477 // FIXME: seems poor form to do this as a side effect of getting a docum
ent fragment | |
| 478 if (DocumentLoader* loader = frame->loader()->documentLoader()) | |
| 479 loader->addAllArchiveResources(coreArchive.get()); | |
| 480 return createFragmentFromMarkup(frame->document(), markupString.get(), m
ainResource->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, PassRefP
tr<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()->pasteb
oardStrategy()->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, N
SFilenamesPboardType, 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()->strin
gForType(NSHTMLPboardType, m_pasteboardName); | |
| 526 // This is a hack to make Microsoft's HTML pasteboard data work. See 377
8785. | |
| 527 if ([HTMLString hasPrefix:@"Version:"]) { | |
| 528 NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseIns
ensitiveSearch]; | |
| 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_pasteboar
dName))) | |
| 540 return fragment.release(); | |
| 541 | |
| 542 if (types.contains(String(NSRTFPboardType)) && | |
| 543 (fragment = documentFragmentWithRTF(frame, NSRTFPboardType, m_pasteboard
Name))) | |
| 544 return fragment.release(); | |
| 545 | |
| 546 if (types.contains(String(NSTIFFPboardType)) && | |
| 547 (fragment = documentFragmentWithImageResource(frame, ArchiveResource::cr
eate(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::cr
eate(platformStrategies()->pasteboardStrategy()->bufferForType(NSPDFPboardType,
m_pasteboardName).get(), uniqueURLWithRelativePart(@"application.pdf"), "applica
tion/pdf", "", "")))) | |
| 552 return fragment.release(); | |
| 553 | |
| 554 if (types.contains(String(kUTTypePNG)) && | |
| 555 (fragment = documentFragmentWithImageResource(frame, ArchiveResource::cr
eate(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_pasteboar
dName); | |
| 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-on
ly, so there is no need to precompose. | |
| 566 if ([URLString length] == 0) | |
| 567 return nil; | |
| 568 NSString *URLTitleString = [platformStrategies()->pasteboardStrategy()->
stringForType(WebURLNamePboardType, m_pasteboardName) precomposedStringWithCanon
icalMapping]; | |
| 569 anchor->setAttribute(HTMLNames::hrefAttr, URLString); | |
| 570 anchor->appendChild(document->createTextNode(URLTitleString), IGNORE_EXC
EPTION); | |
| 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) precom
posedStringWithCanonicalMapping]); | |
| 581 return fragment.release(); | |
| 582 } | |
| 583 | |
| 584 return 0; | |
| 585 } | |
| 586 | |
| 587 } | |
| OLD | NEW |