[Attachment Support] Create attachment elements when dropping files on iOS
[WebKit-https.git] / Source / WebKit / WebProcess / WebCoreSupport / WebPlatformStrategies.cpp
1 /*
2  * Copyright (C) 2010-2017 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 "SessionTracker.h"
38 #include "WebCookieManager.h"
39 #include "WebCoreArgumentCoders.h"
40 #include "WebErrors.h"
41 #include "WebFrame.h"
42 #include "WebFrameLoaderClient.h"
43 #include "WebLoaderStrategy.h"
44 #include "WebPage.h"
45 #include "WebPasteboardOverrides.h"
46 #include "WebPasteboardProxyMessages.h"
47 #include "WebProcess.h"
48 #include "WebProcessProxyMessages.h"
49 #include <WebCore/Color.h>
50 #include <WebCore/Document.h>
51 #include <WebCore/DocumentLoader.h>
52 #include <WebCore/LoaderStrategy.h>
53 #include <WebCore/MainFrame.h>
54 #include <WebCore/NetworkStorageSession.h>
55 #include <WebCore/NetworkingContext.h>
56 #include <WebCore/Page.h>
57 #include <WebCore/PageGroup.h>
58 #include <WebCore/PasteboardItemInfo.h>
59 #include <WebCore/PlatformCookieJar.h>
60 #include <WebCore/PlatformPasteboard.h>
61 #include <WebCore/ProgressTracker.h>
62 #include <WebCore/ResourceError.h>
63 #include <WebCore/StorageNamespace.h>
64 #include <WebCore/SubframeLoader.h>
65 #include <WebCore/URL.h>
66 #include <pal/SessionID.h>
67 #include <wtf/Atomics.h>
68
69 #if PLATFORM(MAC)
70 #include "StringUtilities.h"
71 #endif
72
73 #if PLATFORM(GTK)
74 #include "WebSelectionData.h"
75 #endif
76
77 using namespace WebCore;
78
79 namespace WebKit {
80
81 void WebPlatformStrategies::initialize()
82 {
83     static NeverDestroyed<WebPlatformStrategies> platformStrategies;
84     setPlatformStrategies(&platformStrategies.get());
85 }
86
87 WebPlatformStrategies::WebPlatformStrategies()
88 {
89 }
90
91 CookiesStrategy* WebPlatformStrategies::createCookiesStrategy()
92 {
93     return this;
94 }
95
96 LoaderStrategy* WebPlatformStrategies::createLoaderStrategy()
97 {
98     return &WebProcess::singleton().webLoaderStrategy();
99 }
100
101 PasteboardStrategy* WebPlatformStrategies::createPasteboardStrategy()
102 {
103     return this;
104 }
105
106 BlobRegistry* WebPlatformStrategies::createBlobRegistry()
107 {
108     return new BlobRegistryProxy;
109 }
110
111 // CookiesStrategy
112
113 std::pair<String, bool> WebPlatformStrategies::cookiesForDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies)
114 {
115     String cookieString;
116     bool secureCookiesAccessed = false;
117     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::CookiesForDOM(session.sessionID(), firstParty, url, frameID, pageID, includeSecureCookies), Messages::NetworkConnectionToWebProcess::CookiesForDOM::Reply(cookieString, secureCookiesAccessed), 0))
118         return { String(), false };
119
120     return { cookieString, secureCookiesAccessed };
121 }
122
123 void WebPlatformStrategies::setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String& cookieString)
124 {
125     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCookiesFromDOM(session.sessionID(), firstParty, url, frameID, pageID, cookieString), 0);
126 }
127
128 bool WebPlatformStrategies::cookiesEnabled(const NetworkStorageSession& session)
129 {
130     bool result;
131     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::CookiesEnabled(session.sessionID()), Messages::NetworkConnectionToWebProcess::CookiesEnabled::Reply(result), 0))
132         return false;
133     return result;
134 }
135
136 std::pair<String, bool> WebPlatformStrategies::cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies)
137 {
138     return cookieRequestHeaderFieldValue(session.sessionID(), firstParty, url, frameID, pageID, includeSecureCookies);
139 }
140
141 std::pair<String, bool> WebPlatformStrategies::cookieRequestHeaderFieldValue(PAL::SessionID sessionID, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies)
142 {
143     String cookieString;
144     bool secureCookiesAccessed = false;
145     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::CookieRequestHeaderFieldValue(sessionID, firstParty, url, frameID, pageID, includeSecureCookies), Messages::NetworkConnectionToWebProcess::CookieRequestHeaderFieldValue::Reply(cookieString, secureCookiesAccessed), 0))
146         return { String(), false };
147     return { cookieString, secureCookiesAccessed };
148 }
149
150 bool WebPlatformStrategies::getRawCookies(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>& rawCookies)
151 {
152     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::GetRawCookies(session.sessionID(), firstParty, url, frameID, pageID), Messages::NetworkConnectionToWebProcess::GetRawCookies::Reply(rawCookies), 0))
153         return false;
154     return true;
155 }
156
157 void WebPlatformStrategies::deleteCookie(const NetworkStorageSession& session, const URL& url, const String& cookieName)
158 {
159     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::DeleteCookie(session.sessionID(), url, cookieName), 0);
160 }
161
162 #if PLATFORM(COCOA)
163 // PasteboardStrategy
164
165 void WebPlatformStrategies::getTypes(Vector<String>& types, const String& pasteboardName)
166 {
167     // First check the overrides.
168     // The purpose of the overrides is to avoid messaging back to the UI process.
169     // Therefore, if there are any overridden types, we return just those.
170     types = WebPasteboardOverrides::sharedPasteboardOverrides().overriddenTypes(pasteboardName);
171     if (!types.isEmpty())
172         return;
173
174     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardTypes(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardTypes::Reply(types), 0);
175 }
176
177 RefPtr<WebCore::SharedBuffer> WebPlatformStrategies::bufferForType(const String& pasteboardType, const String& pasteboardName)
178 {
179     // First check the overrides.
180     Vector<char> overrideBuffer;
181     if (WebPasteboardOverrides::sharedPasteboardOverrides().getDataForOverride(pasteboardName, pasteboardType, overrideBuffer))
182         return SharedBuffer::create(WTFMove(overrideBuffer));
183
184     // Fallback to messaging the UI process for native pasteboard content.
185     SharedMemory::Handle handle;
186     uint64_t size = 0;
187     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardBufferForType(pasteboardName, pasteboardType), Messages::WebPasteboardProxy::GetPasteboardBufferForType::Reply(handle, size), 0);
188     if (handle.isNull())
189         return nullptr;
190     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::map(handle, SharedMemory::Protection::ReadOnly);
191     return SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), size);
192 }
193
194 void WebPlatformStrategies::getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName)
195 {
196     SandboxExtension::HandleArray sandboxExtensionsHandleArray;
197     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardPathnamesForType(pasteboardName, pasteboardType),
198         Messages::WebPasteboardProxy::GetPasteboardPathnamesForType::Reply(pathnames, sandboxExtensionsHandleArray), 0);
199     ASSERT(pathnames.size() == sandboxExtensionsHandleArray.size());
200     for (size_t i = 0; i < sandboxExtensionsHandleArray.size(); i++) {
201         if (RefPtr<SandboxExtension> extension = SandboxExtension::create(WTFMove(sandboxExtensionsHandleArray[i])))
202             extension->consumePermanently();
203     }
204 }
205
206 String WebPlatformStrategies::stringForType(const String& pasteboardType, const String& pasteboardName)
207 {
208     String value;
209     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardStringForType(pasteboardName, pasteboardType), Messages::WebPasteboardProxy::GetPasteboardStringForType::Reply(value), 0);
210     return value;
211 }
212
213 long WebPlatformStrategies::changeCount(const WTF::String &pasteboardName)
214 {
215     uint64_t changeCount;
216     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardChangeCount(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardChangeCount::Reply(changeCount), 0);
217     return changeCount;
218 }
219
220 String WebPlatformStrategies::uniqueName()
221 {
222     String pasteboardName;
223     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardUniqueName(), Messages::WebPasteboardProxy::GetPasteboardUniqueName::Reply(pasteboardName), 0);
224     return pasteboardName;
225 }
226
227 Color WebPlatformStrategies::color(const String& pasteboardName)
228 {
229     Color color;
230     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardColor(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardColor::Reply(color), 0);
231     return color;
232 }
233
234 URL WebPlatformStrategies::url(const String& pasteboardName)
235 {
236     String urlString;
237     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardURL(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardURL::Reply(urlString), 0);
238     return URL(ParsedURLString, urlString);
239 }
240
241 long WebPlatformStrategies::addTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName)
242 {
243     uint64_t newChangeCount;
244     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::AddPasteboardTypes(pasteboardName, pasteboardTypes), Messages::WebPasteboardProxy::AddPasteboardTypes::Reply(newChangeCount), 0);
245     return newChangeCount;
246 }
247
248 long WebPlatformStrategies::setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName)
249 {
250     uint64_t newChangeCount;
251     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardTypes(pasteboardName, pasteboardTypes), Messages::WebPasteboardProxy::SetPasteboardTypes::Reply(newChangeCount), 0);
252     return newChangeCount;
253 }
254
255 long WebPlatformStrategies::setBufferForType(SharedBuffer* buffer, const String& pasteboardType, const String& pasteboardName)
256 {
257     SharedMemory::Handle handle;
258     if (buffer) {
259         RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(buffer->size());
260         // FIXME: Null check prevents crashing, but it is not great that we will have empty pasteboard content for this type,
261         // because we've already set the types.
262         if (sharedMemoryBuffer) {
263             memcpy(sharedMemoryBuffer->data(), buffer->data(), buffer->size());
264             sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly);
265         }
266     }
267     uint64_t newChangeCount;
268     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardBufferForType(pasteboardName, pasteboardType, handle, buffer ? buffer->size() : 0), Messages::WebPasteboardProxy::SetPasteboardBufferForType::Reply(newChangeCount), 0);
269     return newChangeCount;
270 }
271
272 long WebPlatformStrategies::setPathnamesForType(const Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName)
273 {
274     uint64_t newChangeCount;
275     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardPathnamesForType(pasteboardName, pasteboardType, pathnames), Messages::WebPasteboardProxy::SetPasteboardPathnamesForType::Reply(newChangeCount), 0);
276     return newChangeCount;
277 }
278
279 long WebPlatformStrategies::setStringForType(const String& string, const String& pasteboardType, const String& pasteboardName)
280 {
281     uint64_t newChangeCount;
282     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardStringForType(pasteboardName, pasteboardType, string), Messages::WebPasteboardProxy::SetPasteboardStringForType::Reply(newChangeCount), 0);
283     return newChangeCount;
284 }
285
286 int WebPlatformStrategies::getNumberOfFiles(const String& pasteboardName)
287 {
288     uint64_t numberOfFiles;
289     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetNumberOfFiles(pasteboardName), Messages::WebPasteboardProxy::GetNumberOfFiles::Reply(numberOfFiles), 0);
290     return numberOfFiles;
291 }
292
293 #if PLATFORM(IOS)
294 void WebPlatformStrategies::getTypesByFidelityForItemAtIndex(Vector<String>& types, uint64_t index, const String& pasteboardName)
295 {
296     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardTypesByFidelityForItemAtIndex(index, pasteboardName), Messages::WebPasteboardProxy::GetPasteboardTypesByFidelityForItemAtIndex::Reply(types), 0);
297 }
298
299 void WebPlatformStrategies::writeToPasteboard(const PasteboardURL& url, const String& pasteboardName)
300 {
301     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteURLToPasteboard(url, pasteboardName), 0);
302 }
303
304 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardWebContent& content, const String& pasteboardName)
305 {
306     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteWebContentToPasteboard(content, pasteboardName), 0);
307 }
308
309 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardImage& image, const String& pasteboardName)
310 {
311     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteImageToPasteboard(image, pasteboardName), 0);
312 }
313
314 void WebPlatformStrategies::writeToPasteboard(const String& pasteboardType, const String& text, const String& pasteboardName)
315 {
316     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteStringToPasteboard(pasteboardType, text, pasteboardName), 0);
317 }
318
319 int WebPlatformStrategies::getPasteboardItemsCount(const String& pasteboardName)
320 {
321     uint64_t itemsCount;
322     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardItemsCount(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardItemsCount::Reply(itemsCount), 0);
323     return itemsCount;
324 }
325
326 PasteboardItemInfo WebPlatformStrategies::informationForItemAtIndex(int index, const String& pasteboardName)
327 {
328     PasteboardItemInfo info;
329     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::InformationForItemAtIndex(index, pasteboardName), Messages::WebPasteboardProxy::InformationForItemAtIndex::Reply(info), 0);
330     return info;
331 }
332
333 void WebPlatformStrategies::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName)
334 {
335     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::UpdateSupportedTypeIdentifiers(identifiers, pasteboardName), 0);
336 }
337
338 RefPtr<WebCore::SharedBuffer> WebPlatformStrategies::readBufferFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName)
339 {
340     SharedMemory::Handle handle;
341     uint64_t size = 0;
342     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadBufferFromPasteboard(index, pasteboardType, pasteboardName), Messages::WebPasteboardProxy::ReadBufferFromPasteboard::Reply(handle, size), 0);
343     if (handle.isNull())
344         return nullptr;
345     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::map(handle, SharedMemory::Protection::ReadOnly);
346     return SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), size);
347 }
348
349 WebCore::URL WebPlatformStrategies::readURLFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName, String& title)
350 {
351     String urlString;
352     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadURLFromPasteboard(index, pasteboardType, pasteboardName), Messages::WebPasteboardProxy::ReadURLFromPasteboard::Reply(urlString, title), 0);
353     return URL(ParsedURLString, urlString);
354 }
355
356 String WebPlatformStrategies::readStringFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName)
357 {
358     String value;
359     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadStringFromPasteboard(index, pasteboardType, pasteboardName), Messages::WebPasteboardProxy::ReadStringFromPasteboard::Reply(value), 0);
360     return value;
361 }
362 #endif // PLATFORM(IOS)
363
364 #endif // PLATFORM(COCOA)
365
366 #if PLATFORM(GTK)
367 // PasteboardStrategy
368
369 void WebPlatformStrategies::writeToClipboard(const String& pasteboardName, const SelectionData& selection)
370 {
371     WebSelectionData selectionData(selection);
372     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteToClipboard(pasteboardName, selectionData), 0);
373 }
374
375 Ref<SelectionData> WebPlatformStrategies::readFromClipboard(const String& pasteboardName)
376 {
377     WebSelectionData selection;
378     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadFromClipboard(pasteboardName), Messages::WebPasteboardProxy::ReadFromClipboard::Reply(selection), 0);
379     return WTFMove(selection.selectionData);
380 }
381
382 #endif // PLATFORM(GTK)
383
384 #if PLATFORM(WPE)
385 // PasteboardStrategy
386
387 void WebPlatformStrategies::getTypes(Vector<String>& types)
388 {
389     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardTypes(), Messages::WebPasteboardProxy::GetPasteboardTypes::Reply(types), 0);
390 }
391
392 String WebPlatformStrategies::readStringFromPasteboard(int index, const String& pasteboardType)
393 {
394     String value;
395     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::ReadStringFromPasteboard(index, pasteboardType), Messages::WebPasteboardProxy::ReadStringFromPasteboard::Reply(value), 0);
396     return value;
397 }
398
399 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardWebContent& content)
400 {
401     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteWebContentToPasteboard(content), 0);
402 }
403
404 void WebPlatformStrategies::writeToPasteboard(const String& pasteboardType, const String& text)
405 {
406     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteStringToPasteboard(pasteboardType, text), 0);
407 }
408
409 #endif // PLATFORM(WPE)
410
411 Vector<String> WebPlatformStrategies::typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin)
412 {
413     Vector<String> types;
414     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite(pasteboardName, origin), Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite::Reply(types), 0);
415     return types;
416 }
417
418 long WebPlatformStrategies::writeCustomData(const WebCore::PasteboardCustomData& data, const String& pasteboardName)
419 {
420     uint64_t newChangeCount;
421     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::WriteCustomData(data, pasteboardName), Messages::WebPasteboardProxy::WriteCustomData::Reply(newChangeCount), 0);
422     return newChangeCount;
423 }
424
425 } // namespace WebKit