Assertion in LegacyWebArchive::create() in editing tests
[WebKit-https.git] / Source / WebCore / platform / mac / PasteboardMac.mm
index bcd7801..c20b7bb 100644 (file)
 #import "Pasteboard.h"
 
 #import "CachedResource.h"
+#import "ClipboardMac.h"
 #import "DOMRangeInternal.h"
 #import "Document.h"
 #import "DocumentFragment.h"
 #import "DocumentLoader.h"
 #import "Editor.h"
 #import "EditorClient.h"
+#import "ExceptionCodePlaceholder.h"
 #import "Frame.h"
 #import "FrameView.h"
 #import "FrameLoaderClient.h"
 #import "HitTestResult.h"
 #import "HTMLAnchorElement.h"
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
 #import "HTMLConverter.h"
-#endif
+#import "htmlediting.h"
 #import "HTMLNames.h"
 #import "Image.h"
 #import "KURL.h"
 #import "MIMETypeRegistry.h"
 #import "Page.h"
 #import "RenderImage.h"
+#import "ResourceBuffer.h"
 #import "Text.h"
 #import "WebCoreNSStringExtras.h"
+#import "WebNSAttributedStringExtras.h"
 #import "markup.h"
 #import <wtf/StdLibExtras.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/UnusedParam.h>
+#import <wtf/text/StringBuilder.h>
 #import <wtf/unicode/CharacterNames.h>
 
-@interface NSAttributedString (AppKitSecretsIKnowAbout)
-- (id)_initWithDOMRange:(DOMRange *)domRange;
-@end
+#if USE(PLATFORM_STRATEGIES)
+#include "PasteboardStrategy.h"
+#include "PlatformStrategies.h"
+#endif
+
 namespace WebCore {
 
 // FIXME: It's not great to have these both here and in WebKit.
-NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type";
-NSString *WebSmartPastePboardType = @"NeXT smart paste pasteboard type";
-NSString *WebURLNamePboardType = @"public.url-name";
-NSString *WebURLPboardType = @"public.url";
-NSString *WebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";
-
-#ifndef BUILDING_ON_TIGER
-static NSArray* selectionPasteboardTypes(bool canSmartCopyOrDelete, bool selectionContainsAttachments)
+const char* WebArchivePboardType = "Apple Web Archive pasteboard type";
+const char* WebSmartPastePboardType = "NeXT smart paste pasteboard type";
+const char* WebURLNamePboardType = "public.url-name";
+const char* WebURLPboardType = "public.url";
+const char* WebURLsWithTitlesPboardType = "WebURLsWithTitlesPboardType";
+
+static Vector<String> selectionPasteboardTypes(bool canSmartCopyOrDelete, bool selectionContainsAttachments)
 {
-    if (selectionContainsAttachments) {
-        if (canSmartCopyOrDelete)
-            return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
-        else
-            return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
-    } else { // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
-        if (canSmartCopyOrDelete)
-            return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
-        else
-            return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
-    }
+    Vector<String> types;
+    if (canSmartCopyOrDelete)
+        types.append(WebSmartPastePboardType);
+    types.append(WebArchivePboardType);
+    if (selectionContainsAttachments)
+        types.append(String(NSRTFDPboardType));
+    types.append(String(NSRTFPboardType));
+    types.append(String(NSStringPboardType));
+
+    return types;
 }
-#endif
 
-static NSArray* writableTypesForURL()
+static const Vector<String> writableTypesForURL()
 {
-    DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, ([[NSArray alloc] initWithObjects:
-            WebURLsWithTitlesPboardType,
-            NSURLPboardType,
-            WebURLPboardType,
-            WebURLNamePboardType,
-            NSStringPboardType,
-            nil]));
-    return types.get();
+    Vector<String> types;
+    
+    types.append(WebURLsWithTitlesPboardType);
+    types.append(String(NSURLPboardType));
+    types.append(WebURLPboardType);
+    types.append(WebURLNamePboardType);
+    types.append(String(NSStringPboardType));        
+    return types;
 }
 
-static inline NSArray* createWritableTypesForImage()
+static inline Vector<String> createWritableTypesForImage()
 {
-    NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
-    [types addObjectsFromArray:writableTypesForURL()];
-    [types addObject:NSRTFDPboardType];
+    Vector<String> types;
+    
+    types.append(String(NSTIFFPboardType));
+    types.append(writableTypesForURL());
+    types.append(String(NSRTFDPboardType));
     return types;
 }
 
-static NSArray* writableTypesForImage()
+static Vector<String> writableTypesForImage()
 {
-    DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (createWritableTypesForImage()));
-    return types.get();
+    Vector<String> types;
+    types.append(createWritableTypesForImage());
+    return types;
 }
 
 Pasteboard* Pasteboard::generalPasteboard() 
 {
-    static Pasteboard* pasteboard = new Pasteboard([NSPasteboard generalPasteboard]);
+    static Pasteboard* pasteboard = new Pasteboard(NSGeneralPboard);
     return pasteboard;
 }
 
-Pasteboard::Pasteboard(NSPasteboard* pboard)
-    : m_pasteboard(pboard)
+Pasteboard::Pasteboard(const String& pasteboardName)
+    : m_pasteboardName(pasteboardName)
 {
+    ASSERT(pasteboardName);
 }
 
 void Pasteboard::clear()
 {
-    [m_pasteboard.get() declareTypes:[NSArray array] owner:nil];
+    platformStrategies()->pasteboardStrategy()->setTypes(Vector<String>(), m_pasteboardName);
 }
 
-static NSAttributedString *stripAttachmentCharacters(NSAttributedString *string)
+String Pasteboard::getStringSelection(Frame* frame)
 {
-    const unichar attachmentCharacter = NSAttachmentCharacter;
-    DEFINE_STATIC_LOCAL(RetainPtr<NSString>, attachmentCharacterString, ([NSString stringWithCharacters:&attachmentCharacter length:1]));
-    NSMutableAttributedString *result = [[string mutableCopy] autorelease];
-    NSRange attachmentRange = [[result string] rangeOfString:attachmentCharacterString.get()];
-    while (attachmentRange.location != NSNotFound) {
-        [result replaceCharactersInRange:attachmentRange withString:@""];
-        attachmentRange = [[result string] rangeOfString:attachmentCharacterString.get()];
-    }
-    return result;
+    String text = frame->editor()->selectedText();
+    text.replace(noBreakSpace, ' ');
+    return text;
 }
 
-void Pasteboard::writeSelection(NSPasteboard* pasteboard, NSArray* pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+PassRefPtr<SharedBuffer> Pasteboard::getDataSelection(Frame* frame, const String& pasteboardType)
 {
-    if (!WebArchivePboardType)
-        Pasteboard::generalPasteboard(); // Initializes pasteboard types.
-    ASSERT(selectedRange);
-    
-    // Using different API for WebKit and WebKit2.
-    NSAttributedString *attributedString = nil;
-    if (frame->view()->platformWidget())
-        attributedString = [[[NSAttributedString alloc] _initWithDOMRange:kit(selectedRange)] autorelease];
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
-    else {
-        // In WebKit2 we are using a different way to create the NSAttributedString from the DOMrange that doesn't require access to the WebView.
-        RetainPtr<WebHTMLConverter> converter = [[WebHTMLConverter alloc] initWithDOMRange:kit(selectedRange)];
-        if (converter)
-            attributedString = [converter.get() attributedString];
-    }
-#endif
-
-#ifdef BUILDING_ON_TIGER
-    // 4930197: Mail overrides [WebHTMLView pasteboardTypesForSelection] in order to add another type to the pasteboard
-    // after WebKit does.  On Tiger we must call this function so that Mail code will be executed, meaning that 
-    // we can't call WebCore::Pasteboard's method for setting types. 
-    UNUSED_PARAM(canSmartCopyOrDelete);
-
-    NSArray *types = pasteboardTypes ? pasteboardTypes : frame->editor()->client()->pasteboardTypesForSelection(frame);
-    // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
-    NSMutableArray *mutableTypes = nil;
-    if (![attributedString containsAttachments]) {
-        mutableTypes = [[types mutableCopy] autorelease];
-        [mutableTypes removeObject:NSRTFDPboardType];
-        types = mutableTypes;
-    }
-    [pasteboard declareTypes:types owner:nil];    
-#else
-    NSArray *types = pasteboardTypes ? pasteboardTypes : selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
-    [pasteboard declareTypes:types owner:nil];
-    frame->editor()->client()->didSetSelectionTypesForPasteboard();
-#endif
-    
-    // Put HTML on the pasteboard.
-    if ([types containsObject:WebArchivePboardType]) {
+    if (pasteboardType == WebArchivePboardType) {
         RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
         RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
-        [pasteboard setData:(NSData *)data.get() forType:WebArchivePboardType];
+        return SharedBuffer::wrapNSData((NSData *)data.get());
     }
+
+    RefPtr<Range> range = frame->editor()->selectedRange();
+    Node* commonAncestor = range->commonAncestorContainer(IGNORE_EXCEPTION);
+    ASSERT(commonAncestor);
+    Node* enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(commonAncestor), HTMLNames::aTag);
+    if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(range->startPosition().anchorNode()), range->startPosition()) >= 0)
+        range->setStart(enclosingAnchor, 0, IGNORE_EXCEPTION);
     
-    // Put the attributed string on the pasteboard (RTF/RTFD format).
-    if ([types containsObject:NSRTFDPboardType]) {
+    NSAttributedString* attributedString = nil;
+    RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(range.get())]);
+    if (converter)
+        attributedString = [converter.get() attributedString];
+    
+    if (pasteboardType == String(NSRTFDPboardType)) {
         NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
-        [pasteboard setData:RTFDData forType:NSRTFDPboardType];
+        return SharedBuffer::wrapNSData((NSData *)RTFDData);
     }
-    if ([types containsObject:NSRTFPboardType]) {
+    if (pasteboardType == String(NSRTFPboardType)) {
         if ([attributedString containsAttachments])
-            attributedString = stripAttachmentCharacters(attributedString);
+            attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
         NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
-        [pasteboard setData:RTFData forType:NSRTFPboardType];
+        return SharedBuffer::wrapNSData((NSData *)RTFData);
     }
+    return 0;
+}
+
+void Pasteboard::writeSelectionForTypes(const Vector<String>& pasteboardTypes, bool canSmartCopyOrDelete, Frame* frame)
+{
+    NSAttributedString* attributedString = nil;
+    RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(frame->editor()->selectedRange().get())]);
+    if (converter)
+        attributedString = [converter.get() attributedString];
+    
+    Vector<String> types = !pasteboardTypes.isEmpty() ? pasteboardTypes : selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
+
+    Vector<String> clientTypes;
+    Vector<RefPtr<SharedBuffer> > clientData;
+    frame->editor()->client()->getClientPasteboardDataForRange(frame->editor()->selectedRange().get(), clientTypes, clientData);
+    types.append(clientTypes);
+
+    platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
+    frame->editor()->client()->didSetSelectionTypesForPasteboard();
+
+    for (size_t i = 0; i < clientTypes.size(); ++i)
+        platformStrategies()->pasteboardStrategy()->setBufferForType(clientData[i], clientTypes[i], m_pasteboardName);
+
+    // Put HTML on the pasteboard.
+    if (types.contains(WebArchivePboardType))
+        platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, WebArchivePboardType), WebArchivePboardType, m_pasteboardName);
+    
+    // Put the attributed string on the pasteboard (RTF/RTFD format).
+    if (types.contains(String(NSRTFDPboardType)))
+        platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, NSRTFDPboardType), NSRTFDPboardType, m_pasteboardName);
+
+    if (types.contains(String(NSRTFPboardType)))
+        platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, NSRTFPboardType), NSRTFPboardType, m_pasteboardName);
     
     // Put plain string on the pasteboard.
-    if ([types containsObject:NSStringPboardType]) {
-        // Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
-        // and because HTML forces you to do this any time you want two spaces in a row.
-        String text = frame->editor()->selectedText();
-        NSMutableString *s = [[[(NSString*)text copy] autorelease] mutableCopy];
-        
-        NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
-        [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
-        [pasteboard setString:s forType:NSStringPboardType];
-        [s release];
-    }
+    if (types.contains(String(NSStringPboardType)))
+        platformStrategies()->pasteboardStrategy()->setStringForType(getStringSelection(frame), NSStringPboardType, m_pasteboardName);
     
-    if ([types containsObject:WebSmartPastePboardType]) {
-        [pasteboard setData:nil forType:WebSmartPastePboardType];
-    }
+    if (types.contains(WebSmartPastePboardType))
+        platformStrategies()->pasteboardStrategy()->setBufferForType(0, WebSmartPastePboardType, m_pasteboardName);
 }
 
-void Pasteboard::writePlainText(NSPasteboard* pasteboard, const String& text)
+void Pasteboard::writePlainText(const String& text, SmartReplaceOption smartReplaceOption)
 {
-    NSArray *types = [NSArray arrayWithObject:NSStringPboardType];
-    [pasteboard declareTypes:types owner:nil];
-    
-    [pasteboard setString:text forType:NSStringPboardType];
+    Vector<String> types;
+    types.append(NSStringPboardType);
+    if (smartReplaceOption == CanSmartReplace)
+        types.append(WebSmartPastePboardType);
+
+    platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
+    platformStrategies()->pasteboardStrategy()->setStringForType(text, NSStringPboardType, m_pasteboardName);
+    if (smartReplaceOption == CanSmartReplace)
+        platformStrategies()->pasteboardStrategy()->setBufferForType(0, WebSmartPastePboardType, m_pasteboardName);
 }
     
-void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+void Pasteboard::writeSelection(Range*, bool canSmartCopyOrDelete, Frame* frame)
 {
-    Pasteboard::writeSelection(m_pasteboard.get(), 0, selectedRange, canSmartCopyOrDelete, frame);
+    writeSelectionForTypes(Vector<String>(), canSmartCopyOrDelete, frame);
 }
 
-void Pasteboard::writePlainText(const String& text)
+static void writeURLForTypes(const Vector<String>& types, const String& pasteboardName, const KURL& url, const String& titleStr, Frame* frame)
 {
-    if (!WebArchivePboardType)
-        Pasteboard::generalPasteboard(); // Initializes pasteboard types.
-
-    NSArray *types = [NSArray arrayWithObject:NSStringPboardType];
-    NSPasteboard *pasteboard = m_pasteboard.get();
-    [pasteboard declareTypes:types owner:nil];
-
-    [pasteboard setString:text forType:NSStringPboardType];
-}
-
-void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame)
-{
-    if (!WebArchivePboardType)
-        Pasteboard::generalPasteboard(); // Initializes pasteboard types.
-   
-    if (!types) {
-        types = writableTypesForURL();
-        [pasteboard declareTypes:types owner:nil];
-    }
+    platformStrategies()->pasteboardStrategy()->setTypes(types, pasteboardName);
     
     ASSERT(!url.isEmpty());
     
@@ -264,30 +247,30 @@ void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL&
         if ([title length] == 0)
             title = userVisibleString;
     }
-        
-    if ([types containsObject:WebURLsWithTitlesPboardType])
-        [pasteboard setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString], 
-                                     [NSArray arrayWithObject:(NSString*)titleStr.stripWhiteSpace()], 
-                                     nil]
-                            forType:WebURLsWithTitlesPboardType];
-    if ([types containsObject:NSURLPboardType])
-        [cocoaURL writeToPasteboard:pasteboard];
-    if ([types containsObject:WebURLPboardType])
-        [pasteboard setString:userVisibleString forType:WebURLPboardType];
-    if ([types containsObject:WebURLNamePboardType])
-        [pasteboard setString:title forType:WebURLNamePboardType];
-    if ([types containsObject:NSStringPboardType])
-        [pasteboard setString:userVisibleString forType:NSStringPboardType];
+    if (types.contains(WebURLsWithTitlesPboardType)) {
+        Vector<String> paths;
+        paths.append([cocoaURL absoluteString]);
+        paths.append(titleStr.stripWhiteSpace());
+        platformStrategies()->pasteboardStrategy()->setPathnamesForType(paths, WebURLsWithTitlesPboardType, pasteboardName);
+    }
+    if (types.contains(String(NSURLPboardType)))
+        platformStrategies()->pasteboardStrategy()->setStringForType([cocoaURL absoluteString], NSURLPboardType, pasteboardName);
+    if (types.contains(WebURLPboardType))
+        platformStrategies()->pasteboardStrategy()->setStringForType(userVisibleString, WebURLPboardType, pasteboardName);
+    if (types.contains(WebURLNamePboardType))
+        platformStrategies()->pasteboardStrategy()->setStringForType(title, WebURLNamePboardType, pasteboardName);
+    if (types.contains(String(NSStringPboardType)))
+        platformStrategies()->pasteboardStrategy()->setStringForType(userVisibleString, NSStringPboardType, pasteboardName);
 }
     
 void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
 {
-    Pasteboard::writeURL(m_pasteboard.get(), nil, url, titleStr, frame);
+    writeURLForTypes(writableTypesForURL(), m_pasteboardName, url, titleStr, frame);
 }
 
 static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url)
 {
-    SharedBuffer* coreData = resource->data();
+    ResourceBuffer* coreData = resource->resourceBuffer();
     NSData *data = [[[NSData alloc] initWithBytes:coreData->data() length:coreData->size()] autorelease];
     NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];
     String coreMIMEType = resource->response().mimeType();
@@ -298,7 +281,7 @@ static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url)
     return wrapper;
 }
 
-void Pasteboard::writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper)
+static void writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper, const String& pasteboardName)
 {
     NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper];
     
@@ -306,75 +289,96 @@ void Pasteboard::writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper)
     [attachment release];
     
     NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil];
-    [m_pasteboard.get() setData:RTFDData forType:NSRTFDPboardType];
+    if (RTFDData)
+        platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData(RTFDData).get(), NSRTFDPboardType, pasteboardName);
 }
 
 void Pasteboard::writeImage(Node* node, const KURL& url, const String& title)
 {
     ASSERT(node);
-    Frame* frame = node->document()->frame();
+
+    if (!(node->renderer() && node->renderer()->isImage()))
+        return;
 
     NSURL *cocoaURL = url;
     ASSERT(cocoaURL);
 
-    ASSERT(node->renderer() && node->renderer()->isImage());
     RenderImage* renderer = toRenderImage(node->renderer());
     CachedImage* cachedImage = renderer->cachedImage();
     if (!cachedImage || cachedImage->errorOccurred())
         return;
 
-    NSArray* types = writableTypesForImage();
-    [m_pasteboard.get() declareTypes:types owner:nil];
-    writeURL(m_pasteboard.get(), types, cocoaURL, nsStringNilIfEmpty(title), frame);
-    
-    Image* image = cachedImage->image();
-    ASSERT(image);
+    writeURLForTypes(writableTypesForImage(), m_pasteboardName, cocoaURL, nsStringNilIfEmpty(title), node->document()->frame());
     
-    [m_pasteboard.get() setData:[image->getNSImage() TIFFRepresentation] forType:NSTIFFPboardType];
+    Image* image = cachedImage->imageForRenderer(renderer);
+    if (!image)
+        return;
+    NSData *imageData = (NSData *)[image->getNSImage() TIFFRepresentation];
+    if (!imageData)
+        return;
+    platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData(imageData), NSTIFFPboardType, m_pasteboardName);
 
     String MIMEType = cachedImage->response().mimeType();
     ASSERT(MIMETypeRegistry::isSupportedImageResourceMIMEType(MIMEType));
 
-    writeFileWrapperAsRTFDAttachment(fileWrapperForImage(cachedImage, cocoaURL));
+    writeFileWrapperAsRTFDAttachment(fileWrapperForImage(cachedImage, cocoaURL), m_pasteboardName);
+}
+
+void Pasteboard::writeClipboard(Clipboard* clipboard)
+{
+    platformStrategies()->pasteboardStrategy()->copy(static_cast<ClipboardMac*>(clipboard)->pasteboardName(), m_pasteboardName);
 }
 
 bool Pasteboard::canSmartReplace()
 {
-    return [[m_pasteboard.get() types] containsObject:WebSmartPastePboardType];
+    Vector<String> types;
+    platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
+    return types.contains(WebSmartPastePboardType);
 }
 
 String Pasteboard::plainText(Frame* frame)
 {
-    NSArray *types = [m_pasteboard.get() types];
+    Vector<String> types;
+    platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
     
-    if ([types containsObject:NSStringPboardType])
-        return [[m_pasteboard.get() stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping];
+    if (types.contains(String(NSStringPboardType)))
+        return [(NSString *)platformStrategies()->pasteboardStrategy()->stringForType(NSStringPboardType, m_pasteboardName) precomposedStringWithCanonicalMapping];
     
     NSAttributedString *attributedString = nil;
     NSString *string;
 
-    if ([types containsObject:NSRTFDPboardType])
-        attributedString = [[NSAttributedString alloc] initWithRTFD:[m_pasteboard.get() dataForType:NSRTFDPboardType] documentAttributes:NULL];
-    if (attributedString == nil && [types containsObject:NSRTFPboardType])
-        attributedString = [[NSAttributedString alloc] initWithRTF:[m_pasteboard.get() dataForType:NSRTFPboardType] documentAttributes:NULL];
+    if (types.contains(String(NSRTFDPboardType))) {
+        RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFDPboardType, m_pasteboardName);
+        if (data)
+            attributedString = [[NSAttributedString alloc] initWithRTFD:[data->createNSData() autorelease] documentAttributes:NULL];
+    }
+    if (attributedString == nil && types.contains(String(NSRTFPboardType))) {
+        RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFPboardType, m_pasteboardName);
+        if (data)
+            attributedString = [[NSAttributedString alloc] initWithRTF:[data->createNSData() autorelease] documentAttributes:NULL];
+    }
     if (attributedString != nil) {
         string = [[attributedString string] precomposedStringWithCanonicalMapping];
         [attributedString release];
         return string;
     }
     
-    if ([types containsObject:NSFilenamesPboardType]) {
-        string = [[[m_pasteboard.get() propertyListForType:NSFilenamesPboardType] componentsJoinedByString:@"\n"] precomposedStringWithCanonicalMapping];
-        if (string != nil)
-            return string;
+    if (types.contains(String(NSFilenamesPboardType))) {
+        Vector<String> pathnames;
+        platformStrategies()->pasteboardStrategy()->getPathnamesForType(pathnames, NSFilenamesPboardType, m_pasteboardName);
+        StringBuilder builder;
+        for (size_t i = 0; i < pathnames.size(); i++)
+            builder.append(i ? "\n" + pathnames[i] : pathnames[i]);
+        string = builder.toString();
+        return [string precomposedStringWithCanonicalMapping];
     }
     
-    
-    if (NSURL *url = [NSURL URLFromPasteboard:m_pasteboard.get()]) {
+    string = platformStrategies()->pasteboardStrategy()->stringForType(NSURLPboardType, m_pasteboardName);
+    if ([string length]) {
         // FIXME: using the editorClient to call into webkit, for now, since 
         // calling _web_userVisibleString from WebCore involves migrating a sizable web of 
         // helper code that should either be done in a separate patch or figured out in another way.
-        string = frame->editor()->client()->userVisibleString(url);
+        string = frame->editor()->client()->userVisibleString([NSURL URLWithString:string]);
         if ([string length] > 0)
             return [string precomposedStringWithCanonicalMapping];
     }
@@ -383,8 +387,11 @@ String Pasteboard::plainText(Frame* frame)
     return String(); 
 }
     
-PassRefPtr<DocumentFragment> Pasteboard::documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource)
+static PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource)
 {
+    if (!resource)
+        return 0;
+    
     if (DocumentLoader* loader = frame->loader()->documentLoader())
         loader->addArchiveResource(resource.get());
 
@@ -396,23 +403,28 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragmentWithImageResource(Frame
     imageElement->setAttribute(HTMLNames::srcAttr, [URL isFileURL] ? [URL absoluteString] : resource->url());
     RefPtr<DocumentFragment> fragment = frame->document()->createDocumentFragment();
     if (fragment) {
-        ExceptionCode ec;
-        fragment->appendChild(imageElement, ec);
-        return fragment.release();       
+        fragment->appendChild(imageElement, IGNORE_EXCEPTION);
+        return fragment.release();
     }
     return 0;
 }
 
-PassRefPtr<DocumentFragment> Pasteboard::documentFragmentWithRtf(Frame* frame, NSString* pboardType)
+static PassRefPtr<DocumentFragment> documentFragmentWithRTF(Frame* frame, NSString *pasteboardType,const String& pastebordName)
 {
     if (!frame || !frame->document() || !frame->document()->isHTMLDocument())
         return 0;
 
     NSAttributedString *string = nil;
-    if (pboardType == NSRTFDPboardType)
-        string = [[NSAttributedString alloc] initWithRTFD:[m_pasteboard.get() dataForType:NSRTFDPboardType] documentAttributes:NULL];
-    if (string == nil)
-        string = [[NSAttributedString alloc] initWithRTF:[m_pasteboard.get() dataForType:NSRTFPboardType] documentAttributes:NULL];
+    if (pasteboardType == NSRTFDPboardType) {
+        RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFDPboardType, pastebordName);
+        if (data)
+            string = [[NSAttributedString alloc] initWithRTFD:[data->createNSData() autorelease] documentAttributes:NULL];
+    }
+    if (string == nil) {
+        RefPtr<SharedBuffer> data = platformStrategies()->pasteboardStrategy()->bufferForType(NSRTFPboardType, pastebordName);
+        if (data)
+            string = [[NSAttributedString alloc] initWithRTF:[data->createNSData() autorelease] documentAttributes:NULL];
+    }
     if (string == nil)
         return nil;
 
@@ -450,90 +462,56 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
     return URL;
 }
 
-NSURL *Pasteboard::getBestURL(Frame* frame)
+static PassRefPtr<DocumentFragment> fragmentFromWebArchive(Frame* frame, PassRefPtr<LegacyWebArchive> coreArchive)
 {
-    NSArray *types = [m_pasteboard.get() types];
+    RefPtr<ArchiveResource> mainResource = coreArchive->mainResource();
+    if (!mainResource)
+        return 0;
 
-    // FIXME: using the editorClient to call into webkit, for now, since 
-    // calling webkit_canonicalize from WebCore involves migrating a sizable amount of 
-    // helper code that should either be done in a separate patch or figured out in another way.
-    
-    if ([types containsObject:NSURLPboardType]) {
-        NSURL *URLFromPasteboard = [NSURL URLFromPasteboard:m_pasteboard.get()];
-        NSString *scheme = [URLFromPasteboard scheme];
-        if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) {
-            return frame->editor()->client()->canonicalizeURL(URLFromPasteboard);
-        }
-    }
-    
-    if ([types containsObject:NSStringPboardType]) {
-        NSString *URLString = [m_pasteboard.get() stringForType:NSStringPboardType];
-        NSURL *URL = frame->editor()->client()->canonicalizeURLString(URLString);
-        if (URL)
-            return URL;
-    }
-    
-    if ([types containsObject:NSFilenamesPboardType]) {
-        NSArray *files = [m_pasteboard.get() propertyListForType:NSFilenamesPboardType];
-        // FIXME: Maybe it makes more sense to allow multiple files and only use the first one?
-        if ([files count] == 1) {
-            NSString *file = [files objectAtIndex:0];
-            BOOL isDirectory;
-            if ([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && isDirectory)
-                return nil;
-            return frame->editor()->client()->canonicalizeURL([NSURL fileURLWithPath:file]);
-        }
+    const String& MIMEType = mainResource->mimeType();
+    if (!frame || !frame->document())
+        return 0;
+
+    if (frame->loader()->client()->canShowMIMETypeAsHTML(MIMEType)) {
+        RetainPtr<NSString> markupString(AdoptNS, [[NSString alloc] initWithData:[mainResource->data()->createNSData() autorelease] encoding:NSUTF8StringEncoding]);
+        // FIXME: seems poor form to do this as a side effect of getting a document fragment
+        if (DocumentLoader* loader = frame->loader()->documentLoader())
+            loader->addAllArchiveResources(coreArchive.get());
+        return createFragmentFromMarkup(frame->document(), markupString.get(), mainResource->url(), DisallowScriptingAndPluginContent);
     }
-    
-    return nil;    
-}
 
-String Pasteboard::asURL(Frame* frame)
-{
-    return [getBestURL(frame) absoluteString];
+    if (MIMETypeRegistry::isSupportedImageMIMEType(MIMEType))
+        return documentFragmentWithImageResource(frame, mainResource);
+
+    return 0;
 }
 
 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText)
 {
-    NSArray *types = [m_pasteboard.get() types];
+    Vector<String> types;
+    platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
     RefPtr<DocumentFragment> fragment;
     chosePlainText = false;
 
-    if ([types containsObject:WebArchivePboardType]) {
-        RefPtr<LegacyWebArchive> coreArchive = LegacyWebArchive::create(SharedBuffer::wrapNSData([m_pasteboard.get() dataForType:WebArchivePboardType]).get());
-        if (coreArchive) {
-            RefPtr<ArchiveResource> mainResource = coreArchive->mainResource();
-            if (mainResource) {
-                NSString *MIMEType = mainResource->mimeType();
-                if (!frame || !frame->document())
-                    return 0;
-                if (frame->loader()->client()->canShowMIMETypeAsHTML(MIMEType)) {
-                    NSString *markupString = [[NSString alloc] initWithData:[mainResource->data()->createNSData() autorelease] encoding:NSUTF8StringEncoding];
-                    // FIXME: seems poor form to do this as a side effect of getting a document fragment
-                    if (DocumentLoader* loader = frame->loader()->documentLoader())
-                        loader->addAllArchiveResources(coreArchive.get());
-                    
-                    fragment = createFragmentFromMarkup(frame->document(), markupString, mainResource->url(), FragmentScriptingNotAllowed);
-                    [markupString release];
-                } else if (MIMETypeRegistry::isSupportedImageMIMEType(MIMEType))
-                   fragment = documentFragmentWithImageResource(frame, mainResource);                    
+    if (types.contains(WebArchivePboardType)) {
+        if (RefPtr<SharedBuffer> webArchiveBuffer = platformStrategies()->pasteboardStrategy()->bufferForType(WebArchivePboardType, m_pasteboardName)) {
+            if (RefPtr<LegacyWebArchive> coreArchive = LegacyWebArchive::create(KURL(), webArchiveBuffer.get())) {
+                if ((fragment = fragmentFromWebArchive(frame, coreArchive)))
+                    return fragment.release();
             }
         }
-        if (fragment)
-            return fragment.release();
-    } 
+    }
 
-    if ([types containsObject:NSFilenamesPboardType]) {
-        NSArray* paths = [m_pasteboard.get() propertyListForType:NSFilenamesPboardType];
-        NSEnumerator* enumerator = [paths objectEnumerator];
-        NSString* path;
+    if (types.contains(String(NSFilenamesPboardType))) {
+        Vector<String> paths;
+        platformStrategies()->pasteboardStrategy()->getPathnamesForType(paths, NSFilenamesPboardType, m_pasteboardName);
         Vector< RefPtr<Node> > refNodesVector;
         Vector<Node*> nodesVector;
 
-        while ((path = [enumerator nextObject]) != nil) {
+        for (size_t i = 0; i < paths.size(); i++) {
             // Non-image file types; _web_userVisibleString is appropriate here because this will
             // be pasted as visible text.
-            NSString *url = frame->editor()->client()->userVisibleString([NSURL fileURLWithPath:path]);
+            NSString *url = frame->editor()->client()->userVisibleString([NSURL fileURLWithPath:paths[i]]);
             RefPtr<Node> textNode = frame->document()->createTextNode(url);
             refNodesVector.append(textNode.get());
             nodesVector.append(textNode.get());
@@ -543,8 +521,8 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP
             return fragment.release();
     }
 
-    if ([types containsObject:NSHTMLPboardType]) {
-        NSString *HTMLString = [m_pasteboard.get() stringForType:NSHTMLPboardType];
+    if (types.contains(String(NSHTMLPboardType))) {
+        NSString *HTMLString = platformStrategies()->pasteboardStrategy()->stringForType(NSHTMLPboardType, m_pasteboardName);
         // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
         if ([HTMLString hasPrefix:@"Version:"]) {
             NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
@@ -553,40 +531,32 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP
             }
         }
         if ([HTMLString length] != 0 &&
-            (fragment = createFragmentFromMarkup(frame->document(), HTMLString, "", FragmentScriptingNotAllowed)))
+            (fragment = createFragmentFromMarkup(frame->document(), HTMLString, "", DisallowScriptingAndPluginContent)))
             return fragment.release();
     }
 
-    if ([types containsObject:NSRTFDPboardType] &&
-        (fragment = documentFragmentWithRtf(frame, NSRTFDPboardType)))
+    if (types.contains(String(NSRTFDPboardType)) &&
+        (fragment = documentFragmentWithRTF(frame, NSRTFDPboardType, m_pasteboardName)))
        return fragment.release();
 
-    if ([types containsObject:NSRTFPboardType] &&
-        (fragment = documentFragmentWithRtf(frame, NSRTFPboardType)))
+    if (types.contains(String(NSRTFPboardType)) &&
+        (fragment = documentFragmentWithRTF(frame, NSRTFPboardType, m_pasteboardName)))
         return fragment.release();
 
-    if ([types containsObject:NSTIFFPboardType] &&
-        (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:NSTIFFPboardType] copy] autorelease]), uniqueURLWithRelativePart(@"image.tiff"), "image/tiff", "", ""))))
+    if (types.contains(String(NSTIFFPboardType)) &&
+        (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(platformStrategies()->pasteboardStrategy()->bufferForType(NSTIFFPboardType, m_pasteboardName), uniqueURLWithRelativePart(@"image.tiff"), "image/tiff", "", ""))))
         return fragment.release();
 
-    if ([types containsObject:NSPDFPboardType] &&
-        (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:NSPDFPboardType] copy] autorelease]), uniqueURLWithRelativePart(@"application.pdf"), "application/pdf", "", ""))))
+    if (types.contains(String(NSPDFPboardType)) &&
+        (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(platformStrategies()->pasteboardStrategy()->bufferForType(NSPDFPboardType, m_pasteboardName).get(), uniqueURLWithRelativePart(@"application.pdf"), "application/pdf", "", ""))))
         return fragment.release();
 
-#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
-    if ([types containsObject:NSPICTPboardType] &&
-        (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:NSPICTPboardType] copy] autorelease]), uniqueURLWithRelativePart(@"image.pict"), "image/pict", "", ""))))
-        return fragment.release();
-#endif
-
-    // Only 10.5 and higher support setting and retrieving pasteboard types with UTIs, but we don't believe
-    // that any applications on Tiger put types for which we only have a UTI, like PNG, on the pasteboard.
-    if ([types containsObject:(NSString*)kUTTypePNG] &&
-        (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[[m_pasteboard.get() dataForType:(NSString*)kUTTypePNG] copy] autorelease]), uniqueURLWithRelativePart(@"image.png"), "image/png", "", ""))))
+    if (types.contains(String(kUTTypePNG)) &&
+        (fragment = documentFragmentWithImageResource(frame, ArchiveResource::create(platformStrategies()->pasteboardStrategy()->bufferForType(String(kUTTypePNG), m_pasteboardName), uniqueURLWithRelativePart(@"image.png"), "image/png", "", ""))))
         return fragment.release();
 
-    if ([types containsObject:NSURLPboardType]) {
-        NSURL *URL = [NSURL URLFromPasteboard:m_pasteboard.get()];
+    if (types.contains(String(NSURLPboardType))) {
+        NSURL *URL = platformStrategies()->pasteboardStrategy()->url(m_pasteboardName);
         Document* document = frame->document();
         ASSERT(document);
         if (!document)
@@ -595,20 +565,19 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP
         NSString *URLString = [URL absoluteString]; // Original data is ASCII-only, so there is no need to precompose.
         if ([URLString length] == 0)
             return nil;
-        NSString *URLTitleString = [[m_pasteboard.get() stringForType:WebURLNamePboardType] precomposedStringWithCanonicalMapping];
-        ExceptionCode ec;
+        NSString *URLTitleString = [platformStrategies()->pasteboardStrategy()->stringForType(WebURLNamePboardType, m_pasteboardName) precomposedStringWithCanonicalMapping];
         anchor->setAttribute(HTMLNames::hrefAttr, URLString);
-        anchor->appendChild(document->createTextNode(URLTitleString), ec);
+        anchor->appendChild(document->createTextNode(URLTitleString), IGNORE_EXCEPTION);
         fragment = document->createDocumentFragment();
         if (fragment) {
-            fragment->appendChild(anchor, ec);
+            fragment->appendChild(anchor, IGNORE_EXCEPTION);
             return fragment.release();
         }
     }
 
-    if (allowPlainText && [types containsObject:NSStringPboardType]) {
+    if (allowPlainText && types.contains(String(NSStringPboardType))) {
         chosePlainText = true;
-        fragment = createFragmentFromText(context.get(), [[m_pasteboard.get() stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping]);
+        fragment = createFragmentFromText(context.get(), [platformStrategies()->pasteboardStrategy()->stringForType(NSStringPboardType, m_pasteboardName) precomposedStringWithCanonicalMapping]);
         return fragment.release();
     }