[Clipboard API] Refactor Pasteboard item reading functions to work on both iOS and...
[WebKit.git] / Source / WebKit / WebProcess / WebCoreSupport / WebPlatformStrategies.cpp
1 /*
2  * Copyright (C) 2010-2018 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebPlatformStrategies.h"
28
29 #include "BlobRegistryProxy.h"
30 #include "BlockingResponseMap.h"
31 #include "DataReference.h"
32 #include "HangDetectionDisabler.h"
33 #include "NetworkConnectionToWebProcessMessages.h"
34 #include "NetworkProcessConnection.h"
35 #include "NetworkResourceLoadParameters.h"
36 #include "PluginInfoStore.h"
37 #include "WebCoreArgumentCoders.h"
38 #include "WebErrors.h"
39 #include "WebFrame.h"
40 #include "WebFrameLoaderClient.h"
41 #include "WebLoaderStrategy.h"
42 #include "WebPage.h"
43 #include "WebPasteboardOverrides.h"
44 #include "WebPasteboardProxyMessages.h"
45 #include "WebProcess.h"
46 #include "WebProcessProxyMessages.h"
47 #include <WebCore/Color.h>
48 #include <WebCore/Document.h>
49 #include <WebCore/DocumentLoader.h>
50 #include <WebCore/Frame.h>
51 #include <WebCore/LoaderStrategy.h>
52 #include <WebCore/NetworkStorageSession.h>
53 #include <WebCore/Page.h>
54 #include <WebCore/PageGroup.h>
55 #include <WebCore/PasteboardItemInfo.h>
56 #include <WebCore/PlatformPasteboard.h>
57 #include <WebCore/ProgressTracker.h>
58 #include <WebCore/ResourceError.h>
59 #include <WebCore/SameSiteInfo.h>
60 #include <WebCore/StorageNamespace.h>
61 #include <WebCore/SubframeLoader.h>
62 #include <wtf/Atomics.h>
63 #include <wtf/URL.h>
64
65 #if PLATFORM(MAC)
66 #include "StringUtilities.h"
67 #endif
68
69 #if PLATFORM(GTK)
70 #include "WebSelectionData.h"
71 #endif
72
73 namespace WebKit {
74 using namespace WebCore;
75
76 void WebPlatformStrategies::initialize()
77 {
78     static NeverDestroyed<WebPlatformStrategies> platformStrategies;
79     setPlatformStrategies(&platformStrategies.get());
80 }
81
82 WebPlatformStrategies::WebPlatformStrategies()
83 {
84 }
85
86 LoaderStrategy* WebPlatformStrategies::createLoaderStrategy()
87 {
88     return &WebProcess::singleton().webLoaderStrategy();
89 }
90
91 PasteboardStrategy* WebPlatformStrategies::createPasteboardStrategy()
92 {
93     return this;
94 }
95
96 BlobRegistry* WebPlatformStrategies::createBlobRegistry()
97 {
98     return new BlobRegistryProxy;
99 }
100
101 #if PLATFORM(COCOA)
102 // PasteboardStrategy
103
104 void WebPlatformStrategies::getTypes(Vector<String>& types, const String& pasteboardName)
105 {
106     // First check the overrides.
107     // The purpose of the overrides is to avoid messaging back to the UI process.
108     // Therefore, if there are any overridden types, we return just those.
109     types = WebPasteboardOverrides::sharedPasteboardOverrides().overriddenTypes(pasteboardName);
110     if (!types.isEmpty())
111         return;
112
113     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardTypes(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardTypes::Reply(types), 0);
114 }
115
116 RefPtr<WebCore::SharedBuffer> WebPlatformStrategies::bufferForType(const String& pasteboardType, const String& pasteboardName)
117 {
118     // First check the overrides.
119     Vector<char> overrideBuffer;
120     if (WebPasteboardOverrides::sharedPasteboardOverrides().getDataForOverride(pasteboardName, pasteboardType, overrideBuffer))
121         return SharedBuffer::create(WTFMove(overrideBuffer));
122
123     // Fallback to messaging the UI process for native pasteboard content.
124     SharedMemory::Handle handle;
125     uint64_t size { 0 };
126     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardBufferForType(pasteboardName, pasteboardType), Messages::WebPasteboardProxy::GetPasteboardBufferForType::Reply(handle, size), 0);
127     if (handle.isNull())
128         return nullptr;
129     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::map(handle, SharedMemory::Protection::ReadOnly);
130     return SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), size);
131 }
132
133 void WebPlatformStrategies::getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName)
134 {
135     SandboxExtension::HandleArray sandboxExtensionsHandleArray;
136     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardPathnamesForType(pasteboardName, pasteboardType),
137         Messages::WebPasteboardProxy::GetPasteboardPathnamesForType::Reply(pathnames, sandboxExtensionsHandleArray), 0);
138     ASSERT(pathnames.size() == sandboxExtensionsHandleArray.size());
139     for (size_t i = 0; i < sandboxExtensionsHandleArray.size(); i++) {
140         if (auto extension = SandboxExtension::create(WTFMove(sandboxExtensionsHandleArray[i])))
141             extension->consumePermanently();
142     }
143 }
144
145 String WebPlatformStrategies::stringForType(const String& pasteboardType, const String& pasteboardName)
146 {
147     String value;
148     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardStringForType(pasteboardName, pasteboardType), Messages::WebPasteboardProxy::GetPasteboardStringForType::Reply(value), 0);
149     return value;
150 }
151
152 Vector<String> WebPlatformStrategies::allStringsForType(const String& pasteboardType, const String& pasteboardName)
153 {
154     Vector<String> values;
155     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardStringsForType(pasteboardName, pasteboardType), Messages::WebPasteboardProxy::GetPasteboardStringsForType::Reply(values), 0);
156     return values;
157 }
158
159 long WebPlatformStrategies::changeCount(const WTF::String &pasteboardName)
160 {
161     uint64_t changeCount { 0 };
162     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardChangeCount(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardChangeCount::Reply(changeCount), 0);
163     return changeCount;
164 }
165
166 String WebPlatformStrategies::uniqueName()
167 {
168     String pasteboardName;
169     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardUniqueName(), Messages::WebPasteboardProxy::GetPasteboardUniqueName::Reply(pasteboardName), 0);
170     return pasteboardName;
171 }
172
173 Color WebPlatformStrategies::color(const String& pasteboardName)
174 {
175     Color color;
176     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardColor(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardColor::Reply(color), 0);
177     return color;
178 }
179
180 URL WebPlatformStrategies::url(const String& pasteboardName)
181 {
182     String urlString;
183     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardURL(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardURL::Reply(urlString), 0);
184     return URL({ }, urlString);
185 }
186
187 long WebPlatformStrategies::addTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName)
188 {
189     uint64_t newChangeCount { 0 };
190     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::AddPasteboardTypes(pasteboardName, pasteboardTypes), Messages::WebPasteboardProxy::AddPasteboardTypes::Reply(newChangeCount), 0);
191     return newChangeCount;
192 }
193
194 long WebPlatformStrategies::setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName)
195 {
196     uint64_t newChangeCount { 0 };
197     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardTypes(pasteboardName, pasteboardTypes), Messages::WebPasteboardProxy::SetPasteboardTypes::Reply(newChangeCount), 0);
198     return newChangeCount;
199 }
200
201 long WebPlatformStrategies::setBufferForType(SharedBuffer* buffer, const String& pasteboardType, const String& pasteboardName)
202 {
203     SharedMemory::Handle handle;
204     if (buffer && buffer->size()) {
205         RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(buffer->size());
206         // FIXME: Null check prevents crashing, but it is not great that we will have empty pasteboard content for this type,
207         // because we've already set the types.
208         if (sharedMemoryBuffer) {
209             memcpy(sharedMemoryBuffer->data(), buffer->data(), buffer->size());
210             sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly);
211         }
212     }
213     uint64_t newChangeCount { 0 };
214     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardBufferForType(pasteboardName, pasteboardType, handle, buffer ? buffer->size() : 0), Messages::WebPasteboardProxy::SetPasteboardBufferForType::Reply(newChangeCount), 0);
215     return newChangeCount;
216 }
217
218 long WebPlatformStrategies::setURL(const PasteboardURL& pasteboardURL, const String& pasteboardName)
219 {
220     uint64_t newChangeCount;
221     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardURL(pasteboardURL, pasteboardName), Messages::WebPasteboardProxy::SetPasteboardURL::Reply(newChangeCount), 0);
222     return newChangeCount;
223 }
224
225 long WebPlatformStrategies::setColor(const Color& color, const String& pasteboardName)
226 {
227     uint64_t newChangeCount { 0 };
228     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardColor(pasteboardName, color), Messages::WebPasteboardProxy::SetPasteboardColor::Reply(newChangeCount), 0);
229     return newChangeCount;
230 }
231
232 long WebPlatformStrategies::setStringForType(const String& string, const String& pasteboardType, const String& pasteboardName)
233 {
234     uint64_t newChangeCount { 0 };
235     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardStringForType(pasteboardName, pasteboardType, string), Messages::WebPasteboardProxy::SetPasteboardStringForType::Reply(newChangeCount), 0);
236     return newChangeCount;
237 }
238
239 int WebPlatformStrategies::getNumberOfFiles(const String& pasteboardName)
240 {
241     uint64_t numberOfFiles { 0 };
242     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetNumberOfFiles(pasteboardName), Messages::WebPasteboardProxy::GetNumberOfFiles::Reply(numberOfFiles), 0);
243     return numberOfFiles;
244 }
245
246 #if PLATFORM(IOS_FAMILY)
247
248 void WebPlatformStrategies::writeToPasteboard(const PasteboardURL& url, const String& pasteboardName)
249 {
250     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteURLToPasteboard(url, pasteboardName), 0);
251 }
252
253 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardWebContent& content, const String& pasteboardName)
254 {
255     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteWebContentToPasteboard(content, pasteboardName), 0);
256 }
257
258 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardImage& image, const String& pasteboardName)
259 {
260     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteImageToPasteboard(image, pasteboardName), 0);
261 }
262
263 void WebPlatformStrategies::writeToPasteboard(const String& pasteboardType, const String& text, const String& pasteboardName)
264 {
265     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteStringToPasteboard(pasteboardType, text, pasteboardName), 0);
266 }
267
268 void WebPlatformStrategies::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName)
269 {
270     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::UpdateSupportedTypeIdentifiers(identifiers, pasteboardName), 0);
271 }
272 #endif // PLATFORM(IOS_FAMILY)
273
274 #endif // PLATFORM(COCOA)
275
276 #if PLATFORM(GTK)
277 // PasteboardStrategy
278
279 void WebPlatformStrategies::writeToClipboard(const String& pasteboardName, const SelectionData& selection)
280 {
281     WebSelectionData selectionData(selection);
282     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteToClipboard(pasteboardName, selectionData), 0);
283 }
284
285 Ref<SelectionData> WebPlatformStrategies::readFromClipboard(const String& pasteboardName)
286 {
287     WebSelectionData selection;
288     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadFromClipboard(pasteboardName), Messages::WebPasteboardProxy::ReadFromClipboard::Reply(selection), 0);
289     return WTFMove(selection.selectionData);
290 }
291
292 #endif // PLATFORM(GTK)
293
294 #if USE(LIBWPE)
295 // PasteboardStrategy
296
297 void WebPlatformStrategies::getTypes(Vector<String>& types)
298 {
299     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardTypes(), Messages::WebPasteboardProxy::GetPasteboardTypes::Reply(types), 0);
300 }
301
302 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardWebContent& content)
303 {
304     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteWebContentToPasteboard(content), 0);
305 }
306
307 void WebPlatformStrategies::writeToPasteboard(const String& pasteboardType, const String& text)
308 {
309     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteStringToPasteboard(pasteboardType, text), 0);
310 }
311
312 #endif // USE(LIBWPE)
313
314 Vector<String> WebPlatformStrategies::typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin)
315 {
316     Vector<String> types;
317     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite(pasteboardName, origin), Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite::Reply(types), 0);
318     return types;
319 }
320
321 long WebPlatformStrategies::writeCustomData(const WebCore::PasteboardCustomData& data, const String& pasteboardName)
322 {
323     uint64_t newChangeCount { 0 };
324     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::WriteCustomData(data, pasteboardName), Messages::WebPasteboardProxy::WriteCustomData::Reply(newChangeCount), 0);
325     return newChangeCount;
326 }
327
328 int WebPlatformStrategies::getPasteboardItemsCount(const String& pasteboardName)
329 {
330     uint64_t itemsCount { 0 };
331     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardItemsCount(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardItemsCount::Reply(itemsCount), 0);
332     return itemsCount;
333 }
334
335 Vector<PasteboardItemInfo> WebPlatformStrategies::allPasteboardItemInfo(const String& pasteboardName)
336 {
337     Vector<PasteboardItemInfo> allInfo;
338     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::AllPasteboardItemInfo(pasteboardName), Messages::WebPasteboardProxy::AllPasteboardItemInfo::Reply(allInfo), 0);
339     return allInfo;
340 }
341
342 PasteboardItemInfo WebPlatformStrategies::informationForItemAtIndex(size_t index, const String& pasteboardName)
343 {
344     PasteboardItemInfo info;
345     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::InformationForItemAtIndex(index, pasteboardName), Messages::WebPasteboardProxy::InformationForItemAtIndex::Reply(info), 0);
346     return info;
347 }
348
349 RefPtr<WebCore::SharedBuffer> WebPlatformStrategies::readBufferFromPasteboard(size_t index, const String& pasteboardType, const String& pasteboardName)
350 {
351     SharedMemory::Handle handle;
352     uint64_t size { 0 };
353     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadBufferFromPasteboard(index, pasteboardType, pasteboardName), Messages::WebPasteboardProxy::ReadBufferFromPasteboard::Reply(handle, size), 0);
354     if (handle.isNull())
355         return nullptr;
356     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::map(handle, SharedMemory::Protection::ReadOnly);
357     return SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), size);
358 }
359
360 URL WebPlatformStrategies::readURLFromPasteboard(size_t index, const String& pasteboardName, String& title)
361 {
362     String urlString;
363     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadURLFromPasteboard(index, pasteboardName), Messages::WebPasteboardProxy::ReadURLFromPasteboard::Reply(urlString, title), 0);
364     return URL({ }, urlString);
365 }
366
367 String WebPlatformStrategies::readStringFromPasteboard(size_t index, const String& pasteboardType, const String& pasteboardName)
368 {
369     String value;
370     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadStringFromPasteboard(index, pasteboardType, pasteboardName), Messages::WebPasteboardProxy::ReadStringFromPasteboard::Reply(value), 0);
371     return value;
372 }
373
374 } // namespace WebKit