Upstream iOS Clipboard and Pasteboard changes
authorddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 May 2013 02:21:12 +0000 (02:21 +0000)
committerddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 May 2013 02:21:12 +0000 (02:21 +0000)
<http://webkit.org/b/116062>

Reviewed by Darin Adler.

* WebCore.xcodeproj/project.pbxproj:
* dom/Clipboard.h:
* platform/Pasteboard.h:
* platform/ios/ClipboardIOS.h: Added.
* platform/ios/ClipboardIOS.mm: Added.
* platform/ios/PasteboardIOS.mm: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@150049 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Clipboard.h
Source/WebCore/platform/Pasteboard.h
Source/WebCore/platform/ios/ClipboardIOS.h [new file with mode: 0644]
Source/WebCore/platform/ios/ClipboardIOS.mm [new file with mode: 0644]
Source/WebCore/platform/ios/PasteboardIOS.mm [new file with mode: 0644]

index 360830a5c4b450a76e5d8543036cc76f2b4b23ad..6f62096e444d8d5aeb6b8b18d37ed0f0dc5b3866 100644 (file)
@@ -1,3 +1,17 @@
+2013-05-13  David Kilzer  <ddkilzer@apple.com>
+
+        Upstream iOS Clipboard and Pasteboard changes
+        <http://webkit.org/b/116062>
+
+        Reviewed by Darin Adler.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Clipboard.h:
+        * platform/Pasteboard.h:
+        * platform/ios/ClipboardIOS.h: Added.
+        * platform/ios/ClipboardIOS.mm: Added.
+        * platform/ios/PasteboardIOS.mm: Added.
+
 2013-05-13  Huang Dongsung  <luxtella@company100.net>
 
         [Mac] Use pageScaleFactor * deviceScaleFactor in requiresTiledLayer() and computePixelAlignment() of GraphicsLayerCA.
index 52941d2a7625eb809fc0fa6026337d13c31da791..aa86bd45411180eaa1fab8d77b344de8625b4f93 100644 (file)
                C55E38C010040D5D00A56BDB /* StorageNamespaceImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C55E38BC10040D5D00A56BDB /* StorageNamespaceImpl.cpp */; };
                C572EE1F1201C9BC007D8F82 /* JSIDBIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = C572EE1D1201C9BC007D8F82 /* JSIDBIndex.h */; };
                C57FEDE11212EE9C0097BE65 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C57FEDE01212EE9C0097BE65 /* FileSystem.cpp */; };
+               C585381913A7DD4E00A3BBEE /* ClipboardIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = C585381713A7DD4E00A3BBEE /* ClipboardIOS.h */; };
+               C585381A13A7DD4E00A3BBEE /* ClipboardIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = C585381813A7DD4E00A3BBEE /* ClipboardIOS.mm */; };
                C585A66211D4FAC5004C3E4B /* IDBBindingUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C585A66011D4FAC5004C3E4B /* IDBBindingUtilities.cpp */; };
                C585A66311D4FAC5004C3E4B /* IDBBindingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C585A66111D4FAC5004C3E4B /* IDBBindingUtilities.h */; };
                C585A67D11D4FB08004C3E4B /* JSIDBAny.h in Headers */ = {isa = PBXBuildFile; fileRef = C585A66511D4FB07004C3E4B /* JSIDBAny.h */; };
                E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = E44B4BB2141650D7002B1D8B /* SelectorChecker.h */; };
                E45322AB140CE267005A0F92 /* SelectorQuery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E45322A9140CE267005A0F92 /* SelectorQuery.cpp */; };
                E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E45322AA140CE267005A0F92 /* SelectorQuery.h */; };
+               E453901E0EAFCACA003695C8 /* PasteboardIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = E45390190EAFCACA003695C8 /* PasteboardIOS.mm */; };
                E45390460EAFD637003695C8 /* SharedTimerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = E45390350EAFD637003695C8 /* SharedTimerIOS.mm */; };
                E462A4A1113E71BE004A4220 /* IntPointHash.h in Headers */ = {isa = PBXBuildFile; fileRef = E462A4A0113E71BE004A4220 /* IntPointHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E47127CA163438A100ED6F5A /* StyleInvalidationAnalysis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E47A97CE163059FC005DCD99 /* StyleInvalidationAnalysis.cpp */; };
                C55E38BC10040D5D00A56BDB /* StorageNamespaceImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageNamespaceImpl.cpp; sourceTree = "<group>"; };
                C572EE1D1201C9BC007D8F82 /* JSIDBIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSIDBIndex.h; sourceTree = "<group>"; };
                C57FEDE01212EE9C0097BE65 /* FileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSystem.cpp; sourceTree = "<group>"; };
+               C585381713A7DD4E00A3BBEE /* ClipboardIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClipboardIOS.h; path = ios/ClipboardIOS.h; sourceTree = "<group>"; };
+               C585381813A7DD4E00A3BBEE /* ClipboardIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ClipboardIOS.mm; path = ios/ClipboardIOS.mm; sourceTree = "<group>"; };
                C585A66011D4FAC5004C3E4B /* IDBBindingUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBBindingUtilities.cpp; sourceTree = "<group>"; };
                C585A66111D4FAC5004C3E4B /* IDBBindingUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBBindingUtilities.h; sourceTree = "<group>"; };
                C585A66511D4FB07004C3E4B /* JSIDBAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSIDBAny.h; sourceTree = "<group>"; };
                E44B4BB2141650D7002B1D8B /* SelectorChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorChecker.h; sourceTree = "<group>"; };
                E45322A9140CE267005A0F92 /* SelectorQuery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorQuery.cpp; sourceTree = "<group>"; };
                E45322AA140CE267005A0F92 /* SelectorQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorQuery.h; sourceTree = "<group>"; };
+               E45390190EAFCACA003695C8 /* PasteboardIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PasteboardIOS.mm; path = ios/PasteboardIOS.mm; sourceTree = "<group>"; };
                E45390350EAFD637003695C8 /* SharedTimerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SharedTimerIOS.mm; path = ios/SharedTimerIOS.mm; sourceTree = "<group>"; };
                E462A4A0113E71BE004A4220 /* IntPointHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntPointHash.h; sourceTree = "<group>"; };
                E4778B7D115A581A00B5D372 /* JSCustomEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomEvent.cpp; sourceTree = "<group>"; };
                A59E3C1B11580F340072928E /* ios */ = {
                        isa = PBXGroup;
                        children = (
+                               C585381713A7DD4E00A3BBEE /* ClipboardIOS.h */,
+                               C585381813A7DD4E00A3BBEE /* ClipboardIOS.mm */,
                                2655414B1489AA2B000DFC5D /* CursorIOS.cpp */,
                                26F40D4914904A6300CA67C4 /* EventLoopIOS.mm */,
                                26C17A3C1491D2D400D12BA2 /* FileSystemIOS.h */,
                                26C17A3D1491D2D400D12BA2 /* FileSystemIOS.mm */,
                                265541371489811C000DFC5D /* KeyEventCodesIOS.h */,
                                265541381489811C000DFC5D /* KeyEventIOS.mm */,
+                               E45390190EAFCACA003695C8 /* PasteboardIOS.mm */,
                                E45390350EAFD637003695C8 /* SharedTimerIOS.mm */,
                        );
                        name = ios;
                                85031B3E0A44EFC700F992E0 /* Clipboard.h in Headers */,
                                4B8AF4AA0B1CE02B00687690 /* ClipboardAccessPolicy.h in Headers */,
                                85031B400A44EFC700F992E0 /* ClipboardEvent.h in Headers */,
+                               C585381913A7DD4E00A3BBEE /* ClipboardIOS.h in Headers */,
                                93F199E708245E59001E9ABC /* ClipboardMac.h in Headers */,
                                FB92DF4B15FED08700994433 /* ClipPathOperation.h in Headers */,
                                97AABD1314FA09D5007457AE /* CloseEvent.h in Headers */,
                                BCC065800F3CE1B700CD2D87 /* ClientRectList.cpp in Sources */,
                                A784941B0B5FE507001E237A /* Clipboard.cpp in Sources */,
                                85031B3F0A44EFC700F992E0 /* ClipboardEvent.cpp in Sources */,
+                               C585381A13A7DD4E00A3BBEE /* ClipboardIOS.mm in Sources */,
                                93F19AFF08245E59001E9ABC /* ClipboardMac.mm in Sources */,
                                CDEA76351460B71A008B31F1 /* Clock.cpp in Sources */,
                                CDEA76341460B56F008B31F1 /* ClockGeneric.cpp in Sources */,
                                FD31601912B0267600C1A359 /* PannerNode.cpp in Sources */,
                                447958051643B4B2001E0A7F /* ParsedContentType.cpp in Sources */,
                                F55B3DC91251F12D003EF269 /* PasswordInputType.cpp in Sources */,
+                               E453901E0EAFCACA003695C8 /* PasteboardIOS.mm in Sources */,
                                4B2709830AF2E5E00065127F /* PasteboardMac.mm in Sources */,
                                B275357F0B053814002CE64F /* Path.cpp in Sources */,
                                B27535630B053814002CE64F /* PathCG.cpp in Sources */,
index 6e831c98d706169b6512361e368f6332f5e17134..cb67c66accc61a82306ebcf8438b4ccc4fa77bd2 100644 (file)
@@ -34,7 +34,7 @@
 // This DOM object now works by calling through to classes in the platform layer.
 // Specifically, the class currently named Pasteboard. The legacy style instead
 // uses this as an abstract base class.
-#define WTF_USE_LEGACY_STYLE_ABSTRACT_CLIPBOARD_CLASS !PLATFORM(MAC)
+#define WTF_USE_LEGACY_STYLE_ABSTRACT_CLIPBOARD_CLASS (!PLATFORM(MAC) || PLATFORM(IOS))
 
 #if USE(LEGACY_STYLE_ABSTRACT_CLIPBOARD_CLASS)
 #define LEGACY_VIRTUAL virtual
index 696514009a8ab837d34124a4853bde781c13036a..f71c75d74b01f7fad67b1f51b8e69caf1943634d 100644 (file)
@@ -20,7 +20,7 @@
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef Pasteboard_h
@@ -53,7 +53,12 @@ typedef struct HWND__* HWND;
 namespace WebCore {
 
 #if PLATFORM(MAC)
+#if PLATFORM(IOS)
+// FIXME: This is only temporary until Pasteboard is refactored for iOS.
+extern NSString *WebArchivePboardType;
+#else
 extern const char* WebArchivePboardType;
+#endif
 extern const char* WebSmartPastePboardType;
 extern const char* WebURLNamePboardType;
 extern const char* WebURLPboardType;
@@ -100,8 +105,14 @@ public:
     bool writeString(const String& type, const String& data);
     void writeSelection(Range*, bool canSmartCopyOrDelete, Frame*, ShouldSerializeSelectedTextForClipboard = DefaultSelectedTextType);
     void writePlainText(const String&, SmartReplaceOption);
+#if !PLATFORM(IOS)
     void writeURL(const KURL&, const String&, Frame* = 0);
     void writeImage(Node*, const KURL&, const String& title);
+#else
+    void writeImage(Node*, Frame*);
+    void writePlainText(const String&, Frame*);
+    static NSArray* supportedPasteboardTypes();
+#endif
     void writeClipboard(Clipboard*);
 
     void clear();
@@ -129,11 +140,15 @@ public:
 private:
     Pasteboard();
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) && !PLATFORM(IOS)
     String m_pasteboardName;
     long m_changeCount;
 #endif
 
+#if PLATFORM(IOS)
+    PassRefPtr<DocumentFragment> documentFragmentForPasteboardItemAtIndex(Frame*, int index, bool allowPlainText, bool& chosePlainText);
+#endif
+
 #if PLATFORM(WIN)
     HWND m_owner;
 #endif
diff --git a/Source/WebCore/platform/ios/ClipboardIOS.h b/Source/WebCore/platform/ios/ClipboardIOS.h
new file mode 100644 (file)
index 0000000..b2aef5c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ClipboardIOS_h
+#define ClipboardIOS_h
+
+#include "CachedResourceClient.h"
+#include "Clipboard.h"
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+class Frame;
+class FileList;
+
+class ClipboardIOS : public Clipboard, public CachedResourceClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<ClipboardIOS> create(ClipboardType clipboardType, ClipboardAccessPolicy policy, Frame* frame)
+    {
+        return adoptRef(new ClipboardIOS(clipboardType, policy, frame));
+    }
+
+    virtual ~ClipboardIOS();
+
+    virtual void clearData(const String& type) OVERRIDE;
+    virtual void clearAllData() OVERRIDE;
+    virtual String getData(const String& type) const OVERRIDE;
+    virtual bool setData(const String& type, const String& data) OVERRIDE;
+
+    virtual bool hasData() OVERRIDE;
+
+    // Extensions beyond IE's API.
+    virtual ListHashSet<String> types() const OVERRIDE;
+    virtual PassRefPtr<FileList> files() const OVERRIDE;
+
+    virtual void setDragImage(CachedImage*, const IntPoint&) OVERRIDE;
+    virtual void setDragImageElement(Node *, const IntPoint&) OVERRIDE;
+
+    virtual DragImageRef createDragImage(IntPoint& dragLoc) const OVERRIDE;
+#if ENABLE(DRAG_SUPPORT)
+    virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*) OVERRIDE;
+#endif
+    virtual void writeRange(Range*, Frame*) OVERRIDE;
+    virtual void writeURL(const KURL&, const String&, Frame*) OVERRIDE;
+    virtual void writePlainText(const String&) OVERRIDE;
+
+private:
+    ClipboardIOS(ClipboardType, ClipboardAccessPolicy, Frame*);
+
+    int m_changeCount;
+    Frame* m_frame; // Used to access the UIPasteboard through the editor client.
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/ios/ClipboardIOS.mm b/Source/WebCore/platform/ios/ClipboardIOS.mm
new file mode 100644 (file)
index 0000000..8ddf4c0
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "ClipboardIOS.h"
+
+#import "DragData.h"
+#import "Editor.h"
+#import "EditorClient.h"
+#import "FileList.h"
+#import "Frame.h"
+#import "Pasteboard.h"
+
+#include "SoftLinking.h"
+#include <MobileCoreServices/MobileCoreServices.h>
+
+SOFT_LINK_FRAMEWORK(MobileCoreServices)
+
+SOFT_LINK(MobileCoreServices, UTTypeCreatePreferredIdentifierForTag, CFStringRef, (CFStringRef inTagClass, CFStringRef inTag, CFStringRef inConformingToUTI), (inTagClass, inTag, inConformingToUTI))
+SOFT_LINK(MobileCoreServices, UTTypeCopyPreferredTagWithClass, CFStringRef, (CFStringRef inUTI, CFStringRef inTagClass), (inUTI, inTagClass))
+
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeText, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeURL, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTagClassMIMEType, CFStringRef)
+
+#define kUTTypeText getkUTTypeText()
+#define kUTTypeURL  getkUTTypeURL()
+#define kUTTypeTIFF getkUTTypeTIFF()
+#define kUTTagClassMIMEType getkUTTagClassMIMEType()
+
+namespace WebCore {
+
+PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData*, Frame* frame)
+{
+    return ClipboardIOS::create(DragAndDrop, policy, frame);
+}
+
+ClipboardIOS::ClipboardIOS(ClipboardType clipboardType, ClipboardAccessPolicy policy, Frame* frame)
+    : Clipboard(policy, clipboardType)
+    , m_frame(frame)
+{
+    m_changeCount = m_frame->editor()->client()->pasteboardChangeCount();
+}
+
+ClipboardIOS::~ClipboardIOS()
+{
+}
+
+bool ClipboardIOS::hasData()
+{
+    return m_frame->editor()->client()->getPasteboardItemsCount() != 0;
+}
+
+static String utiTypeFromCocoaType(NSString* type)
+{
+    RetainPtr<CFStringRef> utiType = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (CFStringRef)type, NULL));
+    if (utiType) {
+        RetainPtr<CFStringRef> mimeType = adoptCF(UTTypeCopyPreferredTagWithClass(utiType.get(), kUTTagClassMIMEType));
+        if (mimeType)
+            return String(mimeType.get());
+    }
+    return String();
+}
+
+static RetainPtr<NSString> cocoaTypeFromHTMLClipboardType(const String& type)
+{
+    String qType = type.stripWhiteSpace();
+
+    if (qType == "Text")
+        return (NSString*)kUTTypeText;
+    if (qType == "URL")
+        return (NSString*)kUTTypeURL;
+
+    // Ignore any trailing charset - JS strings are Unicode, which encapsulates the charset issue.
+    if (qType.startsWith(ASCIILiteral("text/plain")))
+        return (NSString*)kUTTypeText;
+    if (qType == "text/uri-list")
+        // Special case because UTI doesn't work with Cocoa's URL type.
+        return (NSString*)kUTTypeURL;
+
+    // Try UTI now.
+    NSString *pbType = utiTypeFromCocoaType(qType);
+    if (pbType)
+        return pbType;
+
+    // No mapping, just pass the whole string though.
+    return (NSString*)qType;
+}
+
+static void addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, NSString* cocoaType)
+{
+    // UTI may not do these right, so make sure we get the right, predictable result.
+    if ([cocoaType isEqualToString:(NSString*)kUTTypeText]) {
+        resultTypes.add(ASCIILiteral("text/plain"));
+        return;
+    }
+    if ([cocoaType isEqualToString:(NSString*)kUTTypeURL]) {
+        resultTypes.add(ASCIILiteral("text/uri-list"));
+        return;
+    }
+    String utiType = utiTypeFromCocoaType(cocoaType);
+    if (!utiType.isEmpty()) {
+        resultTypes.add(utiType);
+        return;
+    }
+    // No mapping, just pass the whole string though.
+    resultTypes.add(cocoaType);
+}
+
+void ClipboardIOS::clearData(const String& type)
+{
+    if (!canWriteData())
+        return;
+
+    // Note UIPasteboard enforces changeCount itself on writing - can't write if not the owner.
+
+    if (RetainPtr<NSString> cocoaType = cocoaTypeFromHTMLClipboardType(type)) {
+        RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
+        [representations.get() setValue:0 forKey:cocoaType.get()];
+        m_frame->editor()->client()->writeDataToPasteboard(representations.get());
+    }
+}
+
+void ClipboardIOS::clearAllData()
+{
+    if (!canWriteData())
+        return;
+
+    RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
+    m_frame->editor()->client()->writeDataToPasteboard(representations.get());
+}
+
+String ClipboardIOS::getData(const String& type) const
+{
+    if (!canReadData())
+        return String();
+
+    RetainPtr<NSString> cocoaType = cocoaTypeFromHTMLClipboardType(type);
+    NSString *cocoaValue = nil;
+
+    // Grab the value off the pasteboard corresponding to the cocoaType.
+    RetainPtr<NSArray> pasteboardItem = m_frame->editor()->client()->readDataFromPasteboard(cocoaType.get(), 0);
+
+    if ([pasteboardItem.get() count] == 0)
+        return String();
+
+    if ([cocoaType.get() isEqualToString:(NSString*)kUTTypeURL]) {
+        id value = [pasteboardItem.get() objectAtIndex:0];
+        if (![value isKindOfClass:[NSURL class]]) {
+            ASSERT([value isKindOfClass:[NSURL class]]);
+            return String();
+        }
+        NSURL* absoluteURL = (NSURL*)value;
+
+        if (absoluteURL)
+            cocoaValue = [absoluteURL absoluteString];
+    } else if ([cocoaType.get() isEqualToString:(NSString*)kUTTypeText]) {
+        id value = [pasteboardItem.get() objectAtIndex:0];
+        if (![value isKindOfClass:[NSString class]]) {
+            ASSERT([value isKindOfClass:[NSString class]]);
+            return String();
+        }
+
+        cocoaValue = [(NSString*)value precomposedStringWithCanonicalMapping];
+    } else if (cocoaType) {
+        ASSERT([pasteboardItem.get() count] == 1);
+        id value = [pasteboardItem.get() objectAtIndex:0];
+        if (![value isKindOfClass:[NSData class]]) {
+            ASSERT([value isKindOfClass:[NSData class]]);
+            return String();
+        }
+        cocoaValue = [[[NSString alloc] initWithData:(NSData *)value encoding:NSUTF8StringEncoding] autorelease];
+    }
+
+    // Enforce changeCount ourselves for security.  We check after reading instead of before to be
+    // sure it doesn't change between our testing the change count and accessing the data.
+    if (cocoaValue && m_changeCount == m_frame->editor()->client()->pasteboardChangeCount())
+        return cocoaValue;
+
+    return String();
+}
+
+bool ClipboardIOS::setData(const String& type, const String& data)
+{
+    if (!canWriteData())
+        return false;
+
+    RetainPtr<NSString> cocoaType = cocoaTypeFromHTMLClipboardType(type);
+    NSString *cocoaData = data;
+
+    RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
+
+    if ([cocoaType.get() isEqualToString:(NSString*)kUTTypeURL]) {
+        RetainPtr<NSURL> url = adoptNS([[NSURL alloc] initWithString:cocoaData]);
+        [representations.get() setValue:url.get() forKey:(NSString*)kUTTypeURL];
+        m_frame->editor()->client()->writeDataToPasteboard(representations.get());
+        return true;
+    }
+
+    if (cocoaType) {
+        // Everything else we know of goes on the pboard as the original string
+        // we received as parameter.
+        [representations.get() setValue:cocoaData forKey:cocoaType.get()];
+        m_frame->editor()->client()->writeDataToPasteboard(representations.get());
+        return true;
+    }
+
+    return false;
+}
+
+ListHashSet<String> ClipboardIOS::types() const
+{
+    if (!canReadTypes())
+        return ListHashSet<String>();
+
+    NSArray* types = Pasteboard::supportedPasteboardTypes();
+
+    // Enforce changeCount ourselves for security.  We check after reading instead of before to be
+    // sure it doesn't change between our testing the change count and accessing the data.
+    if (m_changeCount != m_frame->editor()->client()->pasteboardChangeCount())
+        return ListHashSet<String>();
+
+    ListHashSet<String> result;
+    NSUInteger count = [types count];
+    for (NSUInteger i = 0; i < count; i++) {
+        NSString* pbType = [types objectAtIndex:i];
+        addHTMLClipboardTypesForCocoaType(result, pbType);
+    }
+
+    return result;
+}
+
+PassRefPtr<FileList> ClipboardIOS::files() const
+{
+    return 0;
+}
+
+void ClipboardIOS::writeRange(Range* range, Frame* frame)
+{
+    ASSERT(range);
+    ASSERT(frame);
+    Pasteboard::generalPasteboard()->writeSelection(range, frame->editor()->smartInsertDeleteEnabled() && frame->selection()->granularity() == WordGranularity, frame);
+}
+
+void ClipboardIOS::writePlainText(const String& text)
+{
+    Pasteboard::generalPasteboard()->writePlainText(text, m_frame);
+}
+
+void ClipboardIOS::writeURL(const KURL&, const String&, Frame*)
+{
+}
+
+#if ENABLE(DRAG_SUPPORT)
+void ClipboardIOS::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
+{
+    ASSERT(frame);
+    if (Page* page = frame->page())
+        page->dragController()->client()->declareAndWriteDragImage(m_pasteboard.get(), kit(element), url, title, frame);
+}
+#endif // ENABLE(DRAG_SUPPORT)
+
+DragImageRef ClipboardIOS::createDragImage(IntPoint&) const
+{
+    return 0;
+}
+
+void ClipboardIOS::setDragImage(CachedImage*, const IntPoint&)
+{
+}
+
+void ClipboardIOS::setDragImageElement(Node *, const IntPoint&)
+{
+}
+
+}
diff --git a/Source/WebCore/platform/ios/PasteboardIOS.mm b/Source/WebCore/platform/ios/PasteboardIOS.mm
new file mode 100644 (file)
index 0000000..d7e55cf
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2007, 2008, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "Pasteboard.h"
+
+#import "CachedImage.h"
+#import "DOMRangeInternal.h"
+#import "Document.h"
+#import "DocumentFragment.h"
+#import "DocumentLoader.h"
+#import "Editor.h"
+#import "EditorClient.h"
+#import "Frame.h"
+#import "FrameLoader.h"
+#import "FrameLoaderClient.h"
+#import "HTMLElement.h"
+#import "HTMLNames.h"
+#import "HTMLParserIdioms.h"
+#import "KURL.h"
+#import "LegacyWebArchive.h"
+#import "Page.h"
+#import "RenderImage.h"
+#import "SoftLinking.h"
+#import "Text.h"
+#import "htmlediting.h"
+#import "markup.h"
+#import "WebNSAttributedStringExtras.h"
+#import <MobileCoreServices/MobileCoreServices.h>
+
+@interface NSHTMLReader
+- (id)initWithDOMRange:(DOMRange *)domRange;
+- (NSAttributedString *)attributedString;
+@end
+
+@interface NSAttributedString (NSAttributedStringKitAdditions)
+- (id)initWithRTF:(NSData *)data documentAttributes:(NSDictionary **)dict;
+- (id)initWithRTFD:(NSData *)data documentAttributes:(NSDictionary **)dict;
+- (NSData *)RTFFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict;
+- (NSData *)RTFDFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict;
+- (BOOL)containsAttachments;
+@end
+
+SOFT_LINK_PRIVATE_FRAMEWORK(UIFoundation)
+SOFT_LINK_CLASS(UIFoundation, NSHTMLReader)
+
+SOFT_LINK_FRAMEWORK(MobileCoreServices)
+
+SOFT_LINK(MobileCoreServices, UTTypeConformsTo, Boolean, (CFStringRef inUTI, CFStringRef inConformsToUTI), (inUTI, inConformsToUTI))
+SOFT_LINK(MobileCoreServices, UTTypeCreatePreferredIdentifierForTag, CFStringRef, (CFStringRef inTagClass, CFStringRef inTag, CFStringRef inConformingToUTI), (inTagClass, inTag, inConformingToUTI))
+SOFT_LINK(MobileCoreServices, UTTypeCopyPreferredTagWithClass, CFStringRef, (CFStringRef inUTI, CFStringRef inTagClass), (inUTI, inTagClass))
+
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeText, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypePNG, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeJPEG, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeURL, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeTIFF, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeGIF, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTagClassMIMEType, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTagClassFilenameExtension, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeRTFD, CFStringRef)
+SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeRTF, CFStringRef)
+
+#define kUTTypeText getkUTTypeText()
+#define kUTTypePNG  getkUTTypePNG()
+#define kUTTypeJPEG getkUTTypeJPEG()
+#define kUTTypeURL  getkUTTypeURL()
+#define kUTTypeTIFF getkUTTypeTIFF()
+#define kUTTypeGIF  getkUTTypeGIF()
+#define kUTTagClassMIMEType getkUTTagClassMIMEType()
+#define kUTTagClassFilenameExtension getkUTTagClassFilenameExtension()
+#define kUTTypeRTFD getkUTTypeRTFD()
+#define kUTTypeRTF getkUTTypeRTF()
+
+SOFT_LINK_FRAMEWORK(AppSupport)
+SOFT_LINK(AppSupport, CPSharedResourcesDirectory, CFStringRef, (void), ())
+
+namespace WebCore {
+
+NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type";
+
+Pasteboard* Pasteboard::generalPasteboard()
+{
+    static Pasteboard* pasteboard = new Pasteboard();
+    return pasteboard;
+}
+
+Pasteboard::Pasteboard()
+{
+}
+
+void Pasteboard::clear()
+{
+}
+
+String Pasteboard::getStringSelection(Frame* frame, ShouldSerializeSelectedTextForClipboard shouldSerializeSelectedTextForClipboard)
+{
+    String text = shouldSerializeSelectedTextForClipboard == IncludeImageAltTextForClipboard ? frame->editor()->selectedTextForClipboard() : frame->editor()->selectedText();
+    text.replace(noBreakSpace, ' ');
+    return text;
+}
+
+void Pasteboard::writeSelection(Range* selectedRange, bool /*canSmartCopyOrDelete*/, Frame *frame, ShouldSerializeSelectedTextForClipboard shouldSerializeSelectedTextForClipboard)
+{
+    ASSERT(selectedRange);
+    ASSERT(frame);
+
+    // If the selection is at the beginning of content inside an anchor tag
+    // we move the selection start to include the anchor.
+    ExceptionCode ec;
+    Node* commonAncestor = selectedRange->commonAncestorContainer(ec);
+    ASSERT(commonAncestor);
+    Node* enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(commonAncestor), HTMLNames::aTag);
+    if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(selectedRange->startPosition().anchorNode()), selectedRange->startPosition()) >= 0)
+        selectedRange->setStart(enclosingAnchor, 0, ec);
+
+    frame->editor()->client()->didSetSelectionTypesForPasteboard();
+
+    RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
+
+    // Put WebArchive on the pasteboard.
+    RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
+    RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
+    if (data)
+        [representations.get() setValue:(NSData *)data.get() forKey:WebArchivePboardType];
+
+    RetainPtr<NSHTMLReader> converter = adoptNS([[getNSHTMLReaderClass() alloc] initWithDOMRange:kit(selectedRange)]);
+    if (converter) {
+        NSAttributedString *attributedString = [converter.get() attributedString];
+        NSData* RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
+        if (RTFDData)
+            [representations.get() setValue:RTFDData forKey:(NSString *)kUTTypeRTFD];
+        if ([attributedString containsAttachments])
+            attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
+        NSData* RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
+        if (RTFData)
+            [representations.get() setValue:RTFData forKey:(NSString *)kUTTypeRTF];
+    }
+
+    // Put plain string on the pasteboard.
+    [representations.get() setValue:getStringSelection(frame, shouldSerializeSelectedTextForClipboard) forKey:(NSString *)kUTTypeText];
+
+    frame->editor()->client()->writeDataToPasteboard(representations.get());
+}
+
+void Pasteboard::writePlainText(const String& text, Frame *frame)
+{
+    ASSERT(frame);
+
+    RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
+    [representations.get() setValue:text forKey:(NSString *)kUTTypeText];
+    frame->editor()->client()->writeDataToPasteboard(representations.get());
+}
+
+void Pasteboard::writeImage(Node* node, Frame* frame)
+{
+    ASSERT(node);
+
+    if (!(node->renderer() && node->renderer()->isImage()))
+        return;
+
+    RenderImage* renderer = toRenderImage(node->renderer());
+    CachedImage* cachedImage = renderer->cachedImage();
+    if (!cachedImage || cachedImage->errorOccurred())
+        return;
+
+    Image* image = cachedImage->imageForRenderer(renderer);
+    ASSERT(image);
+
+    RetainPtr<NSData> imageData = image->data()->createNSData();
+
+    if (!imageData)
+        return;
+
+    RetainPtr<NSMutableDictionary> dictionary = adoptNS([[NSMutableDictionary alloc] init]);
+    NSString *mimeType = cachedImage->response().mimeType();
+    RetainPtr<NSString> uti = adoptCF((NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (CFStringRef)mimeType, NULL));
+    if (uti) {
+        [dictionary.get() setObject:imageData.get() forKey:uti.get()];
+        [dictionary.get() setObject:(NSString *)node->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(static_cast<HTMLElement*>(node)->getAttribute("src"))) forKey:(NSString *)kUTTypeURL];
+    }
+    frame->editor()->client()->writeDataToPasteboard(dictionary.get());
+}
+
+void Pasteboard::writePlainText(const String&, SmartReplaceOption)
+{
+}
+
+void Pasteboard::writeClipboard(Clipboard*)
+{
+}
+
+bool Pasteboard::canSmartReplace()
+{
+    return false;
+}
+
+String Pasteboard::plainText(Frame* frame)
+{
+    RetainPtr<NSArray> pasteboardItem = frame->editor()->client()->readDataFromPasteboard((NSString *)kUTTypeText, 0);
+
+    if ([pasteboardItem.get() count] == 0)
+        return String();
+
+    id value = [pasteboardItem.get() objectAtIndex:0];
+    if ([value isKindOfClass:[NSString class]])
+        return String(value);
+
+    ASSERT([value isKindOfClass:[NSString class]]);
+    return String();
+}
+
+static NSArray* supportedImageTypes()
+{
+    return [NSArray arrayWithObjects:(id)kUTTypePNG, (id)kUTTypeTIFF, (id)kUTTypeJPEG, (id)kUTTypeGIF, nil];
+}
+
+NSArray* Pasteboard::supportedPasteboardTypes()
+{
+    return [NSArray arrayWithObjects:(id)WebArchivePboardType, (id)kUTTypePNG, (id)kUTTypeTIFF, (id)kUTTypeJPEG, (id)kUTTypeGIF, (id)kUTTypeURL, (id)kUTTypeText, (id)kUTTypeRTFD, (id)kUTTypeRTF, nil];
+}
+
+#define WebDataProtocolScheme @"webkit-fake-url"
+
+static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
+{
+    CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
+    NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
+    CFRelease(UUIDRef);
+    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", WebDataProtocolScheme, UUIDString, relativePart]];
+    CFRelease(UUIDString);
+
+    return URL;
+}
+
+static PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource)
+{
+    RefPtr<Element> imageElement = frame->document()->createElement(HTMLNames::imgTag, false);
+
+    if (DocumentLoader* loader = frame->loader()->documentLoader())
+        loader->addArchiveResource(resource.get());
+
+    NSURL *URL = resource->url();
+    imageElement->setAttribute(HTMLNames::srcAttr, [URL isFileURL] ? [URL absoluteString] : resource->url());
+    RefPtr<DocumentFragment> fragment = frame->document()->createDocumentFragment();
+    fragment->appendChild(imageElement.release());
+    return fragment.release();
+}
+
+static PassRefPtr<DocumentFragment> documentFragmentWithLink(Document* document, const String& urlString)
+{
+    RefPtr<Element> anchorElement = document->createElement(HTMLNames::aTag, false);
+
+    anchorElement->setAttribute(HTMLNames::hrefAttr, urlString);
+    anchorElement->appendChild(document->createTextNode(urlString));
+
+    RefPtr<DocumentFragment> fragment = document->createDocumentFragment();
+    fragment->appendChild(anchorElement.release());
+    return fragment.release();
+}
+
+static PassRefPtr<DocumentFragment> documentFragmentWithRTF(Frame* frame, NSString *pasteboardType, NSData* pasteboardData)
+{
+    if (!frame || !frame->document() || !frame->document()->isHTMLDocument())
+        return 0;
+
+    RetainPtr<NSAttributedString> string;
+    if ([pasteboardType isEqualToString:(NSString*)kUTTypeRTFD])
+        string = [[NSAttributedString alloc] initWithRTFD:pasteboardData documentAttributes:NULL];
+
+    if (!string)
+        string = [[NSAttributedString alloc] initWithRTF:pasteboardData documentAttributes:NULL];
+
+    if (!string)
+        return 0;
+
+    bool wasDeferringCallbacks = frame->page()->defersLoading();
+    if (!wasDeferringCallbacks)
+        frame->page()->setDefersLoading(true);
+
+    Vector<RefPtr<ArchiveResource> > resources;
+    RefPtr<DocumentFragment> fragment = frame->editor()->client()->documentFragmentFromAttributedString(string.get(), resources);
+
+    size_t size = resources.size();
+    if (size) {
+        DocumentLoader* loader = frame->loader()->documentLoader();
+        for (size_t i = 0; i < size; ++i)
+            loader->addArchiveResource(resources[i]);
+    }
+
+    if (!wasDeferringCallbacks)
+        frame->page()->setDefersLoading(false);
+
+    return fragment.release();
+}
+
+PassRefPtr<DocumentFragment> Pasteboard::documentFragmentForPasteboardItemAtIndex(Frame* frame, int index, bool allowPlainText, bool& chosePlainText)
+{
+    RefPtr<DocumentFragment> fragment = frame->editor()->client()->documentFragmentFromDelegate(index);
+    if (fragment)
+        return fragment.release();
+
+    // First try to ask the client about the supported types. It will return null if the client
+    // has no selection.
+    NSArray *supportedTypes = frame->editor()->client()->supportedPasteboardTypesForCurrentSelection();
+    if (!supportedTypes)
+        supportedTypes = supportedPasteboardTypes();
+    int numberOfTypes = [supportedTypes count];
+
+    for (int i = 0; i < numberOfTypes; i++) {
+        NSString *type = [supportedTypes objectAtIndex:i];
+        RetainPtr<NSArray> pasteboardItem = frame->editor()->client()->readDataFromPasteboard(type, index);
+
+        if ([pasteboardItem.get() count] == 0)
+            continue;
+
+        if ([type isEqualToString:WebArchivePboardType]) {
+            if (!frame->document())
+                return 0;
+
+            // We put [WebArchive data] on the pasteboard in -copy: instead of the archive itself until there is API to provide the WebArchive.
+            NSData *data = [pasteboardItem.get() objectAtIndex:0];
+            RefPtr<LegacyWebArchive> coreArchive = LegacyWebArchive::create(SharedBuffer::wrapNSData(data).get());
+            if (coreArchive) {
+                RefPtr<ArchiveResource> mainResource = coreArchive->mainResource();
+                if (mainResource) {
+                    NSString *MIMEType = mainResource->mimeType();
+                    if (frame->loader()->client()->canShowMIMETypeAsHTML(MIMEType)) {
+                        RetainPtr<NSString> markupString = adoptNS([[NSString alloc] initWithData:[mainResource->data()->createNSData() autorelease] encoding:NSUTF8StringEncoding]);
+                        if (DocumentLoader* loader = frame->loader()->documentLoader())
+                            loader->addAllArchiveResources(coreArchive.get());
+
+                        fragment = createFragmentFromMarkup(frame->document(), markupString.get(), mainResource->url(), DisallowScriptingContent);
+                    }
+                }
+                if (fragment)
+                    return fragment.release();
+            }
+        }
+
+        if ([type isEqualToString:(NSString *)kUTTypeRTFD])
+            return documentFragmentWithRTF(frame, (NSString *)kUTTypeRTFD, [pasteboardItem.get() objectAtIndex:0]);
+
+        if ([type isEqualToString:(NSString *)kUTTypeRTF])
+            return documentFragmentWithRTF(frame, (NSString *)kUTTypeRTF, [pasteboardItem.get() objectAtIndex:0]);
+
+        if ([supportedImageTypes() containsObject:type]) {
+            RetainPtr<NSString> filenameExtension = adoptNS((NSString *)UTTypeCopyPreferredTagWithClass((CFStringRef)type, kUTTagClassFilenameExtension));
+            NSString *relativeURLPart = [@"image" stringByAppendingString:filenameExtension.get()];
+            RetainPtr<NSString> mimeType = adoptNS((NSString *)UTTypeCopyPreferredTagWithClass((CFStringRef)type, kUTTagClassMIMEType));
+            NSData *data = [pasteboardItem.get() objectAtIndex:0];
+            return documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), uniqueURLWithRelativePart(relativeURLPart), mimeType.get(), "", ""));
+        }
+        if ([type isEqualToString:(NSString *)kUTTypeURL]) {
+            id value = [pasteboardItem.get() objectAtIndex:0];
+            if (![value isKindOfClass:[NSURL class]]) {
+                ASSERT([value isKindOfClass:[NSURL class]]);
+                return 0;
+            }
+            NSURL *url = (NSURL *)value;
+
+            if (!frame->editor()->client()->hasRichlyEditableSelection()) {
+                fragment = createFragmentFromText(frame->selection()->toNormalizedRange().get(), [url absoluteString]);
+                if (fragment)
+                    return fragment.release();
+            }
+
+            if ([url isFileURL]) {
+                NSString *localPath = [url relativePath];
+                // Only allow url attachments from ~/Media for now.
+                if (![localPath hasPrefix:[(NSString *)CPSharedResourcesDirectory() stringByAppendingString:@"/Media/DCIM/"]])
+                    continue;
+
+                RetainPtr<NSString> fileType = adoptNS((NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[localPath pathExtension], NULL));
+                NSData *data = [NSData dataWithContentsOfFile:localPath];
+                if (UTTypeConformsTo((CFStringRef)fileType.get(), kUTTypePNG))
+                    return documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), uniqueURLWithRelativePart(@"image.png"), @"image/png", "", ""));
+                else if (UTTypeConformsTo((CFStringRef)fileType.get(), kUTTypeJPEG))
+                    return documentFragmentWithImageResource(frame, ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), uniqueURLWithRelativePart(@"image.jpg"), @"image/jpg", "", ""));
+            } else {
+                // Create a link with URL text.
+                return documentFragmentWithLink(frame->document(), [url absoluteString]);
+            }
+        }
+        if (allowPlainText && [type isEqualToString:(NSString *)kUTTypeText]) {
+            id value = [pasteboardItem.get() objectAtIndex:0];
+            if (![value isKindOfClass:[NSString class]]) {
+                ASSERT([value isKindOfClass:[NSString class]]);
+                return 0;
+            }
+
+            chosePlainText = true;
+            fragment = createFragmentFromText(frame->selection()->toNormalizedRange().get(), (NSString*)value);
+            if (fragment)
+                return fragment.release();
+        }
+    }
+
+    return 0;
+}
+
+PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> /*context*/, bool allowPlainText, bool& chosePlainText)
+{
+    chosePlainText = false;
+
+    if (!frame)
+        return 0;
+
+    int numberOfItems = frame->editor()->client()->getPasteboardItemsCount();
+
+    if (!numberOfItems)
+        return 0;
+
+    // In the common case there is just one item on the pasteboard, avoid the expense of transferring the content of
+    // fragmentForCurrentItem to the main fragment.
+    RefPtr<DocumentFragment> fragment = documentFragmentForPasteboardItemAtIndex(frame, 0, allowPlainText, chosePlainText);
+
+    for (int i = 1; i < numberOfItems; i++) {
+        RefPtr<DocumentFragment> fragmentForCurrentItem = documentFragmentForPasteboardItemAtIndex(frame, i, allowPlainText, chosePlainText);
+        if (!fragment)
+            fragment = fragmentForCurrentItem;
+        else if (fragmentForCurrentItem && fragmentForCurrentItem->firstChild()) {
+            ExceptionCode ec;
+            fragment->appendChild(fragmentForCurrentItem->firstChild(), ec);
+        }
+    }
+
+    if (fragment)
+        return fragment.release();
+
+    return 0;
+}
+
+}