Add support for recognizing data interaction gestures in WebKit2
[WebKit-https.git] / Source / WebCore / platform / ios / PlatformPasteboardIOS.mm
1 /*
2  * Copyright (C) 2013 Apple 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 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 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 "PlatformPasteboard.h"
28
29 #import "Color.h"
30 #import "URL.h"
31 #import "Image.h"
32 #import "Pasteboard.h"
33 #import "SharedBuffer.h"
34 #import "SoftLinking.h"
35 #import "WebItemProviderPasteboard.h"
36 #import <MobileCoreServices/MobileCoreServices.h>
37
38 SOFT_LINK_FRAMEWORK(UIKit)
39 SOFT_LINK_CLASS(UIKit, UIPasteboard)
40
41 @interface UIPasteboard
42 + (UIPasteboard *)generalPasteboard;
43 - (void)setItems:(NSArray *)items;
44 @property(readonly,nonatomic) NSInteger numberOfItems;
45 - (NSArray *)dataForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet;
46 - (NSArray *)valuesForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet;
47 - (NSInteger)changeCount;
48 @end
49
50 namespace WebCore {
51
52 PlatformPasteboard::PlatformPasteboard()
53     : m_pasteboard([getUIPasteboardClass() generalPasteboard])
54 {
55 }
56
57 #if ENABLE(DATA_INTERACTION)
58 PlatformPasteboard::PlatformPasteboard(const String& name)
59 {
60     if (name == "data interaction pasteboard")
61         m_pasteboard = [WebItemProviderPasteboard sharedInstance];
62     else
63         m_pasteboard = [getUIPasteboardClass() generalPasteboard];
64 }
65 #else
66 PlatformPasteboard::PlatformPasteboard(const String&)
67     : m_pasteboard([getUIPasteboardClass() generalPasteboard])
68 {
69 }
70 #endif
71
72 void PlatformPasteboard::getTypes(Vector<String>& types)
73 {
74     for (NSString *pasteboardType in [m_pasteboard pasteboardTypes])
75         types.append(pasteboardType);
76 }
77
78 RefPtr<SharedBuffer> PlatformPasteboard::bufferForType(const String&)
79 {
80     return nullptr;
81 }
82
83 void PlatformPasteboard::getPathnamesForType(Vector<String>&, const String&)
84 {
85 }
86
87 String PlatformPasteboard::stringForType(const String&)
88 {
89     return String();
90 }
91
92 Color PlatformPasteboard::color()
93 {
94     return Color();
95 }
96
97 URL PlatformPasteboard::url()
98 {
99     return URL();
100 }
101
102 long PlatformPasteboard::copy(const String&)
103 {
104     return 0;
105 }
106
107 long PlatformPasteboard::addTypes(const Vector<String>&)
108 {
109     return 0;
110 }
111
112 long PlatformPasteboard::setTypes(const Vector<String>&)
113 {
114     return 0;
115 }
116
117 long PlatformPasteboard::setBufferForType(SharedBuffer*, const String&)
118 {
119     return 0;
120 }
121
122 long PlatformPasteboard::setPathnamesForType(const Vector<String>&, const String&)
123 {
124     return 0;
125 }
126
127 long PlatformPasteboard::setStringForType(const String&, const String&)
128 {
129     return 0;
130 }
131
132 long PlatformPasteboard::changeCount() const
133 {
134     return [m_pasteboard changeCount];
135 }
136
137 String PlatformPasteboard::uniqueName()
138 {
139     return String();
140 }
141
142 void PlatformPasteboard::write(const PasteboardWebContent& content)
143 {
144     RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
145
146     ASSERT(content.clientTypes.size() == content.clientData.size());
147     for (size_t i = 0, size = content.clientTypes.size(); i < size; ++i)
148         [representations setValue:content.clientData[i]->createNSData().get() forKey:content.clientTypes[i]];
149
150     if (content.dataInWebArchiveFormat) {
151         [representations setValue:(NSData *)content.dataInWebArchiveFormat->createNSData().get() forKey:WebArchivePboardType];
152         // Flag for UIKit to know that this copy contains rich content. This will trigger a two-step paste.
153         NSString* webIOSPastePboardType = @"iOS rich content paste pasteboard type";
154         [representations setValue:webIOSPastePboardType forKey:webIOSPastePboardType];
155     }
156
157     if (content.dataInRTFDFormat)
158         [representations setValue:content.dataInRTFDFormat->createNSData().get() forKey:(NSString *)kUTTypeFlatRTFD];
159     if (content.dataInRTFFormat)
160         [representations setValue:content.dataInRTFFormat->createNSData().get() forKey:(NSString *)kUTTypeRTF];
161
162     [representations setValue:content.dataInStringFormat forKey:(NSString *)kUTTypeText];
163     [representations setValue:[(NSString *)content.dataInStringFormat dataUsingEncoding:NSUTF8StringEncoding] forKey:(NSString *)kUTTypeUTF8PlainText];
164     [m_pasteboard setItems:@[representations.get()]];
165 }
166
167 void PlatformPasteboard::write(const PasteboardImage& pasteboardImage)
168 {
169     RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
170     if (!pasteboardImage.resourceMIMEType.isNull()) {
171         [representations setObject:pasteboardImage.resourceData->createNSData().get() forKey:pasteboardImage.resourceMIMEType];
172         [representations setObject:(NSURL *)pasteboardImage.url.url forKey:(NSString *)kUTTypeURL];
173     }
174     [m_pasteboard setItems:@[representations.get()]];
175 }
176
177 void PlatformPasteboard::write(const String& pasteboardType, const String& text)
178 {
179     RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
180
181     if (pasteboardType == String(kUTTypeURL)) {
182         [representations setValue:adoptNS([[NSURL alloc] initWithString:text]).get() forKey:pasteboardType];
183         [representations setValue:text forKey:(NSString *)kUTTypeText];
184     } else if (!pasteboardType.isNull())
185         [representations setValue:text forKey:pasteboardType];
186     [m_pasteboard setItems:@[representations.get()]];
187 }
188
189 int PlatformPasteboard::count()
190 {
191     return [m_pasteboard numberOfItems];
192 }
193
194 RefPtr<SharedBuffer> PlatformPasteboard::readBuffer(int index, const String& type)
195 {
196     NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
197
198     RetainPtr<NSArray> pasteboardItem = [m_pasteboard dataForPasteboardType:type inItemSet:indexSet];
199
200     if (![pasteboardItem count])
201         return nullptr;
202     return SharedBuffer::wrapNSData([pasteboardItem.get() objectAtIndex:0]);
203 }
204
205 String PlatformPasteboard::readString(int index, const String& type)
206 {
207     NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
208
209     RetainPtr<NSArray> pasteboardItem = [m_pasteboard valuesForPasteboardType:type inItemSet:indexSet];
210
211     if (![pasteboardItem count])
212         return String();
213
214     id value = [pasteboardItem objectAtIndex:0];
215     
216     if (type == String(kUTTypeText)) {
217         ASSERT([value isKindOfClass:[NSString class]]);
218         if ([value isKindOfClass:[NSString class]])
219             return String(value);
220     } else if (type == String(kUTTypeURL)) {
221         ASSERT([value isKindOfClass:[NSURL class]]);
222         if ([value isKindOfClass:[NSURL class]])
223             return [(NSURL *)value absoluteString];
224     }
225
226     return String();
227 }
228
229 URL PlatformPasteboard::readURL(int index, const String& type)
230 {
231     NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
232
233     RetainPtr<NSArray> pasteboardItem = [m_pasteboard valuesForPasteboardType:type inItemSet:indexSet];
234
235     if (![pasteboardItem count])
236         return URL();
237
238     id value = [pasteboardItem objectAtIndex:0];
239     ASSERT([value isKindOfClass:[NSURL class]]);
240     if (![value isKindOfClass:[NSURL class]])
241         return URL();
242
243     return (NSURL *)value;
244 }
245
246 }