a416766e2b383e1b51448fc9cc402c01f1beb3aa
[WebKit-https.git] / Source / WebKit / UIProcess / API / C / WKPage.cpp
1 /*
2  * Copyright (C) 2010, 2015-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 "WKPage.h"
28 #include "WKPagePrivate.h"
29
30 #include "APIArray.h"
31 #include "APIContextMenuClient.h"
32 #include "APIData.h"
33 #include "APIDictionary.h"
34 #include "APIFindClient.h"
35 #include "APIFindMatchesClient.h"
36 #include "APIFrameHandle.h"
37 #include "APIFrameInfo.h"
38 #include "APIGeometry.h"
39 #include "APIHitTestResult.h"
40 #include "APILoaderClient.h"
41 #include "APINavigation.h"
42 #include "APINavigationAction.h"
43 #include "APINavigationClient.h"
44 #include "APINavigationResponse.h"
45 #include "APIOpenPanelParameters.h"
46 #include "APIPageConfiguration.h"
47 #include "APIPolicyClient.h"
48 #include "APISessionState.h"
49 #include "APIUIClient.h"
50 #include "APIWebsitePolicies.h"
51 #include "APIWindowFeatures.h"
52 #include "AuthenticationChallengeDisposition.h"
53 #include "AuthenticationChallengeProxy.h"
54 #include "AuthenticationDecisionListener.h"
55 #include "LegacySessionStateCoding.h"
56 #include "Logging.h"
57 #include "NativeWebKeyboardEvent.h"
58 #include "NativeWebWheelEvent.h"
59 #include "NavigationActionData.h"
60 #include "PageClient.h"
61 #include "PluginInformation.h"
62 #include "PrintInfo.h"
63 #include "WKAPICast.h"
64 #include "WKPagePolicyClientInternal.h"
65 #include "WKPageRenderingProgressEventsInternal.h"
66 #include "WKPluginInformation.h"
67 #include "WebBackForwardList.h"
68 #include "WebFormClient.h"
69 #include "WebImage.h"
70 #include "WebInspectorProxy.h"
71 #include "WebOpenPanelResultListenerProxy.h"
72 #include "WebPageGroup.h"
73 #include "WebPageMessages.h"
74 #include "WebPageProxy.h"
75 #include "WebProcessPool.h"
76 #include "WebProcessProxy.h"
77 #include "WebProtectionSpace.h"
78 #include <WebCore/Page.h>
79 #include <WebCore/SSLKeyGenerator.h>
80 #include <WebCore/SecurityOriginData.h>
81 #include <WebCore/SerializedCryptoKeyWrap.h>
82 #include <WebCore/WindowFeatures.h>
83
84 #ifdef __BLOCKS__
85 #include <Block.h>
86 #endif
87
88 #if ENABLE(CONTEXT_MENUS)
89 #include "WebContextMenuItem.h"
90 #endif
91
92 #if ENABLE(MEDIA_SESSION)
93 #include "WebMediaSessionMetadata.h"
94 #include <WebCore/MediaSessionEvents.h>
95 #endif
96
97 #if PLATFORM(COCOA)
98 #include "VersionChecks.h"
99 #endif
100
101 namespace API {
102 using namespace WebCore;
103 using namespace WebKit;
104     
105 template<> struct ClientTraits<WKPageLoaderClientBase> {
106     typedef std::tuple<WKPageLoaderClientV0, WKPageLoaderClientV1, WKPageLoaderClientV2, WKPageLoaderClientV3, WKPageLoaderClientV4, WKPageLoaderClientV5, WKPageLoaderClientV6> Versions;
107 };
108
109 template<> struct ClientTraits<WKPageNavigationClientBase> {
110     typedef std::tuple<WKPageNavigationClientV0, WKPageNavigationClientV1, WKPageNavigationClientV2, WKPageNavigationClientV3> Versions;
111 };
112
113 template<> struct ClientTraits<WKPagePolicyClientBase> {
114     typedef std::tuple<WKPagePolicyClientV0, WKPagePolicyClientV1, WKPagePolicyClientInternal> Versions;
115 };
116
117 template<> struct ClientTraits<WKPageUIClientBase> {
118     typedef std::tuple<WKPageUIClientV0, WKPageUIClientV1, WKPageUIClientV2, WKPageUIClientV3, WKPageUIClientV4, WKPageUIClientV5, WKPageUIClientV6, WKPageUIClientV7, WKPageUIClientV8, WKPageUIClientV9, WKPageUIClientV10, WKPageUIClientV11, WKPageUIClientV12> Versions;
119 };
120
121 #if ENABLE(CONTEXT_MENUS)
122 template<> struct ClientTraits<WKPageContextMenuClientBase> {
123     typedef std::tuple<WKPageContextMenuClientV0, WKPageContextMenuClientV1, WKPageContextMenuClientV2, WKPageContextMenuClientV3, WKPageContextMenuClientV4> Versions;
124 };
125 #endif
126
127 template<> struct ClientTraits<WKPageFindClientBase> {
128     typedef std::tuple<WKPageFindClientV0> Versions;
129 };
130
131 template<> struct ClientTraits<WKPageFindMatchesClientBase> {
132     typedef std::tuple<WKPageFindMatchesClientV0> Versions;
133 };
134     
135 } // namespace API
136
137 using namespace WebKit;
138
139 WKTypeID WKPageGetTypeID()
140 {
141     return toAPI(WebPageProxy::APIType);
142 }
143
144 WKContextRef WKPageGetContext(WKPageRef pageRef)
145 {
146     return toAPI(&toImpl(pageRef)->process().processPool());
147 }
148
149 WKPageGroupRef WKPageGetPageGroup(WKPageRef pageRef)
150 {
151     return toAPI(&toImpl(pageRef)->pageGroup());
152 }
153
154 WKPageConfigurationRef WKPageCopyPageConfiguration(WKPageRef pageRef)
155 {
156     return toAPI(&toImpl(pageRef)->configuration().copy().leakRef());
157 }
158
159 void WKPageLoadURL(WKPageRef pageRef, WKURLRef URLRef)
160 {
161     toImpl(pageRef)->loadRequest(URL(URL(), toWTFString(URLRef)));
162 }
163
164 void WKPageLoadURLWithShouldOpenExternalURLsPolicy(WKPageRef pageRef, WKURLRef URLRef, bool shouldOpenExternalURLs)
165 {
166     WebCore::ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLs ? WebCore::ShouldOpenExternalURLsPolicy::ShouldAllow : WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow;
167     toImpl(pageRef)->loadRequest(URL(URL(), toWTFString(URLRef)), shouldOpenExternalURLsPolicy);
168 }
169
170 void WKPageLoadURLWithUserData(WKPageRef pageRef, WKURLRef URLRef, WKTypeRef userDataRef)
171 {
172     toImpl(pageRef)->loadRequest(URL(URL(), toWTFString(URLRef)), WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow, toImpl(userDataRef));
173 }
174
175 void WKPageLoadURLRequest(WKPageRef pageRef, WKURLRequestRef urlRequestRef)
176 {
177     auto resourceRequest = toImpl(urlRequestRef)->resourceRequest();
178     toImpl(pageRef)->loadRequest(WTFMove(resourceRequest));
179 }
180
181 void WKPageLoadURLRequestWithUserData(WKPageRef pageRef, WKURLRequestRef urlRequestRef, WKTypeRef userDataRef)
182 {
183     auto resourceRequest = toImpl(urlRequestRef)->resourceRequest();
184     toImpl(pageRef)->loadRequest(WTFMove(resourceRequest), WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow, toImpl(userDataRef));
185 }
186
187 void WKPageLoadFile(WKPageRef pageRef, WKURLRef fileURL, WKURLRef resourceDirectoryURL)
188 {
189     toImpl(pageRef)->loadFile(toWTFString(fileURL), toWTFString(resourceDirectoryURL));
190 }
191
192 void WKPageLoadFileWithUserData(WKPageRef pageRef, WKURLRef fileURL, WKURLRef resourceDirectoryURL, WKTypeRef userDataRef)
193 {
194     toImpl(pageRef)->loadFile(toWTFString(fileURL), toWTFString(resourceDirectoryURL), toImpl(userDataRef));
195 }
196
197 void WKPageLoadData(WKPageRef pageRef, WKDataRef dataRef, WKStringRef MIMETypeRef, WKStringRef encodingRef, WKURLRef baseURLRef)
198 {
199     toImpl(pageRef)->loadData(toImpl(dataRef)->dataReference(), toWTFString(MIMETypeRef), toWTFString(encodingRef), toWTFString(baseURLRef));
200 }
201
202 void WKPageLoadDataWithUserData(WKPageRef pageRef, WKDataRef dataRef, WKStringRef MIMETypeRef, WKStringRef encodingRef, WKURLRef baseURLRef, WKTypeRef userDataRef)
203 {
204     toImpl(pageRef)->loadData(toImpl(dataRef)->dataReference(), toWTFString(MIMETypeRef), toWTFString(encodingRef), toWTFString(baseURLRef), toImpl(userDataRef));
205 }
206
207 static String encodingOf(const String& string)
208 {
209     if (string.isNull() || !string.is8Bit())
210         return "utf-16"_s;
211     return "latin1"_s;
212 }
213
214 static IPC::DataReference dataFrom(const String& string)
215 {
216     if (string.isNull() || !string.is8Bit())
217         return { reinterpret_cast<const uint8_t*>(string.characters16()), string.length() * sizeof(UChar) };
218     return { reinterpret_cast<const uint8_t*>(string.characters8()), string.length() * sizeof(LChar) };
219 }
220
221 static void loadString(WKPageRef pageRef, WKStringRef stringRef, const String& mimeType, const String& baseURL, WKTypeRef userDataRef)
222 {
223     String string = toWTFString(stringRef);
224     toImpl(pageRef)->loadData(dataFrom(string), mimeType, encodingOf(string), baseURL, toImpl(userDataRef));
225 }
226
227 void WKPageLoadHTMLString(WKPageRef pageRef, WKStringRef htmlStringRef, WKURLRef baseURLRef)
228 {
229     WKPageLoadHTMLStringWithUserData(pageRef, htmlStringRef, baseURLRef, nullptr);
230 }
231
232 void WKPageLoadHTMLStringWithUserData(WKPageRef pageRef, WKStringRef htmlStringRef, WKURLRef baseURLRef, WKTypeRef userDataRef)
233 {
234     loadString(pageRef, htmlStringRef, "text/html"_s, toWTFString(baseURLRef), userDataRef);
235 }
236
237 void WKPageLoadAlternateHTMLString(WKPageRef pageRef, WKStringRef htmlStringRef, WKURLRef baseURLRef, WKURLRef unreachableURLRef)
238 {
239     WKPageLoadAlternateHTMLStringWithUserData(pageRef, htmlStringRef, baseURLRef, unreachableURLRef, nullptr);
240 }
241
242 void WKPageLoadAlternateHTMLStringWithUserData(WKPageRef pageRef, WKStringRef htmlStringRef, WKURLRef baseURLRef, WKURLRef unreachableURLRef, WKTypeRef userDataRef)
243 {
244     String string = toWTFString(htmlStringRef);
245     toImpl(pageRef)->loadAlternateHTML(dataFrom(string), encodingOf(string), URL(URL(), toWTFString(baseURLRef)), URL(URL(), toWTFString(unreachableURLRef)), toImpl(userDataRef));
246 }
247
248 void WKPageLoadPlainTextString(WKPageRef pageRef, WKStringRef plainTextStringRef)
249 {
250     WKPageLoadPlainTextStringWithUserData(pageRef, plainTextStringRef, nullptr);
251 }
252
253 void WKPageLoadPlainTextStringWithUserData(WKPageRef pageRef, WKStringRef plainTextStringRef, WKTypeRef userDataRef)
254 {
255     loadString(pageRef, plainTextStringRef, "text/plain"_s, WTF::blankURL().string(), userDataRef);
256 }
257
258 void WKPageLoadWebArchiveData(WKPageRef pageRef, WKDataRef webArchiveDataRef)
259 {
260     toImpl(pageRef)->loadWebArchiveData(toImpl(webArchiveDataRef));
261 }
262
263 void WKPageLoadWebArchiveDataWithUserData(WKPageRef pageRef, WKDataRef webArchiveDataRef, WKTypeRef userDataRef)
264 {
265     toImpl(pageRef)->loadWebArchiveData(toImpl(webArchiveDataRef), toImpl(userDataRef));
266 }
267
268 void WKPageStopLoading(WKPageRef pageRef)
269 {
270     toImpl(pageRef)->stopLoading();
271 }
272
273 void WKPageReload(WKPageRef pageRef)
274 {
275     OptionSet<WebCore::ReloadOption> reloadOptions;
276 #if PLATFORM(COCOA)
277     if (linkedOnOrAfter(WebKit::SDKVersion::FirstWithExpiredOnlyReloadBehavior))
278         reloadOptions.add(WebCore::ReloadOption::ExpiredOnly);
279 #endif
280
281     toImpl(pageRef)->reload(reloadOptions);
282 }
283
284 void WKPageReloadWithoutContentBlockers(WKPageRef pageRef)
285 {
286     toImpl(pageRef)->reload(WebCore::ReloadOption::DisableContentBlockers);
287 }
288
289 void WKPageReloadFromOrigin(WKPageRef pageRef)
290 {
291     toImpl(pageRef)->reload(WebCore::ReloadOption::FromOrigin);
292 }
293
294 void WKPageReloadExpiredOnly(WKPageRef pageRef)
295 {
296     toImpl(pageRef)->reload(WebCore::ReloadOption::ExpiredOnly);
297 }
298
299 bool WKPageTryClose(WKPageRef pageRef)
300 {
301     return toImpl(pageRef)->tryClose();
302 }
303
304 void WKPageClose(WKPageRef pageRef)
305 {
306     toImpl(pageRef)->close();
307 }
308
309 bool WKPageIsClosed(WKPageRef pageRef)
310 {
311     return toImpl(pageRef)->isClosed();
312 }
313
314 void WKPageGoForward(WKPageRef pageRef)
315 {
316     toImpl(pageRef)->goForward();
317 }
318
319 bool WKPageCanGoForward(WKPageRef pageRef)
320 {
321     return toImpl(pageRef)->backForwardList().forwardItem();
322 }
323
324 void WKPageGoBack(WKPageRef pageRef)
325 {
326     auto& page = *toImpl(pageRef);
327     if (page.pageClient().hasSafeBrowsingWarning()) {
328         WKPageReload(pageRef);
329         return;
330     }
331     page.goBack();
332 }
333
334 bool WKPageCanGoBack(WKPageRef pageRef)
335 {
336     return toImpl(pageRef)->backForwardList().backItem();
337 }
338
339 void WKPageGoToBackForwardListItem(WKPageRef pageRef, WKBackForwardListItemRef itemRef)
340 {
341     toImpl(pageRef)->goToBackForwardItem(*toImpl(itemRef));
342 }
343
344 void WKPageTryRestoreScrollPosition(WKPageRef pageRef)
345 {
346     toImpl(pageRef)->tryRestoreScrollPosition();
347 }
348
349 WKBackForwardListRef WKPageGetBackForwardList(WKPageRef pageRef)
350 {
351     return toAPI(&toImpl(pageRef)->backForwardList());
352 }
353
354 bool WKPageWillHandleHorizontalScrollEvents(WKPageRef pageRef)
355 {
356     return toImpl(pageRef)->willHandleHorizontalScrollEvents();
357 }
358
359 void WKPageUpdateWebsitePolicies(WKPageRef pageRef, WKWebsitePoliciesRef websitePoliciesRef)
360 {
361     auto data = toImpl(websitePoliciesRef)->data();
362     RELEASE_ASSERT_WITH_MESSAGE(!data.websiteDataStoreParameters, "Setting WebsitePolicies.WebsiteDataStore is only supported during WKFramePolicyListenerUseWithPolicies().");
363     toImpl(pageRef)->updateWebsitePolicies(WTFMove(data));
364 }
365
366 WKStringRef WKPageCopyTitle(WKPageRef pageRef)
367 {
368     return toCopiedAPI(toImpl(pageRef)->pageLoadState().title());
369 }
370
371 WKFrameRef WKPageGetMainFrame(WKPageRef pageRef)
372 {
373     return toAPI(toImpl(pageRef)->mainFrame());
374 }
375
376 WKFrameRef WKPageGetFocusedFrame(WKPageRef pageRef)
377 {
378     return toAPI(toImpl(pageRef)->focusedFrame());
379 }
380
381 WKFrameRef WKPageGetFrameSetLargestFrame(WKPageRef pageRef)
382 {
383     return toAPI(toImpl(pageRef)->frameSetLargestFrame());
384 }
385
386 uint64_t WKPageGetRenderTreeSize(WKPageRef page)
387 {
388     return toImpl(page)->renderTreeSize();
389 }
390
391 WKInspectorRef WKPageGetInspector(WKPageRef pageRef)
392 {
393     return toAPI(toImpl(pageRef)->inspector());
394 }
395
396 double WKPageGetEstimatedProgress(WKPageRef pageRef)
397 {
398     return toImpl(pageRef)->estimatedProgress();
399 }
400
401 WKStringRef WKPageCopyUserAgent(WKPageRef pageRef)
402 {
403     return toCopiedAPI(toImpl(pageRef)->userAgent());
404 }
405
406 WKStringRef WKPageCopyApplicationNameForUserAgent(WKPageRef pageRef)
407 {
408     return toCopiedAPI(toImpl(pageRef)->applicationNameForUserAgent());
409 }
410
411 void WKPageSetApplicationNameForUserAgent(WKPageRef pageRef, WKStringRef applicationNameRef)
412 {
413     toImpl(pageRef)->setApplicationNameForUserAgent(toWTFString(applicationNameRef));
414 }
415
416 WKStringRef WKPageCopyCustomUserAgent(WKPageRef pageRef)
417 {
418     return toCopiedAPI(toImpl(pageRef)->customUserAgent());
419 }
420
421 void WKPageSetCustomUserAgent(WKPageRef pageRef, WKStringRef userAgentRef)
422 {
423     toImpl(pageRef)->setCustomUserAgent(toWTFString(userAgentRef));
424 }
425
426 void WKPageSetUserContentExtensionsEnabled(WKPageRef pageRef, bool enabled)
427 {
428     // FIXME: Remove this function once it is no longer used.
429 }
430
431 bool WKPageSupportsTextEncoding(WKPageRef pageRef)
432 {
433     return toImpl(pageRef)->supportsTextEncoding();
434 }
435
436 WKStringRef WKPageCopyCustomTextEncodingName(WKPageRef pageRef)
437 {
438     return toCopiedAPI(toImpl(pageRef)->customTextEncodingName());
439 }
440
441 void WKPageSetCustomTextEncodingName(WKPageRef pageRef, WKStringRef encodingNameRef)
442 {
443     toImpl(pageRef)->setCustomTextEncodingName(toWTFString(encodingNameRef));
444 }
445
446 void WKPageTerminate(WKPageRef pageRef)
447 {
448     Ref<WebProcessProxy> protectedProcessProxy(toImpl(pageRef)->process());
449     protectedProcessProxy->requestTermination(ProcessTerminationReason::RequestedByClient);
450 }
451
452 WKStringRef WKPageGetSessionHistoryURLValueType()
453 {
454     static API::String& sessionHistoryURLValueType = API::String::create("SessionHistoryURL").leakRef();
455     return toAPI(&sessionHistoryURLValueType);
456 }
457
458 WKStringRef WKPageGetSessionBackForwardListItemValueType()
459 {
460     static API::String& sessionBackForwardListValueType = API::String::create("SessionBackForwardListItem").leakRef();
461     return toAPI(&sessionBackForwardListValueType);
462 }
463
464 WKTypeRef WKPageCopySessionState(WKPageRef pageRef, void* context, WKPageSessionStateFilterCallback filter)
465 {
466     // FIXME: This is a hack to make sure we return a WKDataRef to maintain compatibility with older versions of Safari.
467     bool shouldReturnData = !(reinterpret_cast<uintptr_t>(context) & 1);
468     context = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(context) & ~1);
469
470     auto sessionState = toImpl(pageRef)->sessionState([pageRef, context, filter](WebBackForwardListItem& item) {
471         if (filter) {
472             if (!filter(pageRef, WKPageGetSessionBackForwardListItemValueType(), toAPI(&item), context))
473                 return false;
474
475             if (!filter(pageRef, WKPageGetSessionHistoryURLValueType(), toURLRef(item.originalURL().impl()), context))
476                 return false;
477         }
478
479         return true;
480     });
481
482     if (shouldReturnData)
483         return toAPI(encodeLegacySessionState(sessionState).leakRef());
484
485     return toAPI(&API::SessionState::create(WTFMove(sessionState)).leakRef());
486 }
487
488 static void restoreFromSessionState(WKPageRef pageRef, WKTypeRef sessionStateRef, bool navigate)
489 {
490     SessionState sessionState;
491
492     // FIXME: This is for backwards compatibility with Safari. Remove it once Safari no longer depends on it.
493     if (toImpl(sessionStateRef)->type() == API::Object::Type::Data) {
494         if (!decodeLegacySessionState(toImpl(static_cast<WKDataRef>(sessionStateRef))->bytes(), toImpl(static_cast<WKDataRef>(sessionStateRef))->size(), sessionState))
495             return;
496     } else {
497         ASSERT(toImpl(sessionStateRef)->type() == API::Object::Type::SessionState);
498
499         sessionState = toImpl(static_cast<WKSessionStateRef>(sessionStateRef))->sessionState();
500     }
501
502     toImpl(pageRef)->restoreFromSessionState(WTFMove(sessionState), navigate);
503 }
504
505 void WKPageRestoreFromSessionState(WKPageRef pageRef, WKTypeRef sessionStateRef)
506 {
507     restoreFromSessionState(pageRef, sessionStateRef, true);
508 }
509
510 void WKPageRestoreFromSessionStateWithoutNavigation(WKPageRef pageRef, WKTypeRef sessionStateRef)
511 {
512     restoreFromSessionState(pageRef, sessionStateRef, false);
513 }
514
515 double WKPageGetTextZoomFactor(WKPageRef pageRef)
516 {
517     return toImpl(pageRef)->textZoomFactor();
518 }
519
520 double WKPageGetBackingScaleFactor(WKPageRef pageRef)
521 {
522     return toImpl(pageRef)->deviceScaleFactor();
523 }
524
525 void WKPageSetCustomBackingScaleFactor(WKPageRef pageRef, double customScaleFactor)
526 {
527     toImpl(pageRef)->setCustomDeviceScaleFactor(customScaleFactor);
528 }
529
530 bool WKPageSupportsTextZoom(WKPageRef pageRef)
531 {
532     return toImpl(pageRef)->supportsTextZoom();
533 }
534
535 void WKPageSetTextZoomFactor(WKPageRef pageRef, double zoomFactor)
536 {
537     toImpl(pageRef)->setTextZoomFactor(zoomFactor);
538 }
539
540 double WKPageGetPageZoomFactor(WKPageRef pageRef)
541 {
542     return toImpl(pageRef)->pageZoomFactor();
543 }
544
545 void WKPageSetPageZoomFactor(WKPageRef pageRef, double zoomFactor)
546 {
547     toImpl(pageRef)->setPageZoomFactor(zoomFactor);
548 }
549
550 void WKPageSetPageAndTextZoomFactors(WKPageRef pageRef, double pageZoomFactor, double textZoomFactor)
551 {
552     toImpl(pageRef)->setPageAndTextZoomFactors(pageZoomFactor, textZoomFactor);
553 }
554
555 void WKPageSetScaleFactor(WKPageRef pageRef, double scale, WKPoint origin)
556 {
557     toImpl(pageRef)->scalePage(scale, toIntPoint(origin));
558 }
559
560 double WKPageGetScaleFactor(WKPageRef pageRef)
561 {
562     return toImpl(pageRef)->pageScaleFactor();
563 }
564
565 void WKPageSetUseFixedLayout(WKPageRef pageRef, bool fixed)
566 {
567     toImpl(pageRef)->setUseFixedLayout(fixed);
568 }
569
570 void WKPageSetFixedLayoutSize(WKPageRef pageRef, WKSize size)
571 {
572     toImpl(pageRef)->setFixedLayoutSize(toIntSize(size));
573 }
574
575 bool WKPageUseFixedLayout(WKPageRef pageRef)
576 {
577     return toImpl(pageRef)->useFixedLayout();
578 }
579
580 WKSize WKPageFixedLayoutSize(WKPageRef pageRef)
581 {
582     return toAPI(toImpl(pageRef)->fixedLayoutSize());
583 }
584
585 void WKPageListenForLayoutMilestones(WKPageRef pageRef, WKLayoutMilestones milestones)
586 {
587     toImpl(pageRef)->listenForLayoutMilestones(toLayoutMilestones(milestones));
588 }
589
590 bool WKPageHasHorizontalScrollbar(WKPageRef pageRef)
591 {
592     return toImpl(pageRef)->hasHorizontalScrollbar();
593 }
594
595 bool WKPageHasVerticalScrollbar(WKPageRef pageRef)
596 {
597     return toImpl(pageRef)->hasVerticalScrollbar();
598 }
599
600 void WKPageSetSuppressScrollbarAnimations(WKPageRef pageRef, bool suppressAnimations)
601 {
602     toImpl(pageRef)->setSuppressScrollbarAnimations(suppressAnimations);
603 }
604
605 bool WKPageAreScrollbarAnimationsSuppressed(WKPageRef pageRef)
606 {
607     return toImpl(pageRef)->areScrollbarAnimationsSuppressed();
608 }
609
610 bool WKPageIsPinnedToLeftSide(WKPageRef pageRef)
611 {
612     return toImpl(pageRef)->isPinnedToLeftSide();
613 }
614
615 bool WKPageIsPinnedToRightSide(WKPageRef pageRef)
616 {
617     return toImpl(pageRef)->isPinnedToRightSide();
618 }
619
620 bool WKPageIsPinnedToTopSide(WKPageRef pageRef)
621 {
622     return toImpl(pageRef)->isPinnedToTopSide();
623 }
624
625 bool WKPageIsPinnedToBottomSide(WKPageRef pageRef)
626 {
627     return toImpl(pageRef)->isPinnedToBottomSide();
628 }
629
630 bool WKPageRubberBandsAtLeft(WKPageRef pageRef)
631 {
632     return toImpl(pageRef)->rubberBandsAtLeft();
633 }
634
635 void WKPageSetRubberBandsAtLeft(WKPageRef pageRef, bool rubberBandsAtLeft)
636 {
637     toImpl(pageRef)->setRubberBandsAtLeft(rubberBandsAtLeft);
638 }
639
640 bool WKPageRubberBandsAtRight(WKPageRef pageRef)
641 {
642     return toImpl(pageRef)->rubberBandsAtRight();
643 }
644
645 void WKPageSetRubberBandsAtRight(WKPageRef pageRef, bool rubberBandsAtRight)
646 {
647     toImpl(pageRef)->setRubberBandsAtRight(rubberBandsAtRight);
648 }
649
650 bool WKPageRubberBandsAtTop(WKPageRef pageRef)
651 {
652     return toImpl(pageRef)->rubberBandsAtTop();
653 }
654
655 void WKPageSetRubberBandsAtTop(WKPageRef pageRef, bool rubberBandsAtTop)
656 {
657     toImpl(pageRef)->setRubberBandsAtTop(rubberBandsAtTop);
658 }
659
660 bool WKPageRubberBandsAtBottom(WKPageRef pageRef)
661 {
662     return toImpl(pageRef)->rubberBandsAtBottom();
663 }
664
665 void WKPageSetRubberBandsAtBottom(WKPageRef pageRef, bool rubberBandsAtBottom)
666 {
667     toImpl(pageRef)->setRubberBandsAtBottom(rubberBandsAtBottom);
668 }
669
670 bool WKPageVerticalRubberBandingIsEnabled(WKPageRef pageRef)
671 {
672     return toImpl(pageRef)->verticalRubberBandingIsEnabled();
673 }
674
675 void WKPageSetEnableVerticalRubberBanding(WKPageRef pageRef, bool enableVerticalRubberBanding)
676 {
677     toImpl(pageRef)->setEnableVerticalRubberBanding(enableVerticalRubberBanding);
678 }
679
680 bool WKPageHorizontalRubberBandingIsEnabled(WKPageRef pageRef)
681 {
682     return toImpl(pageRef)->horizontalRubberBandingIsEnabled();
683 }
684
685 void WKPageSetEnableHorizontalRubberBanding(WKPageRef pageRef, bool enableHorizontalRubberBanding)
686 {
687     toImpl(pageRef)->setEnableHorizontalRubberBanding(enableHorizontalRubberBanding);
688 }
689
690 void WKPageSetBackgroundExtendsBeyondPage(WKPageRef pageRef, bool backgroundExtendsBeyondPage)
691 {
692     toImpl(pageRef)->setBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage);
693 }
694
695 bool WKPageBackgroundExtendsBeyondPage(WKPageRef pageRef)
696 {
697     return toImpl(pageRef)->backgroundExtendsBeyondPage();
698 }
699
700 void WKPageSetPaginationMode(WKPageRef pageRef, WKPaginationMode paginationMode)
701 {
702     WebCore::Pagination::Mode mode;
703     switch (paginationMode) {
704     case kWKPaginationModeUnpaginated:
705         mode = WebCore::Pagination::Unpaginated;
706         break;
707     case kWKPaginationModeLeftToRight:
708         mode = WebCore::Pagination::LeftToRightPaginated;
709         break;
710     case kWKPaginationModeRightToLeft:
711         mode = WebCore::Pagination::RightToLeftPaginated;
712         break;
713     case kWKPaginationModeTopToBottom:
714         mode = WebCore::Pagination::TopToBottomPaginated;
715         break;
716     case kWKPaginationModeBottomToTop:
717         mode = WebCore::Pagination::BottomToTopPaginated;
718         break;
719     default:
720         return;
721     }
722     toImpl(pageRef)->setPaginationMode(mode);
723 }
724
725 WKPaginationMode WKPageGetPaginationMode(WKPageRef pageRef)
726 {
727     switch (toImpl(pageRef)->paginationMode()) {
728     case WebCore::Pagination::Unpaginated:
729         return kWKPaginationModeUnpaginated;
730     case WebCore::Pagination::LeftToRightPaginated:
731         return kWKPaginationModeLeftToRight;
732     case WebCore::Pagination::RightToLeftPaginated:
733         return kWKPaginationModeRightToLeft;
734     case WebCore::Pagination::TopToBottomPaginated:
735         return kWKPaginationModeTopToBottom;
736     case WebCore::Pagination::BottomToTopPaginated:
737         return kWKPaginationModeBottomToTop;
738     }
739
740     ASSERT_NOT_REACHED();
741     return kWKPaginationModeUnpaginated;
742 }
743
744 void WKPageSetPaginationBehavesLikeColumns(WKPageRef pageRef, bool behavesLikeColumns)
745 {
746     toImpl(pageRef)->setPaginationBehavesLikeColumns(behavesLikeColumns);
747 }
748
749 bool WKPageGetPaginationBehavesLikeColumns(WKPageRef pageRef)
750 {
751     return toImpl(pageRef)->paginationBehavesLikeColumns();
752 }
753
754 void WKPageSetPageLength(WKPageRef pageRef, double pageLength)
755 {
756     toImpl(pageRef)->setPageLength(pageLength);
757 }
758
759 double WKPageGetPageLength(WKPageRef pageRef)
760 {
761     return toImpl(pageRef)->pageLength();
762 }
763
764 void WKPageSetGapBetweenPages(WKPageRef pageRef, double gap)
765 {
766     toImpl(pageRef)->setGapBetweenPages(gap);
767 }
768
769 double WKPageGetGapBetweenPages(WKPageRef pageRef)
770 {
771     return toImpl(pageRef)->gapBetweenPages();
772 }
773
774 void WKPageSetPaginationLineGridEnabled(WKPageRef pageRef, bool lineGridEnabled)
775 {
776     toImpl(pageRef)->setPaginationLineGridEnabled(lineGridEnabled);
777 }
778
779 bool WKPageGetPaginationLineGridEnabled(WKPageRef pageRef)
780 {
781     return toImpl(pageRef)->paginationLineGridEnabled();
782 }
783
784 unsigned WKPageGetPageCount(WKPageRef pageRef)
785 {
786     return toImpl(pageRef)->pageCount();
787 }
788
789 bool WKPageCanDelete(WKPageRef pageRef)
790 {
791     return toImpl(pageRef)->canDelete();
792 }
793
794 bool WKPageHasSelectedRange(WKPageRef pageRef)
795 {
796     return toImpl(pageRef)->hasSelectedRange();
797 }
798
799 bool WKPageIsContentEditable(WKPageRef pageRef)
800 {
801     return toImpl(pageRef)->isContentEditable();
802 }
803
804 void WKPageSetMaintainsInactiveSelection(WKPageRef pageRef, bool newValue)
805 {
806     return toImpl(pageRef)->setMaintainsInactiveSelection(newValue);
807 }
808
809 void WKPageCenterSelectionInVisibleArea(WKPageRef pageRef)
810 {
811     return toImpl(pageRef)->centerSelectionInVisibleArea();
812 }
813
814 void WKPageFindStringMatches(WKPageRef pageRef, WKStringRef string, WKFindOptions options, unsigned maxMatchCount)
815 {
816     toImpl(pageRef)->findStringMatches(toImpl(string)->string(), toFindOptions(options), maxMatchCount);
817 }
818
819 void WKPageGetImageForFindMatch(WKPageRef pageRef, int32_t matchIndex)
820 {
821     toImpl(pageRef)->getImageForFindMatch(matchIndex);
822 }
823
824 void WKPageSelectFindMatch(WKPageRef pageRef, int32_t matchIndex)
825 {
826     toImpl(pageRef)->selectFindMatch(matchIndex);
827 }
828
829 void WKPageFindString(WKPageRef pageRef, WKStringRef string, WKFindOptions options, unsigned maxMatchCount)
830 {
831     toImpl(pageRef)->findString(toImpl(string)->string(), toFindOptions(options), maxMatchCount);
832 }
833
834 void WKPageHideFindUI(WKPageRef pageRef)
835 {
836     toImpl(pageRef)->hideFindUI();
837 }
838
839 void WKPageCountStringMatches(WKPageRef pageRef, WKStringRef string, WKFindOptions options, unsigned maxMatchCount)
840 {
841     toImpl(pageRef)->countStringMatches(toImpl(string)->string(), toFindOptions(options), maxMatchCount);
842 }
843
844 void WKPageSetPageContextMenuClient(WKPageRef pageRef, const WKPageContextMenuClientBase* wkClient)
845 {
846 #if ENABLE(CONTEXT_MENUS)
847     class ContextMenuClient final : public API::Client<WKPageContextMenuClientBase>, public API::ContextMenuClient {
848     public:
849         explicit ContextMenuClient(const WKPageContextMenuClientBase* client)
850         {
851             initialize(client);
852         }
853
854     private:
855         void getContextMenuFromProposedMenu(WebPageProxy& page, Vector<Ref<WebKit::WebContextMenuItem>>&& proposedMenuVector, WebKit::WebContextMenuListenerProxy& contextMenuListener, const WebHitTestResultData& hitTestResultData, API::Object* userData) override
856         {
857             if (m_client.base.version >= 4 && m_client.getContextMenuFromProposedMenuAsync) {
858                 Vector<RefPtr<API::Object>> proposedMenuItems;
859                 proposedMenuItems.reserveInitialCapacity(proposedMenuVector.size());
860                 
861                 for (const auto& menuItem : proposedMenuVector)
862                     proposedMenuItems.uncheckedAppend(menuItem.ptr());
863                 
864                 auto webHitTestResult = API::HitTestResult::create(hitTestResultData);
865                 m_client.getContextMenuFromProposedMenuAsync(toAPI(&page), toAPI(API::Array::create(WTFMove(proposedMenuItems)).ptr()), toAPI(&contextMenuListener), toAPI(webHitTestResult.ptr()), toAPI(userData), m_client.base.clientInfo);
866                 return;
867             }
868             
869             if (!m_client.getContextMenuFromProposedMenu && !m_client.getContextMenuFromProposedMenu_deprecatedForUseWithV0) {
870                 contextMenuListener.useContextMenuItems(WTFMove(proposedMenuVector));
871                 return;
872             }
873
874             if (m_client.base.version >= 2 && !m_client.getContextMenuFromProposedMenu) {
875                 contextMenuListener.useContextMenuItems(WTFMove(proposedMenuVector));
876                 return;
877             }
878
879             Vector<RefPtr<API::Object>> proposedMenuItems;
880             proposedMenuItems.reserveInitialCapacity(proposedMenuVector.size());
881
882             for (const auto& menuItem : proposedMenuVector)
883                 proposedMenuItems.uncheckedAppend(menuItem.ptr());
884
885             WKArrayRef newMenu = nullptr;
886             if (m_client.base.version >= 2) {
887                 auto webHitTestResult = API::HitTestResult::create(hitTestResultData);
888                 m_client.getContextMenuFromProposedMenu(toAPI(&page), toAPI(API::Array::create(WTFMove(proposedMenuItems)).ptr()), &newMenu, toAPI(webHitTestResult.ptr()), toAPI(userData), m_client.base.clientInfo);
889             } else
890                 m_client.getContextMenuFromProposedMenu_deprecatedForUseWithV0(toAPI(&page), toAPI(API::Array::create(WTFMove(proposedMenuItems)).ptr()), &newMenu, toAPI(userData), m_client.base.clientInfo);
891
892             RefPtr<API::Array> array = adoptRef(toImpl(newMenu));
893
894             Vector<Ref<WebContextMenuItem>> customMenu;
895             size_t newSize = array ? array->size() : 0;
896             customMenu.reserveInitialCapacity(newSize);
897             for (size_t i = 0; i < newSize; ++i) {
898                 WebContextMenuItem* item = array->at<WebContextMenuItem>(i);
899                 if (!item) {
900                     LOG(ContextMenu, "New menu entry at index %i is not a WebContextMenuItem", (int)i);
901                     continue;
902                 }
903
904                 customMenu.uncheckedAppend(*item);
905             }
906
907             contextMenuListener.useContextMenuItems(WTFMove(customMenu));
908         }
909
910         void customContextMenuItemSelected(WebPageProxy& page, const WebContextMenuItemData& itemData) override
911         {
912             if (!m_client.customContextMenuItemSelected)
913                 return;
914
915             m_client.customContextMenuItemSelected(toAPI(&page), toAPI(WebContextMenuItem::create(itemData).ptr()), m_client.base.clientInfo);
916         }
917
918         bool showContextMenu(WebPageProxy& page, const WebCore::IntPoint& menuLocation, const Vector<Ref<WebContextMenuItem>>& menuItemsVector) override
919         {
920             if (!m_client.showContextMenu)
921                 return false;
922
923             Vector<RefPtr<API::Object>> menuItems;
924             menuItems.reserveInitialCapacity(menuItemsVector.size());
925
926             for (const auto& menuItem : menuItemsVector)
927                 menuItems.uncheckedAppend(menuItem.ptr());
928
929             m_client.showContextMenu(toAPI(&page), toAPI(menuLocation), toAPI(API::Array::create(WTFMove(menuItems)).ptr()), m_client.base.clientInfo);
930
931             return true;
932         }
933
934         bool hideContextMenu(WebPageProxy& page) override
935         {
936             if (!m_client.hideContextMenu)
937                 return false;
938
939             m_client.hideContextMenu(toAPI(&page), m_client.base.clientInfo);
940
941             return true;
942         }
943     };
944
945     toImpl(pageRef)->setContextMenuClient(std::make_unique<ContextMenuClient>(wkClient));
946 #else
947     UNUSED_PARAM(pageRef);
948     UNUSED_PARAM(wkClient);
949 #endif
950 }
951
952 void WKPageSetPageDiagnosticLoggingClient(WKPageRef pageRef, const WKPageDiagnosticLoggingClientBase* wkClient)
953 {
954     toImpl(pageRef)->setDiagnosticLoggingClient(std::make_unique<WebPageDiagnosticLoggingClient>(wkClient));
955 }
956
957 void WKPageSetPageFindClient(WKPageRef pageRef, const WKPageFindClientBase* wkClient)
958 {
959     class FindClient : public API::Client<WKPageFindClientBase>, public API::FindClient {
960     public:
961         explicit FindClient(const WKPageFindClientBase* client)
962         {
963             initialize(client);
964         }
965
966     private:
967         void didFindString(WebPageProxy* page, const String& string, const Vector<WebCore::IntRect>&, uint32_t matchCount, int32_t, bool didWrapAround) override
968         {
969             if (!m_client.didFindString)
970                 return;
971             
972             m_client.didFindString(toAPI(page), toAPI(string.impl()), matchCount, m_client.base.clientInfo);
973         }
974
975         void didFailToFindString(WebPageProxy* page, const String& string) override
976         {
977             if (!m_client.didFailToFindString)
978                 return;
979             
980             m_client.didFailToFindString(toAPI(page), toAPI(string.impl()), m_client.base.clientInfo);
981         }
982
983         void didCountStringMatches(WebPageProxy* page, const String& string, uint32_t matchCount) override
984         {
985             if (!m_client.didCountStringMatches)
986                 return;
987
988             m_client.didCountStringMatches(toAPI(page), toAPI(string.impl()), matchCount, m_client.base.clientInfo);
989         }
990     };
991
992     toImpl(pageRef)->setFindClient(std::make_unique<FindClient>(wkClient));
993 }
994
995 void WKPageSetPageFindMatchesClient(WKPageRef pageRef, const WKPageFindMatchesClientBase* wkClient)
996 {
997     class FindMatchesClient : public API::Client<WKPageFindMatchesClientBase>, public API::FindMatchesClient {
998     public:
999         explicit FindMatchesClient(const WKPageFindMatchesClientBase* client)
1000         {
1001             initialize(client);
1002         }
1003
1004     private:
1005         void didFindStringMatches(WebPageProxy* page, const String& string, const Vector<Vector<WebCore::IntRect>>& matchRects, int32_t index) override
1006         {
1007             if (!m_client.didFindStringMatches)
1008                 return;
1009
1010             Vector<RefPtr<API::Object>> matches;
1011             matches.reserveInitialCapacity(matchRects.size());
1012
1013             for (const auto& rects : matchRects) {
1014                 Vector<RefPtr<API::Object>> apiRects;
1015                 apiRects.reserveInitialCapacity(rects.size());
1016
1017                 for (const auto& rect : rects)
1018                     apiRects.uncheckedAppend(API::Rect::create(toAPI(rect)));
1019
1020                 matches.uncheckedAppend(API::Array::create(WTFMove(apiRects)));
1021             }
1022
1023             m_client.didFindStringMatches(toAPI(page), toAPI(string.impl()), toAPI(API::Array::create(WTFMove(matches)).ptr()), index, m_client.base.clientInfo);
1024         }
1025
1026         void didGetImageForMatchResult(WebPageProxy* page, WebImage* image, int32_t index) override
1027         {
1028             if (!m_client.didGetImageForMatchResult)
1029                 return;
1030
1031             m_client.didGetImageForMatchResult(toAPI(page), toAPI(image), index, m_client.base.clientInfo);
1032         }
1033     };
1034
1035     toImpl(pageRef)->setFindMatchesClient(std::make_unique<FindMatchesClient>(wkClient));
1036 }
1037
1038 void WKPageSetPageInjectedBundleClient(WKPageRef pageRef, const WKPageInjectedBundleClientBase* wkClient)
1039 {
1040     toImpl(pageRef)->setInjectedBundleClient(wkClient);
1041 }
1042
1043 void WKPageSetPageFormClient(WKPageRef pageRef, const WKPageFormClientBase* wkClient)
1044 {
1045     toImpl(pageRef)->setFormClient(std::make_unique<WebFormClient>(wkClient));
1046 }
1047
1048 void WKPageSetPageLoaderClient(WKPageRef pageRef, const WKPageLoaderClientBase* wkClient)
1049 {
1050     class LoaderClient : public API::Client<WKPageLoaderClientBase>, public API::LoaderClient {
1051     public:
1052         explicit LoaderClient(const WKPageLoaderClientBase* client)
1053         {
1054             initialize(client);
1055             
1056 #if !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED > 101400
1057             // WKPageSetPageLoaderClient is deprecated. Use WKPageSetPageNavigationClient instead.
1058             RELEASE_ASSERT(!m_client.didFinishDocumentLoadForFrame);
1059             RELEASE_ASSERT(!m_client.didSameDocumentNavigationForFrame);
1060             RELEASE_ASSERT(!m_client.didReceiveTitleForFrame);
1061             RELEASE_ASSERT(!m_client.didFirstLayoutForFrame);
1062             RELEASE_ASSERT(!m_client.didRemoveFrameFromHierarchy);
1063             RELEASE_ASSERT(!m_client.didDisplayInsecureContentForFrame);
1064             RELEASE_ASSERT(!m_client.didRunInsecureContentForFrame);
1065             RELEASE_ASSERT(!m_client.canAuthenticateAgainstProtectionSpaceInFrame);
1066             RELEASE_ASSERT(!m_client.didReceiveAuthenticationChallengeInFrame);
1067             RELEASE_ASSERT(!m_client.didStartProgress);
1068             RELEASE_ASSERT(!m_client.didChangeProgress);
1069             RELEASE_ASSERT(!m_client.didFinishProgress);
1070             RELEASE_ASSERT(!m_client.processDidBecomeUnresponsive);
1071             RELEASE_ASSERT(!m_client.processDidBecomeResponsive);
1072             RELEASE_ASSERT(!m_client.shouldGoToBackForwardListItem);
1073             RELEASE_ASSERT(!m_client.didFailToInitializePlugin_deprecatedForUseWithV0);
1074             RELEASE_ASSERT(!m_client.didDetectXSSForFrame);
1075             RELEASE_ASSERT(!m_client.didNewFirstVisuallyNonEmptyLayout_unavailable);
1076             RELEASE_ASSERT(!m_client.willGoToBackForwardListItem);
1077             RELEASE_ASSERT(!m_client.interactionOccurredWhileProcessUnresponsive);
1078             RELEASE_ASSERT(!m_client.pluginDidFail_deprecatedForUseWithV1);
1079             RELEASE_ASSERT(!m_client.didReceiveIntentForFrame_unavailable);
1080             RELEASE_ASSERT(!m_client.registerIntentServiceForFrame_unavailable);
1081             RELEASE_ASSERT(!m_client.pluginLoadPolicy_deprecatedForUseWithV2);
1082             RELEASE_ASSERT(!m_client.pluginDidFail);
1083             RELEASE_ASSERT(!m_client.pluginLoadPolicy);
1084             RELEASE_ASSERT(!m_client.webGLLoadPolicy);
1085             RELEASE_ASSERT(!m_client.resolveWebGLLoadPolicy);
1086             RELEASE_ASSERT(!m_client.navigationGestureDidBegin);
1087             RELEASE_ASSERT(!m_client.navigationGestureWillEnd);
1088             RELEASE_ASSERT(!m_client.navigationGestureDidEnd);
1089 #endif
1090         }
1091
1092     private:
1093         
1094         void didCommitLoadForFrame(WebPageProxy& page, WebFrameProxy& frame, API::Navigation*, API::Object* userData) override
1095         {
1096             if (!m_client.didCommitLoadForFrame)
1097                 return;
1098
1099             m_client.didCommitLoadForFrame(toAPI(&page), toAPI(&frame), toAPI(userData), m_client.base.clientInfo);
1100         }
1101         
1102         void didStartProvisionalLoadForFrame(WebPageProxy& page, WebFrameProxy& frame, API::Navigation*, API::Object* userData) override
1103         {
1104             if (!m_client.didStartProvisionalLoadForFrame)
1105                 return;
1106
1107             m_client.didStartProvisionalLoadForFrame(toAPI(&page), toAPI(&frame), toAPI(userData), m_client.base.clientInfo);
1108         }
1109
1110         void didReceiveServerRedirectForProvisionalLoadForFrame(WebPageProxy& page, WebFrameProxy& frame, API::Navigation*, API::Object* userData) override
1111         {
1112             if (!m_client.didReceiveServerRedirectForProvisionalLoadForFrame)
1113                 return;
1114
1115             m_client.didReceiveServerRedirectForProvisionalLoadForFrame(toAPI(&page), toAPI(&frame), toAPI(userData), m_client.base.clientInfo);
1116         }
1117
1118         void didFailProvisionalLoadWithErrorForFrame(WebPageProxy& page, WebFrameProxy& frame, API::Navigation*, const WebCore::ResourceError& error, API::Object* userData) override
1119         {
1120             if (!m_client.didFailProvisionalLoadWithErrorForFrame)
1121                 return;
1122
1123             m_client.didFailProvisionalLoadWithErrorForFrame(toAPI(&page), toAPI(&frame), toAPI(error), toAPI(userData), m_client.base.clientInfo);
1124         }
1125
1126         void didFinishLoadForFrame(WebPageProxy& page, WebFrameProxy& frame, API::Navigation*, API::Object* userData) override
1127         {
1128             if (!m_client.didFinishLoadForFrame)
1129                 return;
1130
1131             m_client.didFinishLoadForFrame(toAPI(&page), toAPI(&frame), toAPI(userData), m_client.base.clientInfo);
1132         }
1133
1134         void didFailLoadWithErrorForFrame(WebPageProxy& page, WebFrameProxy& frame, API::Navigation*, const WebCore::ResourceError& error, API::Object* userData) override
1135         {
1136             if (!m_client.didFailLoadWithErrorForFrame)
1137                 return;
1138
1139             m_client.didFailLoadWithErrorForFrame(toAPI(&page), toAPI(&frame), toAPI(error), toAPI(userData), m_client.base.clientInfo);
1140         }
1141
1142         void didFirstVisuallyNonEmptyLayoutForFrame(WebPageProxy& page, WebFrameProxy& frame, API::Object* userData) override
1143         {
1144             if (!m_client.didFirstVisuallyNonEmptyLayoutForFrame)
1145                 return;
1146
1147             m_client.didFirstVisuallyNonEmptyLayoutForFrame(toAPI(&page), toAPI(&frame), toAPI(userData), m_client.base.clientInfo);
1148         }
1149
1150         void didReachLayoutMilestone(WebPageProxy& page, OptionSet<WebCore::LayoutMilestone> milestones) override
1151         {
1152             if (!m_client.didLayout)
1153                 return;
1154
1155             m_client.didLayout(toAPI(&page), toWKLayoutMilestones(milestones), nullptr, m_client.base.clientInfo);
1156         }
1157
1158         bool processDidCrash(WebPageProxy& page) override
1159         {
1160             if (!m_client.processDidCrash)
1161                 return false;
1162
1163             m_client.processDidCrash(toAPI(&page), m_client.base.clientInfo);
1164             return true;
1165         }
1166
1167         void didChangeBackForwardList(WebPageProxy& page, WebBackForwardListItem* addedItem, Vector<Ref<WebBackForwardListItem>>&& removedItems) override
1168         {
1169             if (!m_client.didChangeBackForwardList)
1170                 return;
1171
1172             RefPtr<API::Array> removedItemsArray;
1173             if (!removedItems.isEmpty()) {
1174                 Vector<RefPtr<API::Object>> removedItemsVector;
1175                 removedItemsVector.reserveInitialCapacity(removedItems.size());
1176                 for (auto& removedItem : removedItems)
1177                 removedItemsVector.append(WTFMove(removedItem));
1178
1179                 removedItemsArray = API::Array::create(WTFMove(removedItemsVector));
1180             }
1181
1182             m_client.didChangeBackForwardList(toAPI(&page), toAPI(addedItem), toAPI(removedItemsArray.get()), m_client.base.clientInfo);
1183         }
1184         
1185         bool shouldKeepCurrentBackForwardListItemInList(WebKit::WebPageProxy& page, WebKit::WebBackForwardListItem& item) override
1186         {
1187             if (!m_client.shouldKeepCurrentBackForwardListItemInList)
1188                 return true;
1189
1190             return m_client.shouldKeepCurrentBackForwardListItemInList(toAPI(&page), toAPI(&item), m_client.base.clientInfo);
1191         }
1192     };
1193
1194     WebPageProxy* webPageProxy = toImpl(pageRef);
1195
1196     auto loaderClient = std::make_unique<LoaderClient>(wkClient);
1197
1198     // It would be nice to get rid of this code and transition all clients to using didLayout instead of
1199     // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required
1200     // for backwards compatibility.
1201     OptionSet<WebCore::LayoutMilestone> milestones;
1202     if (loaderClient->client().didFirstLayoutForFrame)
1203         milestones.add(WebCore::DidFirstLayout);
1204     if (loaderClient->client().didFirstVisuallyNonEmptyLayoutForFrame)
1205         milestones.add(WebCore::DidFirstVisuallyNonEmptyLayout);
1206
1207     if (milestones)
1208         webPageProxy->process().send(Messages::WebPage::ListenForLayoutMilestones(milestones), webPageProxy->pageID());
1209
1210     webPageProxy->setLoaderClient(WTFMove(loaderClient));
1211 }
1212
1213 void WKPageSetPagePolicyClient(WKPageRef pageRef, const WKPagePolicyClientBase* wkClient)
1214 {
1215     class PolicyClient : public API::Client<WKPagePolicyClientBase>, public API::PolicyClient {
1216     public:
1217         explicit PolicyClient(const WKPagePolicyClientBase* client)
1218         {
1219             initialize(client);
1220         }
1221
1222     private:
1223         void decidePolicyForNavigationAction(WebPageProxy& page, WebFrameProxy* frame, const NavigationActionData& navigationActionData, WebFrameProxy* originatingFrame, const WebCore::ResourceRequest& originalResourceRequest, const WebCore::ResourceRequest& resourceRequest, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userData) override
1224         {
1225             if (!m_client.decidePolicyForNavigationAction_deprecatedForUseWithV0 && !m_client.decidePolicyForNavigationAction_deprecatedForUseWithV1 && !m_client.decidePolicyForNavigationAction) {
1226                 listener->use();
1227                 return;
1228             }
1229
1230             Ref<API::URLRequest> originalRequest = API::URLRequest::create(originalResourceRequest);
1231             Ref<API::URLRequest> request = API::URLRequest::create(resourceRequest);
1232
1233             if (m_client.decidePolicyForNavigationAction_deprecatedForUseWithV0)
1234                 m_client.decidePolicyForNavigationAction_deprecatedForUseWithV0(toAPI(&page), toAPI(frame), toAPI(navigationActionData.navigationType), toAPI(navigationActionData.modifiers), toAPI(navigationActionData.mouseButton), toAPI(request.ptr()), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
1235             else if (m_client.decidePolicyForNavigationAction_deprecatedForUseWithV1)
1236                 m_client.decidePolicyForNavigationAction_deprecatedForUseWithV1(toAPI(&page), toAPI(frame), toAPI(navigationActionData.navigationType), toAPI(navigationActionData.modifiers), toAPI(navigationActionData.mouseButton), toAPI(originatingFrame), toAPI(request.ptr()), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
1237             else
1238                 m_client.decidePolicyForNavigationAction(toAPI(&page), toAPI(frame), toAPI(navigationActionData.navigationType), toAPI(navigationActionData.modifiers), toAPI(navigationActionData.mouseButton), toAPI(originatingFrame), toAPI(originalRequest.ptr()), toAPI(request.ptr()), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
1239         }
1240
1241         void decidePolicyForNewWindowAction(WebPageProxy& page, WebFrameProxy& frame, const NavigationActionData& navigationActionData, const WebCore::ResourceRequest& resourceRequest, const String& frameName, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userData) override
1242         {
1243             if (!m_client.decidePolicyForNewWindowAction) {
1244                 listener->use();
1245                 return;
1246             }
1247
1248             Ref<API::URLRequest> request = API::URLRequest::create(resourceRequest);
1249
1250             m_client.decidePolicyForNewWindowAction(toAPI(&page), toAPI(&frame), toAPI(navigationActionData.navigationType), toAPI(navigationActionData.modifiers), toAPI(navigationActionData.mouseButton), toAPI(request.ptr()), toAPI(frameName.impl()), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
1251         }
1252
1253         void decidePolicyForResponse(WebPageProxy& page, WebFrameProxy& frame, const WebCore::ResourceResponse& resourceResponse, const WebCore::ResourceRequest& resourceRequest, bool canShowMIMEType, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userData) override
1254         {
1255             if (!m_client.decidePolicyForResponse_deprecatedForUseWithV0 && !m_client.decidePolicyForResponse) {
1256                 listener->use();
1257                 return;
1258             }
1259
1260             Ref<API::URLResponse> response = API::URLResponse::create(resourceResponse);
1261             Ref<API::URLRequest> request = API::URLRequest::create(resourceRequest);
1262
1263             if (m_client.decidePolicyForResponse_deprecatedForUseWithV0)
1264                 m_client.decidePolicyForResponse_deprecatedForUseWithV0(toAPI(&page), toAPI(&frame), toAPI(response.ptr()), toAPI(request.ptr()), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
1265             else
1266                 m_client.decidePolicyForResponse(toAPI(&page), toAPI(&frame), toAPI(response.ptr()), toAPI(request.ptr()), canShowMIMEType, toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
1267         }
1268
1269         void unableToImplementPolicy(WebPageProxy& page, WebFrameProxy& frame, const WebCore::ResourceError& error, API::Object* userData) override
1270         {
1271             if (!m_client.unableToImplementPolicy)
1272                 return;
1273             
1274             m_client.unableToImplementPolicy(toAPI(&page), toAPI(&frame), toAPI(error), toAPI(userData), m_client.base.clientInfo);
1275         }
1276     };
1277
1278     toImpl(pageRef)->setPolicyClient(std::make_unique<PolicyClient>(wkClient));
1279 }
1280
1281 namespace WebKit {
1282 using namespace WebCore;
1283     
1284 class RunBeforeUnloadConfirmPanelResultListener : public API::ObjectImpl<API::Object::Type::RunBeforeUnloadConfirmPanelResultListener> {
1285 public:
1286     static Ref<RunBeforeUnloadConfirmPanelResultListener> create(Function<void(bool)>&& completionHandler)
1287     {
1288         return adoptRef(*new RunBeforeUnloadConfirmPanelResultListener(WTFMove(completionHandler)));
1289     }
1290
1291     virtual ~RunBeforeUnloadConfirmPanelResultListener()
1292     {
1293     }
1294
1295     void call(bool result)
1296     {
1297         m_completionHandler(result);
1298     }
1299
1300 private:
1301     explicit RunBeforeUnloadConfirmPanelResultListener(Function<void (bool)>&& completionHandler)
1302         : m_completionHandler(WTFMove(completionHandler))
1303     {
1304     }
1305
1306     Function<void (bool)> m_completionHandler;
1307 };
1308
1309 class RunJavaScriptAlertResultListener : public API::ObjectImpl<API::Object::Type::RunJavaScriptAlertResultListener> {
1310 public:
1311     static Ref<RunJavaScriptAlertResultListener> create(Function<void()>&& completionHandler)
1312     {
1313         return adoptRef(*new RunJavaScriptAlertResultListener(WTFMove(completionHandler)));
1314     }
1315
1316     virtual ~RunJavaScriptAlertResultListener()
1317     {
1318     }
1319
1320     void call()
1321     {
1322         m_completionHandler();
1323     }
1324
1325 private:
1326     explicit RunJavaScriptAlertResultListener(Function<void ()>&& completionHandler)
1327         : m_completionHandler(WTFMove(completionHandler))
1328     {
1329     }
1330     
1331     Function<void ()> m_completionHandler;
1332 };
1333
1334 class RunJavaScriptConfirmResultListener : public API::ObjectImpl<API::Object::Type::RunJavaScriptConfirmResultListener> {
1335 public:
1336     static Ref<RunJavaScriptConfirmResultListener> create(Function<void(bool)>&& completionHandler)
1337     {
1338         return adoptRef(*new RunJavaScriptConfirmResultListener(WTFMove(completionHandler)));
1339     }
1340
1341     virtual ~RunJavaScriptConfirmResultListener()
1342     {
1343     }
1344
1345     void call(bool result)
1346     {
1347         m_completionHandler(result);
1348     }
1349
1350 private:
1351     explicit RunJavaScriptConfirmResultListener(Function<void(bool)>&& completionHandler)
1352         : m_completionHandler(WTFMove(completionHandler))
1353     {
1354     }
1355
1356     Function<void (bool)> m_completionHandler;
1357 };
1358
1359 class RunJavaScriptPromptResultListener : public API::ObjectImpl<API::Object::Type::RunJavaScriptPromptResultListener> {
1360 public:
1361     static Ref<RunJavaScriptPromptResultListener> create(Function<void(const String&)>&& completionHandler)
1362     {
1363         return adoptRef(*new RunJavaScriptPromptResultListener(WTFMove(completionHandler)));
1364     }
1365
1366     virtual ~RunJavaScriptPromptResultListener()
1367     {
1368     }
1369
1370     void call(const String& result)
1371     {
1372         m_completionHandler(result);
1373     }
1374
1375 private:
1376     explicit RunJavaScriptPromptResultListener(Function<void(const String&)>&& completionHandler)
1377         : m_completionHandler(WTFMove(completionHandler))
1378     {
1379     }
1380
1381     Function<void (const String&)> m_completionHandler;
1382 };
1383
1384 class RequestStorageAccessConfirmResultListener : public API::ObjectImpl<API::Object::Type::RequestStorageAccessConfirmResultListener> {
1385 public:
1386     static Ref<RequestStorageAccessConfirmResultListener> create(CompletionHandler<void(bool)>&& completionHandler)
1387     {
1388         return adoptRef(*new RequestStorageAccessConfirmResultListener(WTFMove(completionHandler)));
1389     }
1390     
1391     virtual ~RequestStorageAccessConfirmResultListener()
1392     {
1393     }
1394     
1395     void call(bool result)
1396     {
1397         m_completionHandler(result);
1398     }
1399     
1400 private:
1401     explicit RequestStorageAccessConfirmResultListener(CompletionHandler<void(bool)>&& completionHandler)
1402         : m_completionHandler(WTFMove(completionHandler))
1403     {
1404     }
1405     
1406     CompletionHandler<void(bool)> m_completionHandler;
1407 };
1408
1409 WK_ADD_API_MAPPING(WKPageRunBeforeUnloadConfirmPanelResultListenerRef, RunBeforeUnloadConfirmPanelResultListener)
1410 WK_ADD_API_MAPPING(WKPageRunJavaScriptAlertResultListenerRef, RunJavaScriptAlertResultListener)
1411 WK_ADD_API_MAPPING(WKPageRunJavaScriptConfirmResultListenerRef, RunJavaScriptConfirmResultListener)
1412 WK_ADD_API_MAPPING(WKPageRunJavaScriptPromptResultListenerRef, RunJavaScriptPromptResultListener)
1413 WK_ADD_API_MAPPING(WKPageRequestStorageAccessConfirmResultListenerRef, RequestStorageAccessConfirmResultListener)
1414
1415 }
1416
1417 WKTypeID WKPageRunBeforeUnloadConfirmPanelResultListenerGetTypeID()
1418 {
1419     return toAPI(RunBeforeUnloadConfirmPanelResultListener::APIType);
1420 }
1421
1422 void WKPageRunBeforeUnloadConfirmPanelResultListenerCall(WKPageRunBeforeUnloadConfirmPanelResultListenerRef listener, bool result)
1423 {
1424     toImpl(listener)->call(result);
1425 }
1426
1427 WKTypeID WKPageRunJavaScriptAlertResultListenerGetTypeID()
1428 {
1429     return toAPI(RunJavaScriptAlertResultListener::APIType);
1430 }
1431
1432 void WKPageRunJavaScriptAlertResultListenerCall(WKPageRunJavaScriptAlertResultListenerRef listener)
1433 {
1434     toImpl(listener)->call();
1435 }
1436
1437 WKTypeID WKPageRunJavaScriptConfirmResultListenerGetTypeID()
1438 {
1439     return toAPI(RunJavaScriptConfirmResultListener::APIType);
1440 }
1441
1442 void WKPageRunJavaScriptConfirmResultListenerCall(WKPageRunJavaScriptConfirmResultListenerRef listener, bool result)
1443 {
1444     toImpl(listener)->call(result);
1445 }
1446
1447 WKTypeID WKPageRunJavaScriptPromptResultListenerGetTypeID()
1448 {
1449     return toAPI(RunJavaScriptPromptResultListener::APIType);
1450 }
1451
1452 void WKPageRunJavaScriptPromptResultListenerCall(WKPageRunJavaScriptPromptResultListenerRef listener, WKStringRef result)
1453 {
1454     toImpl(listener)->call(toWTFString(result));
1455 }
1456
1457 WKTypeID WKPageRequestStorageAccessConfirmResultListenerGetTypeID()
1458 {
1459     return toAPI(RequestStorageAccessConfirmResultListener::APIType);
1460 }
1461
1462 void WKPageRequestStorageAccessConfirmResultListenerCall(WKPageRequestStorageAccessConfirmResultListenerRef listener, bool result)
1463 {
1464     toImpl(listener)->call(result);
1465 }
1466
1467 void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient)
1468 {
1469     class UIClient : public API::Client<WKPageUIClientBase>, public API::UIClient {
1470     public:
1471         explicit UIClient(const WKPageUIClientBase* client)
1472         {
1473             initialize(client);
1474         }
1475
1476     private:
1477         void createNewPage(WebPageProxy& page, Ref<API::FrameInfo>&& sourceFrameInfo, WebCore::ResourceRequest&& resourceRequest, WebCore::WindowFeatures&& windowFeatures, NavigationActionData&& navigationActionData, CompletionHandler<void(RefPtr<WebPageProxy>&&)>&& completionHandler) final
1478         {
1479             if (m_client.createNewPage) {
1480                 auto configuration = page.configuration().copy();
1481                 configuration->setRelatedPage(&page);
1482
1483                 auto userInitiatedActivity = page.process().userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
1484                 bool shouldOpenAppLinks = !hostsAreEqual(sourceFrameInfo->request().url(), resourceRequest.url());
1485                 auto apiNavigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.ptr(), nullptr, WTF::nullopt, WTFMove(resourceRequest), URL(), shouldOpenAppLinks, WTFMove(userInitiatedActivity));
1486
1487                 auto apiWindowFeatures = API::WindowFeatures::create(windowFeatures);
1488
1489                 return completionHandler(adoptRef(toImpl(m_client.createNewPage(toAPI(&page), toAPI(configuration.ptr()), toAPI(apiNavigationAction.ptr()), toAPI(apiWindowFeatures.ptr()), m_client.base.clientInfo))));
1490             }
1491         
1492             if (m_client.createNewPage_deprecatedForUseWithV1 || m_client.createNewPage_deprecatedForUseWithV0) {
1493                 API::Dictionary::MapType map;
1494                 if (windowFeatures.x)
1495                     map.set("x", API::Double::create(*windowFeatures.x));
1496                 if (windowFeatures.y)
1497                     map.set("y", API::Double::create(*windowFeatures.y));
1498                 if (windowFeatures.width)
1499                     map.set("width", API::Double::create(*windowFeatures.width));
1500                 if (windowFeatures.height)
1501                     map.set("height", API::Double::create(*windowFeatures.height));
1502                 map.set("menuBarVisible", API::Boolean::create(windowFeatures.menuBarVisible));
1503                 map.set("statusBarVisible", API::Boolean::create(windowFeatures.statusBarVisible));
1504                 map.set("toolBarVisible", API::Boolean::create(windowFeatures.toolBarVisible));
1505                 map.set("locationBarVisible", API::Boolean::create(windowFeatures.locationBarVisible));
1506                 map.set("scrollbarsVisible", API::Boolean::create(windowFeatures.scrollbarsVisible));
1507                 map.set("resizable", API::Boolean::create(windowFeatures.resizable));
1508                 map.set("fullscreen", API::Boolean::create(windowFeatures.fullscreen));
1509                 map.set("dialog", API::Boolean::create(windowFeatures.dialog));
1510                 Ref<API::Dictionary> featuresMap = API::Dictionary::create(WTFMove(map));
1511
1512                 if (m_client.createNewPage_deprecatedForUseWithV1) {
1513                     Ref<API::URLRequest> request = API::URLRequest::create(resourceRequest);
1514                     return completionHandler(adoptRef(toImpl(m_client.createNewPage_deprecatedForUseWithV1(toAPI(&page), toAPI(request.ptr()), toAPI(featuresMap.ptr()), toAPI(navigationActionData.modifiers), toAPI(navigationActionData.mouseButton), m_client.base.clientInfo))));
1515                 }
1516     
1517                 ASSERT(m_client.createNewPage_deprecatedForUseWithV0);
1518                 return completionHandler(adoptRef(toImpl(m_client.createNewPage_deprecatedForUseWithV0(toAPI(&page), toAPI(featuresMap.ptr()), toAPI(navigationActionData.modifiers), toAPI(navigationActionData.mouseButton), m_client.base.clientInfo))));
1519             }
1520
1521             completionHandler(nullptr);
1522         }
1523
1524         void showPage(WebPageProxy* page) final
1525         {
1526             if (!m_client.showPage)
1527                 return;
1528
1529             m_client.showPage(toAPI(page), m_client.base.clientInfo);
1530         }
1531
1532         void fullscreenMayReturnToInline(WebPageProxy* page) final
1533         {
1534             if (!m_client.fullscreenMayReturnToInline)
1535                 return;
1536
1537             m_client.fullscreenMayReturnToInline(toAPI(page), m_client.base.clientInfo);
1538         }
1539         
1540         void hasVideoInPictureInPictureDidChange(WebPageProxy* page, bool hasVideoInPictureInPicture) final
1541         {
1542             if (!m_client.hasVideoInPictureInPictureDidChange)
1543                 return;
1544             
1545             m_client.hasVideoInPictureInPictureDidChange(toAPI(page), hasVideoInPictureInPicture, m_client.base.clientInfo);
1546         }
1547
1548         void didExceedBackgroundResourceLimitWhileInForeground(WebPageProxy& page, WKResourceLimit limit) final
1549         {
1550             if (!m_client.didExceedBackgroundResourceLimitWhileInForeground)
1551                 return;
1552
1553             m_client.didExceedBackgroundResourceLimitWhileInForeground(toAPI(&page), limit, m_client.base.clientInfo);
1554         }
1555
1556         void close(WebPageProxy* page) final
1557         {
1558             if (!m_client.close)
1559                 return;
1560
1561             m_client.close(toAPI(page), m_client.base.clientInfo);
1562         }
1563
1564         bool takeFocus(WebPageProxy* page, WKFocusDirection direction) final
1565         {
1566             if (!m_client.takeFocus)
1567                 return false;
1568
1569             m_client.takeFocus(toAPI(page), direction, m_client.base.clientInfo);
1570             return true;
1571         }
1572
1573         void focus(WebPageProxy* page) final
1574         {
1575             if (!m_client.focus)
1576                 return;
1577
1578             m_client.focus(toAPI(page), m_client.base.clientInfo);
1579         }
1580
1581         void unfocus(WebPageProxy* page) final
1582         {
1583             if (!m_client.unfocus)
1584                 return;
1585
1586             m_client.unfocus(toAPI(page), m_client.base.clientInfo);
1587         }
1588
1589         void runJavaScriptAlert(WebPageProxy* page, const String& message, WebFrameProxy* frame, const SecurityOriginData& securityOriginData, Function<void()>&& completionHandler) final
1590         {
1591             if (m_client.runJavaScriptAlert) {
1592                 RefPtr<RunJavaScriptAlertResultListener> listener = RunJavaScriptAlertResultListener::create(WTFMove(completionHandler));
1593                 RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::create(securityOriginData.protocol, securityOriginData.host, securityOriginData.port);
1594                 m_client.runJavaScriptAlert(toAPI(page), toAPI(message.impl()), toAPI(frame), toAPI(securityOrigin.get()), toAPI(listener.get()), m_client.base.clientInfo);
1595                 return;
1596             }
1597
1598             if (m_client.runJavaScriptAlert_deprecatedForUseWithV5) {
1599                 RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::create(securityOriginData.protocol, securityOriginData.host, securityOriginData.port);
1600                 m_client.runJavaScriptAlert_deprecatedForUseWithV5(toAPI(page), toAPI(message.impl()), toAPI(frame), toAPI(securityOrigin.get()), m_client.base.clientInfo);
1601                 completionHandler();
1602                 return;
1603             }
1604             
1605             if (m_client.runJavaScriptAlert_deprecatedForUseWithV0) {
1606                 m_client.runJavaScriptAlert_deprecatedForUseWithV0(toAPI(page), toAPI(message.impl()), toAPI(frame), m_client.base.clientInfo);
1607                 completionHandler();
1608                 return;
1609             }
1610
1611
1612             completionHandler();
1613         }
1614
1615         void runJavaScriptConfirm(WebPageProxy* page, const String& message, WebFrameProxy* frame, const SecurityOriginData& securityOriginData, Function<void(bool)>&& completionHandler) final
1616         {
1617             if (m_client.runJavaScriptConfirm) {
1618                 RefPtr<RunJavaScriptConfirmResultListener> listener = RunJavaScriptConfirmResultListener::create(WTFMove(completionHandler));
1619                 RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::create(securityOriginData.protocol, securityOriginData.host, securityOriginData.port);
1620                 m_client.runJavaScriptConfirm(toAPI(page), toAPI(message.impl()), toAPI(frame), toAPI(securityOrigin.get()), toAPI(listener.get()), m_client.base.clientInfo);
1621                 return;
1622             }
1623
1624             if (m_client.runJavaScriptConfirm_deprecatedForUseWithV5) {
1625                 RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::create(securityOriginData.protocol, securityOriginData.host, securityOriginData.port);
1626                 bool result = m_client.runJavaScriptConfirm_deprecatedForUseWithV5(toAPI(page), toAPI(message.impl()), toAPI(frame), toAPI(securityOrigin.get()), m_client.base.clientInfo);
1627                 
1628                 completionHandler(result);
1629                 return;
1630             }
1631             
1632             if (m_client.runJavaScriptConfirm_deprecatedForUseWithV0) {
1633                 bool result = m_client.runJavaScriptConfirm_deprecatedForUseWithV0(toAPI(page), toAPI(message.impl()), toAPI(frame), m_client.base.clientInfo);
1634
1635                 completionHandler(result);
1636                 return;
1637             }
1638             
1639             completionHandler(false);
1640         }
1641
1642         void runJavaScriptPrompt(WebPageProxy* page, const String& message, const String& defaultValue, WebFrameProxy* frame, const SecurityOriginData& securityOriginData, Function<void(const String&)>&& completionHandler) final
1643         {
1644             if (m_client.runJavaScriptPrompt) {
1645                 RefPtr<RunJavaScriptPromptResultListener> listener = RunJavaScriptPromptResultListener::create(WTFMove(completionHandler));
1646                 RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::create(securityOriginData.protocol, securityOriginData.host, securityOriginData.port);
1647                 m_client.runJavaScriptPrompt(toAPI(page), toAPI(message.impl()), toAPI(defaultValue.impl()), toAPI(frame), toAPI(securityOrigin.get()), toAPI(listener.get()), m_client.base.clientInfo);
1648                 return;
1649             }
1650
1651             if (m_client.runJavaScriptPrompt_deprecatedForUseWithV5) {
1652                 RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::create(securityOriginData.protocol, securityOriginData.host, securityOriginData.port);
1653                 RefPtr<API::String> string = adoptRef(toImpl(m_client.runJavaScriptPrompt_deprecatedForUseWithV5(toAPI(page), toAPI(message.impl()), toAPI(defaultValue.impl()), toAPI(frame), toAPI(securityOrigin.get()), m_client.base.clientInfo)));
1654                 
1655                 if (string)
1656                     completionHandler(string->string());
1657                 else
1658                     completionHandler(String());
1659                 return;
1660             }
1661             
1662             if (m_client.runJavaScriptPrompt_deprecatedForUseWithV0) {
1663                 RefPtr<API::String> string = adoptRef(toImpl(m_client.runJavaScriptPrompt_deprecatedForUseWithV0(toAPI(page), toAPI(message.impl()), toAPI(defaultValue.impl()), toAPI(frame), m_client.base.clientInfo)));
1664                 
1665                 if (string)
1666                     completionHandler(string->string());
1667                 else
1668                     completionHandler(String());
1669                 return;
1670             }
1671
1672             completionHandler(String());
1673         }
1674
1675         void setStatusText(WebPageProxy* page, const String& text) final
1676         {
1677             if (!m_client.setStatusText)
1678                 return;
1679
1680             m_client.setStatusText(toAPI(page), toAPI(text.impl()), m_client.base.clientInfo);
1681         }
1682
1683         void mouseDidMoveOverElement(WebPageProxy& page, const WebHitTestResultData& data, OptionSet<WebKit::WebEvent::Modifier> modifiers, API::Object* userData) final
1684         {
1685             if (!m_client.mouseDidMoveOverElement && !m_client.mouseDidMoveOverElement_deprecatedForUseWithV0)
1686                 return;
1687
1688             if (m_client.base.version > 0 && !m_client.mouseDidMoveOverElement)
1689                 return;
1690
1691             if (!m_client.base.version) {
1692                 m_client.mouseDidMoveOverElement_deprecatedForUseWithV0(toAPI(&page), toAPI(modifiers), toAPI(userData), m_client.base.clientInfo);
1693                 return;
1694             }
1695
1696             auto apiHitTestResult = API::HitTestResult::create(data);
1697             m_client.mouseDidMoveOverElement(toAPI(&page), toAPI(apiHitTestResult.ptr()), toAPI(modifiers), toAPI(userData), m_client.base.clientInfo);
1698         }
1699
1700 #if ENABLE(NETSCAPE_PLUGIN_API)
1701         void unavailablePluginButtonClicked(WebPageProxy& page, WKPluginUnavailabilityReason pluginUnavailabilityReason, API::Dictionary& pluginInformation) final
1702         {
1703             if (pluginUnavailabilityReason == kWKPluginUnavailabilityReasonPluginMissing) {
1704                 if (m_client.missingPluginButtonClicked_deprecatedForUseWithV0)
1705                     m_client.missingPluginButtonClicked_deprecatedForUseWithV0(
1706                         toAPI(&page),
1707                         toAPI(pluginInformation.get<API::String>(pluginInformationMIMETypeKey())),
1708                         toAPI(pluginInformation.get<API::String>(pluginInformationPluginURLKey())),
1709                         toAPI(pluginInformation.get<API::String>(pluginInformationPluginspageAttributeURLKey())),
1710                         m_client.base.clientInfo);
1711             }
1712
1713             if (m_client.unavailablePluginButtonClicked_deprecatedForUseWithV1)
1714                 m_client.unavailablePluginButtonClicked_deprecatedForUseWithV1(
1715                     toAPI(&page),
1716                     pluginUnavailabilityReason,
1717                     toAPI(pluginInformation.get<API::String>(pluginInformationMIMETypeKey())),
1718                     toAPI(pluginInformation.get<API::String>(pluginInformationPluginURLKey())),
1719                     toAPI(pluginInformation.get<API::String>(pluginInformationPluginspageAttributeURLKey())),
1720                     m_client.base.clientInfo);
1721
1722             if (m_client.unavailablePluginButtonClicked)
1723                 m_client.unavailablePluginButtonClicked(
1724                     toAPI(&page),
1725                     pluginUnavailabilityReason,
1726                     toAPI(&pluginInformation),
1727                     m_client.base.clientInfo);
1728         }
1729 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1730
1731         void didNotHandleKeyEvent(WebPageProxy* page, const NativeWebKeyboardEvent& event) final
1732         {
1733             if (!m_client.didNotHandleKeyEvent)
1734                 return;
1735             m_client.didNotHandleKeyEvent(toAPI(page), event.nativeEvent(), m_client.base.clientInfo);
1736         }
1737
1738         void didNotHandleWheelEvent(WebPageProxy* page, const NativeWebWheelEvent& event) final
1739         {
1740             if (!m_client.didNotHandleWheelEvent)
1741                 return;
1742             m_client.didNotHandleWheelEvent(toAPI(page), event.nativeEvent(), m_client.base.clientInfo);
1743         }
1744
1745         void toolbarsAreVisible(WebPageProxy& page, Function<void(bool)>&& completionHandler) final
1746         {
1747             if (!m_client.toolbarsAreVisible)
1748                 return completionHandler(true);
1749             completionHandler(m_client.toolbarsAreVisible(toAPI(&page), m_client.base.clientInfo));
1750         }
1751
1752         void setToolbarsAreVisible(WebPageProxy& page, bool visible) final
1753         {
1754             if (!m_client.setToolbarsAreVisible)
1755                 return;
1756             m_client.setToolbarsAreVisible(toAPI(&page), visible, m_client.base.clientInfo);
1757         }
1758
1759         void menuBarIsVisible(WebPageProxy& page, Function<void(bool)>&& completionHandler) final
1760         {
1761             if (!m_client.menuBarIsVisible)
1762                 return completionHandler(true);
1763             completionHandler(m_client.menuBarIsVisible(toAPI(&page), m_client.base.clientInfo));
1764         }
1765
1766         void setMenuBarIsVisible(WebPageProxy& page, bool visible) final
1767         {
1768             if (!m_client.setMenuBarIsVisible)
1769                 return;
1770             m_client.setMenuBarIsVisible(toAPI(&page), visible, m_client.base.clientInfo);
1771         }
1772
1773         void statusBarIsVisible(WebPageProxy& page, Function<void(bool)>&& completionHandler) final
1774         {
1775             if (!m_client.statusBarIsVisible)
1776                 return completionHandler(true);
1777             completionHandler(m_client.statusBarIsVisible(toAPI(&page), m_client.base.clientInfo));
1778         }
1779
1780         void setStatusBarIsVisible(WebPageProxy& page, bool visible) final
1781         {
1782             if (!m_client.setStatusBarIsVisible)
1783                 return;
1784             m_client.setStatusBarIsVisible(toAPI(&page), visible, m_client.base.clientInfo);
1785         }
1786
1787         void setIsResizable(WebPageProxy& page, bool resizable) final
1788         {
1789             if (!m_client.setIsResizable)
1790                 return;
1791             m_client.setIsResizable(toAPI(&page), resizable, m_client.base.clientInfo);
1792         }
1793
1794         void setWindowFrame(WebPageProxy& page, const FloatRect& frame) final
1795         {
1796             if (!m_client.setWindowFrame)
1797                 return;
1798
1799             m_client.setWindowFrame(toAPI(&page), toAPI(frame), m_client.base.clientInfo);
1800         }
1801
1802         void windowFrame(WebPageProxy& page, Function<void(WebCore::FloatRect)>&& completionHandler) final
1803         {
1804             if (!m_client.getWindowFrame)
1805                 return completionHandler({ });
1806
1807             completionHandler(toFloatRect(m_client.getWindowFrame(toAPI(&page), m_client.base.clientInfo)));
1808         }
1809
1810         bool canRunBeforeUnloadConfirmPanel() const final
1811         {
1812             return m_client.runBeforeUnloadConfirmPanel_deprecatedForUseWithV6 || m_client.runBeforeUnloadConfirmPanel;
1813         }
1814
1815         void runBeforeUnloadConfirmPanel(WebKit::WebPageProxy* page, const WTF::String& message, WebKit::WebFrameProxy* frame, const SecurityOriginData&, Function<void(bool)>&& completionHandler) final
1816         {
1817             if (m_client.runBeforeUnloadConfirmPanel) {
1818                 RefPtr<RunBeforeUnloadConfirmPanelResultListener> listener = RunBeforeUnloadConfirmPanelResultListener::create(WTFMove(completionHandler));
1819                 m_client.runBeforeUnloadConfirmPanel(toAPI(page), toAPI(message.impl()), toAPI(frame), toAPI(listener.get()), m_client.base.clientInfo);
1820                 return;
1821             }
1822
1823             if (m_client.runBeforeUnloadConfirmPanel_deprecatedForUseWithV6) {
1824                 bool result = m_client.runBeforeUnloadConfirmPanel_deprecatedForUseWithV6(toAPI(page), toAPI(message.impl()), toAPI(frame), m_client.base.clientInfo);
1825                 completionHandler(result);
1826                 return;
1827             }
1828
1829             completionHandler(true);
1830         }
1831
1832         void pageDidScroll(WebPageProxy* page) final
1833         {
1834             if (!m_client.pageDidScroll)
1835                 return;
1836
1837             m_client.pageDidScroll(toAPI(page), m_client.base.clientInfo);
1838         }
1839
1840         void exceededDatabaseQuota(WebPageProxy* page, WebFrameProxy* frame, API::SecurityOrigin* origin, const String& databaseName, const String& databaseDisplayName, unsigned long long currentQuota, unsigned long long currentOriginUsage, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage, Function<void(unsigned long long)>&& completionHandler) final
1841         {
1842             if (!m_client.exceededDatabaseQuota) {
1843                 completionHandler(currentQuota);
1844                 return;
1845             }
1846
1847             completionHandler(m_client.exceededDatabaseQuota(toAPI(page), toAPI(frame), toAPI(origin), toAPI(databaseName.impl()), toAPI(databaseDisplayName.impl()), currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage, m_client.base.clientInfo));
1848         }
1849
1850         bool runOpenPanel(WebPageProxy* page, WebFrameProxy* frame, const WebCore::SecurityOriginData&, API::OpenPanelParameters* parameters, WebOpenPanelResultListenerProxy* listener) final
1851         {
1852             if (!m_client.runOpenPanel)
1853                 return false;
1854
1855             m_client.runOpenPanel(toAPI(page), toAPI(frame), toAPI(parameters), toAPI(listener), m_client.base.clientInfo);
1856             return true;
1857         }
1858
1859         void decidePolicyForGeolocationPermissionRequest(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& origin, Function<void(bool)>& completionHandler) final
1860         {
1861             if (!m_client.decidePolicyForGeolocationPermissionRequest)
1862                 return;
1863
1864             m_client.decidePolicyForGeolocationPermissionRequest(toAPI(&page), toAPI(&frame), toAPI(&origin), toAPI(GeolocationPermissionRequest::create(std::exchange(completionHandler, nullptr)).ptr()), m_client.base.clientInfo);
1865         }
1866
1867         void decidePolicyForUserMediaPermissionRequest(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaDocumentOrigin, API::SecurityOrigin& topLevelDocumentOrigin, UserMediaPermissionRequestProxy& permissionRequest) final
1868         {
1869             if (!m_client.decidePolicyForUserMediaPermissionRequest) {
1870                 permissionRequest.deny();
1871                 return;
1872             }
1873
1874             m_client.decidePolicyForUserMediaPermissionRequest(toAPI(&page), toAPI(&frame), toAPI(&userMediaDocumentOrigin), toAPI(&topLevelDocumentOrigin), toAPI(&permissionRequest), m_client.base.clientInfo);
1875         }
1876
1877         void checkUserMediaPermissionForOrigin(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaDocumentOrigin, API::SecurityOrigin& topLevelDocumentOrigin, UserMediaPermissionCheckProxy& request) final
1878         {
1879             if (!m_client.checkUserMediaPermissionForOrigin) {
1880                 request.deny();
1881                 return;
1882             }
1883
1884             m_client.checkUserMediaPermissionForOrigin(toAPI(&page), toAPI(&frame), toAPI(&userMediaDocumentOrigin), toAPI(&topLevelDocumentOrigin), toAPI(&request), m_client.base.clientInfo);
1885         }
1886         
1887         void decidePolicyForNotificationPermissionRequest(WebPageProxy& page, API::SecurityOrigin& origin, Function<void(bool)>&& completionHandler) final
1888         {
1889             if (!m_client.decidePolicyForNotificationPermissionRequest)
1890                 return completionHandler(false);
1891
1892             m_client.decidePolicyForNotificationPermissionRequest(toAPI(&page), toAPI(&origin), toAPI(NotificationPermissionRequest::create(WTFMove(completionHandler)).ptr()), m_client.base.clientInfo);
1893         }
1894
1895         void requestStorageAccessConfirm(WebPageProxy& page, WebFrameProxy* frame, const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler<void(bool)>&& completionHandler) final
1896         {
1897             if (!m_client.requestStorageAccessConfirm) {
1898                 completionHandler(true);
1899                 return;
1900             }
1901
1902             auto listener = RequestStorageAccessConfirmResultListener::create(WTFMove(completionHandler));
1903             m_client.requestStorageAccessConfirm(toAPI(&page), toAPI(frame), toAPI(requestingDomain.impl()), toAPI(currentDomain.impl()), toAPI(listener.ptr()), m_client.base.clientInfo);
1904         }
1905
1906         // Printing.
1907         float headerHeight(WebPageProxy& page, WebFrameProxy& frame) final
1908         {
1909             if (!m_client.headerHeight)
1910                 return 0;
1911
1912             return m_client.headerHeight(toAPI(&page), toAPI(&frame), m_client.base.clientInfo);
1913         }
1914
1915         float footerHeight(WebPageProxy& page, WebFrameProxy& frame) final
1916         {
1917             if (!m_client.footerHeight)
1918                 return 0;
1919
1920             return m_client.footerHeight(toAPI(&page), toAPI(&frame), m_client.base.clientInfo);
1921         }
1922
1923         void drawHeader(WebPageProxy& page, WebFrameProxy& frame, WebCore::FloatRect&& rect) final
1924         {
1925             if (!m_client.drawHeader)
1926                 return;
1927
1928             m_client.drawHeader(toAPI(&page), toAPI(&frame), toAPI(rect), m_client.base.clientInfo);
1929         }
1930
1931         void drawFooter(WebPageProxy& page, WebFrameProxy& frame, WebCore::FloatRect&& rect) final
1932         {
1933             if (!m_client.drawFooter)
1934                 return;
1935
1936             m_client.drawFooter(toAPI(&page), toAPI(&frame), toAPI(rect), m_client.base.clientInfo);
1937         }
1938
1939         void printFrame(WebPageProxy& page, WebFrameProxy& frame) final
1940         {
1941             if (!m_client.printFrame)
1942                 return;
1943
1944             m_client.printFrame(toAPI(&page), toAPI(&frame), m_client.base.clientInfo);
1945         }
1946
1947         bool canRunModal() const final
1948         {
1949             return m_client.runModal;
1950         }
1951
1952         void runModal(WebPageProxy& page) final
1953         {
1954             if (!m_client.runModal)
1955                 return;
1956
1957             m_client.runModal(toAPI(&page), m_client.base.clientInfo);
1958         }
1959
1960         void saveDataToFileInDownloadsFolder(WebPageProxy* page, const String& suggestedFilename, const String& mimeType, const URL& originatingURL, API::Data& data) final
1961         {
1962             if (!m_client.saveDataToFileInDownloadsFolder)
1963                 return;
1964
1965             m_client.saveDataToFileInDownloadsFolder(toAPI(page), toAPI(suggestedFilename.impl()), toAPI(mimeType.impl()), toURLRef(originatingURL.string().impl()), toAPI(&data), m_client.base.clientInfo);
1966         }
1967
1968         void pinnedStateDidChange(WebPageProxy& page) final
1969         {
1970             if (!m_client.pinnedStateDidChange)
1971                 return;
1972
1973             m_client.pinnedStateDidChange(toAPI(&page), m_client.base.clientInfo);
1974         }
1975
1976         void isPlayingMediaDidChange(WebPageProxy& page) final
1977         {
1978             if (!m_client.isPlayingAudioDidChange)
1979                 return;
1980
1981             m_client.isPlayingAudioDidChange(toAPI(&page), m_client.base.clientInfo);
1982         }
1983
1984         void didClickAutoFillButton(WebPageProxy& page, API::Object* userInfo) final
1985         {
1986             if (!m_client.didClickAutoFillButton)
1987                 return;
1988
1989             m_client.didClickAutoFillButton(toAPI(&page), toAPI(userInfo), m_client.base.clientInfo);
1990         }
1991
1992         void didResignInputElementStrongPasswordAppearance(WebPageProxy& page, API::Object* userInfo) final
1993         {
1994             if (!m_client.didResignInputElementStrongPasswordAppearance)
1995                 return;
1996
1997             m_client.didResignInputElementStrongPasswordAppearance(toAPI(&page), toAPI(userInfo), m_client.base.clientInfo);
1998         }
1999
2000 #if ENABLE(MEDIA_SESSION)
2001         void mediaSessionMetadataDidChange(WebPageProxy& page, WebMediaSessionMetadata* metadata) final
2002         {
2003             if (!m_client.mediaSessionMetadataDidChange)
2004                 return;
2005
2006             m_client.mediaSessionMetadataDidChange(toAPI(&page), toAPI(metadata), m_client.base.clientInfo);
2007         }
2008 #endif
2009 #if ENABLE(POINTER_LOCK)
2010         void requestPointerLock(WebPageProxy* page) final
2011         {
2012             if (!m_client.requestPointerLock)
2013                 return;
2014             
2015             m_client.requestPointerLock(toAPI(page), m_client.base.clientInfo);
2016         }
2017
2018         void didLosePointerLock(WebPageProxy* page) final
2019         {
2020             if (!m_client.didLosePointerLock)
2021                 return;
2022
2023             m_client.didLosePointerLock(toAPI(page), m_client.base.clientInfo);
2024         }
2025 #endif
2026
2027         static WKAutoplayEventFlags toWKAutoplayEventFlags(OptionSet<WebCore::AutoplayEventFlags> flags)
2028         {
2029             WKAutoplayEventFlags wkFlags = kWKAutoplayEventFlagsNone;
2030             if (flags.contains(WebCore::AutoplayEventFlags::HasAudio))
2031                 wkFlags |= kWKAutoplayEventFlagsHasAudio;
2032             if (flags.contains(WebCore::AutoplayEventFlags::PlaybackWasPrevented))
2033                 wkFlags |= kWKAutoplayEventFlagsPlaybackWasPrevented;
2034             if (flags.contains(WebCore::AutoplayEventFlags::MediaIsMainContent))
2035                 wkFlags |= kWKAutoplayEventFlagsMediaIsMainContent;
2036
2037             return wkFlags;
2038         }
2039
2040         static WKAutoplayEvent toWKAutoplayEvent(WebCore::AutoplayEvent event)
2041         {
2042             switch (event) {
2043             case WebCore::AutoplayEvent::DidAutoplayMediaPastThresholdWithoutUserInterference:
2044                 return kWKAutoplayEventDidAutoplayMediaPastThresholdWithoutUserInterference;
2045             case WebCore::AutoplayEvent::DidPlayMediaWithUserGesture:
2046                 return kWKAutoplayEventDidPlayMediaWithUserGesture;
2047             case WebCore::AutoplayEvent::DidPreventMediaFromPlaying:
2048                 return kWKAutoplayEventDidPreventFromAutoplaying;
2049             case WebCore::AutoplayEvent::UserDidInterfereWithPlayback:
2050                 return kWKAutoplayEventUserDidInterfereWithPlayback;
2051             }
2052
2053             RELEASE_ASSERT_NOT_REACHED();
2054         }
2055
2056         void handleAutoplayEvent(WebPageProxy& page, WebCore::AutoplayEvent event, OptionSet<WebCore::AutoplayEventFlags> flags) final
2057         {
2058             if (!m_client.handleAutoplayEvent)
2059                 return;
2060
2061             m_client.handleAutoplayEvent(toAPI(&page), toWKAutoplayEvent(event), toWKAutoplayEventFlags(flags), m_client.base.clientInfo);
2062         }
2063     };
2064
2065     toImpl(pageRef)->setUIClient(std::make_unique<UIClient>(wkClient));
2066 }
2067
2068 void WKPageSetPageNavigationClient(WKPageRef pageRef, const WKPageNavigationClientBase* wkClient)
2069 {
2070     class NavigationClient : public API::Client<WKPageNavigationClientBase>, public API::NavigationClient {
2071     public:
2072         explicit NavigationClient(const WKPageNavigationClientBase* client)
2073         {
2074             initialize(client);
2075         }
2076
2077     private:
2078         void decidePolicyForNavigationAction(WebPageProxy& page, Ref<API::NavigationAction>&& navigationAction, Ref<WebKit::WebFramePolicyListenerProxy>&& listener, API::Object* userData) final
2079         {
2080             if (!m_client.decidePolicyForNavigationAction) {
2081                 listener->use();
2082                 return;
2083             }
2084             m_client.decidePolicyForNavigationAction(toAPI(&page), toAPI(navigationAction.ptr()), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
2085         }
2086
2087         void decidePolicyForNavigationResponse(WebPageProxy& page, Ref<API::NavigationResponse>&& navigationResponse, Ref<WebKit::WebFramePolicyListenerProxy>&& listener, API::Object* userData) override
2088         {
2089             if (!m_client.decidePolicyForNavigationResponse) {
2090                 listener->use();
2091                 return;
2092             }
2093             m_client.decidePolicyForNavigationResponse(toAPI(&page), toAPI(navigationResponse.ptr()), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
2094         }
2095
2096         void didStartProvisionalNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object* userData) override
2097         {
2098             if (!m_client.didStartProvisionalNavigation)
2099                 return;
2100             m_client.didStartProvisionalNavigation(toAPI(&page), toAPI(navigation), toAPI(userData), m_client.base.clientInfo);
2101         }
2102
2103         void didReceiveServerRedirectForProvisionalNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object* userData) override
2104         {
2105             if (!m_client.didReceiveServerRedirectForProvisionalNavigation)
2106                 return;
2107             m_client.didReceiveServerRedirectForProvisionalNavigation(toAPI(&page), toAPI(navigation), toAPI(userData), m_client.base.clientInfo);
2108         }
2109
2110         void didFailProvisionalNavigationWithError(WebPageProxy& page, WebFrameProxy&, API::Navigation* navigation, const WebCore::ResourceError& error, API::Object* userData) override
2111         {
2112             if (!m_client.didFailProvisionalNavigation)
2113                 return;
2114             m_client.didFailProvisionalNavigation(toAPI(&page), toAPI(navigation), toAPI(error), toAPI(userData), m_client.base.clientInfo);
2115         }
2116
2117         void didCommitNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object* userData) override
2118         {
2119             if (!m_client.didCommitNavigation)
2120                 return;
2121             m_client.didCommitNavigation(toAPI(&page), toAPI(navigation), toAPI(userData), m_client.base.clientInfo);
2122         }
2123
2124         void didFinishNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object* userData) override
2125         {
2126             if (!m_client.didFinishNavigation)
2127                 return;
2128             m_client.didFinishNavigation(toAPI(&page), toAPI(navigation), toAPI(userData), m_client.base.clientInfo);
2129         }
2130
2131         void didFailNavigationWithError(WebPageProxy& page, WebFrameProxy&, API::Navigation* navigation, const WebCore::ResourceError& error, API::Object* userData) override
2132         {
2133             if (!m_client.didFailNavigation)
2134                 return;
2135             m_client.didFailNavigation(toAPI(&page), toAPI(navigation), toAPI(error), toAPI(userData), m_client.base.clientInfo);
2136         }
2137
2138         void didFailProvisionalLoadInSubframeWithError(WebPageProxy& page, WebFrameProxy& subframe, const WebCore::SecurityOriginData& securityOriginData, API::Navigation* navigation, const WebCore::ResourceError& error, API::Object* userData) override
2139         {
2140             if (!m_client.didFailProvisionalLoadInSubframe)
2141                 return;
2142             m_client.didFailProvisionalLoadInSubframe(toAPI(&page), toAPI(navigation), toAPI(API::FrameInfo::create(subframe, securityOriginData.securityOrigin()).ptr()), toAPI(error), toAPI(userData), m_client.base.clientInfo);
2143         }
2144
2145         void didFinishDocumentLoad(WebPageProxy& page, API::Navigation* navigation, API::Object* userData) override
2146         {
2147             if (!m_client.didFinishDocumentLoad)
2148                 return;
2149             m_client.didFinishDocumentLoad(toAPI(&page), toAPI(navigation), toAPI(userData), m_client.base.clientInfo);
2150         }
2151
2152         void didSameDocumentNavigation(WebPageProxy& page, API::Navigation* navigation, WebKit::SameDocumentNavigationType navigationType, API::Object* userData) override
2153         {
2154             if (!m_client.didSameDocumentNavigation)
2155                 return;
2156             m_client.didSameDocumentNavigation(toAPI(&page), toAPI(navigation), toAPI(navigationType), toAPI(userData), m_client.base.clientInfo);
2157         }
2158         
2159         void renderingProgressDidChange(WebPageProxy& page, OptionSet<WebCore::LayoutMilestone> milestones) override
2160         {
2161             if (!m_client.renderingProgressDidChange)
2162                 return;
2163             m_client.renderingProgressDidChange(toAPI(&page), pageRenderingProgressEvents(milestones), nullptr, m_client.base.clientInfo);
2164         }
2165         
2166         void didReceiveAuthenticationChallenge(WebPageProxy& page, AuthenticationChallengeProxy& authenticationChallenge) override
2167         {
2168             if (m_client.canAuthenticateAgainstProtectionSpace && !m_client.canAuthenticateAgainstProtectionSpace(toAPI(&page), toAPI(WebProtectionSpace::create(authenticationChallenge.core().protectionSpace()).ptr()), m_client.base.clientInfo))
2169                 return authenticationChallenge.listener().completeChallenge(WebKit::AuthenticationChallengeDisposition::RejectProtectionSpaceAndContinue);
2170             if (!m_client.didReceiveAuthenticationChallenge)
2171                 return authenticationChallenge.listener().completeChallenge(WebKit::AuthenticationChallengeDisposition::PerformDefaultHandling);
2172             m_client.didReceiveAuthenticationChallenge(toAPI(&page), toAPI(&authenticationChallenge), m_client.base.clientInfo);
2173         }
2174
2175         bool processDidTerminate(WebPageProxy& page, WebKit::ProcessTerminationReason reason) override
2176         {
2177             if (m_client.webProcessDidTerminate) {
2178                 m_client.webProcessDidTerminate(toAPI(&page), toAPI(reason), m_client.base.clientInfo);
2179                 return true;
2180             }
2181
2182             if (m_client.webProcessDidCrash && reason != WebKit::ProcessTerminationReason::RequestedByClient) {
2183                 m_client.webProcessDidCrash(toAPI(&page), m_client.base.clientInfo);
2184                 return true;
2185             }
2186
2187             return false;
2188         }
2189
2190         RefPtr<API::Data> webCryptoMasterKey(WebPageProxy& page) override
2191         {
2192             if (m_client.copyWebCryptoMasterKey)
2193                 return adoptRef(toImpl(m_client.copyWebCryptoMasterKey(toAPI(&page), m_client.base.clientInfo)));
2194
2195             Vector<uint8_t> masterKey;
2196 #if ENABLE(WEB_CRYPTO)
2197             if (!getDefaultWebCryptoMasterKey(masterKey))
2198                 return nullptr;
2199 #endif
2200
2201             return API::Data::create(masterKey.data(), masterKey.size());
2202         }
2203
2204         RefPtr<API::String> signedPublicKeyAndChallengeString(WebPageProxy& page, unsigned keySizeIndex, const RefPtr<API::String>& challengeString, const URL& url) override
2205         {
2206             if (m_client.copySignedPublicKeyAndChallengeString)
2207                 return adoptRef(toImpl(m_client.copySignedPublicKeyAndChallengeString(toAPI(&page), m_client.base.clientInfo)));
2208             return API::String::create(WebCore::signedPublicKeyAndChallengeString(keySizeIndex, challengeString->string(), url));
2209         }
2210
2211         void didBeginNavigationGesture(WebPageProxy& page) override
2212         {
2213             if (!m_client.didBeginNavigationGesture)
2214                 return;
2215             m_client.didBeginNavigationGesture(toAPI(&page), m_client.base.clientInfo);
2216         }
2217
2218         void didEndNavigationGesture(WebPageProxy& page, bool willNavigate, WebKit::WebBackForwardListItem& item) override
2219         {
2220             if (!m_client.didEndNavigationGesture)
2221                 return;
2222             m_client.didEndNavigationGesture(toAPI(&page), willNavigate ? toAPI(&item) : nullptr, m_client.base.clientInfo);
2223         }
2224
2225         void willEndNavigationGesture(WebPageProxy& page, bool willNavigate, WebKit::WebBackForwardListItem& item) override
2226         {
2227             if (!m_client.willEndNavigationGesture)
2228                 return;
2229             m_client.willEndNavigationGesture(toAPI(&page), willNavigate ? toAPI(&item) : nullptr, m_client.base.clientInfo);
2230         }
2231
2232         void didRemoveNavigationGestureSnapshot(WebPageProxy& page) override
2233         {
2234             if (!m_client.didRemoveNavigationGestureSnapshot)
2235                 return;
2236             m_client.didRemoveNavigationGestureSnapshot(toAPI(&page), m_client.base.clientInfo);
2237         }
2238         
2239         void contentRuleListNotification(WebPageProxy& page, URL&& url, Vector<String>&& listIdentifiers, Vector<String>&& notifications) final
2240         {
2241             if (!m_client.contentRuleListNotification)
2242                 return;
2243
2244             Vector<RefPtr<API::Object>> apiListIdentifiers;
2245             for (const auto& identifier : listIdentifiers)
2246                 apiListIdentifiers.append(API::String::create(identifier));
2247
2248             Vector<RefPtr<API::Object>> apiNotifications;
2249             for (const auto& notification : notifications)
2250                 apiNotifications.append(API::String::create(notification));
2251
2252             m_client.contentRuleListNotification(toAPI(&page), toURLRef(url.string().impl()), toAPI(API::Array::create(WTFMove(apiListIdentifiers)).ptr()), toAPI(API::Array::create(WTFMove(apiNotifications)).ptr()), m_client.base.clientInfo);
2253         }
2254 #if ENABLE(NETSCAPE_PLUGIN_API)
2255         void decidePolicyForPluginLoad(WebPageProxy& page, PluginModuleLoadPolicy currentPluginLoadPolicy, API::Dictionary& pluginInformation, CompletionHandler<void(PluginModuleLoadPolicy, const String&)>&& completionHandler) override
2256         {
2257             WKStringRef unavailabilityDescriptionOut = 0;
2258             PluginModuleLoadPolicy loadPolicy = currentPluginLoadPolicy;
2259             
2260             if (m_client.decidePolicyForPluginLoad)
2261                 loadPolicy = toPluginModuleLoadPolicy(m_client.decidePolicyForPluginLoad(toAPI(&page), toWKPluginLoadPolicy(currentPluginLoadPolicy), toAPI(&pluginInformation), &unavailabilityDescriptionOut, m_client.base.clientInfo));
2262             
2263             String unavailabilityDescription;
2264             if (unavailabilityDescriptionOut) {
2265                 RefPtr<API::String> webUnavailabilityDescription = adoptRef(toImpl(unavailabilityDescriptionOut));
2266                 unavailabilityDescription = webUnavailabilityDescription->string();
2267             }
2268             
2269             completionHandler(loadPolicy, unavailabilityDescription);
2270         }
2271 #endif
2272     };
2273
2274     WebPageProxy* webPageProxy = toImpl(pageRef);
2275
2276     webPageProxy->setNavigationClient(makeUniqueRef<NavigationClient>(wkClient));
2277 }
2278
2279 void WKPageRunJavaScriptInMainFrame(WKPageRef pageRef, WKStringRef scriptRef, void* context, WKPageRunJavaScriptFunction callback)
2280 {
2281     toImpl(pageRef)->runJavaScriptInMainFrame(toImpl(scriptRef)->string(), true, [context, callback](API::SerializedScriptValue* returnValue, bool, const WebCore::ExceptionDetails&, CallbackBase::Error error) {
2282         callback(toAPI(returnValue), (error != CallbackBase::Error::None) ? toAPI(API::Error::create().ptr()) : 0, context);
2283     });
2284 }
2285
2286 #ifdef __BLOCKS__
2287 static void callRunJavaScriptBlockAndRelease(WKSerializedScriptValueRef resultValue, WKErrorRef error, void* context)
2288 {
2289     WKPageRunJavaScriptBlock block = (WKPageRunJavaScriptBlock)context;
2290     block(resultValue, error);
2291     Block_release(block);
2292 }
2293
2294 void WKPageRunJavaScriptInMainFrame_b(WKPageRef pageRef, WKStringRef scriptRef, WKPageRunJavaScriptBlock block)
2295 {
2296     WKPageRunJavaScriptInMainFrame(pageRef, scriptRef, Block_copy(block), callRunJavaScriptBlockAndRelease);
2297 }
2298 #endif
2299
2300 static WTF::Function<void (const String&, WebKit::CallbackBase::Error)> toGenericCallbackFunction(void* context, void (*callback)(WKStringRef, WKErrorRef, void*))
2301 {
2302     return [context, callback](const String& returnValue, WebKit::CallbackBase::Error error) {
2303         callback(toAPI(API::String::create(returnValue).ptr()), error != WebKit::CallbackBase::Error::None ? toAPI(API::Error::create().ptr()) : 0, context);
2304     };
2305 }
2306
2307 void WKPageRenderTreeExternalRepresentation(WKPageRef pageRef, void* context, WKPageRenderTreeExternalRepresentationFunction callback)
2308 {
2309     toImpl(pageRef)->getRenderTreeExternalRepresentation(toGenericCallbackFunction(context, callback));
2310 }
2311
2312 void WKPageGetSourceForFrame(WKPageRef pageRef, WKFrameRef frameRef, void* context, WKPageGetSourceForFrameFunction callback)
2313 {
2314     toImpl(pageRef)->getSourceForFrame(toImpl(frameRef), toGenericCallbackFunction(context, callback));
2315 }
2316
2317 void WKPageGetContentsAsString(WKPageRef pageRef, void* context, WKPageGetContentsAsStringFunction callback)
2318 {
2319     toImpl(pageRef)->getContentsAsString(toGenericCallbackFunction(context, callback));
2320 }
2321
2322 void WKPageGetBytecodeProfile(WKPageRef pageRef, void* context, WKPageGetBytecodeProfileFunction callback)
2323 {
2324     toImpl(pageRef)->getBytecodeProfile(toGenericCallbackFunction(context, callback));
2325 }
2326
2327 void WKPageGetSamplingProfilerOutput(WKPageRef pageRef, void* context, WKPageGetSamplingProfilerOutputFunction callback)
2328 {
2329     toImpl(pageRef)->getSamplingProfilerOutput(toGenericCallbackFunction(context, callback));
2330 }
2331
2332 void WKPageGetSelectionAsWebArchiveData(WKPageRef pageRef, void* context, WKPageGetSelectionAsWebArchiveDataFunction callback)
2333 {
2334     toImpl(pageRef)->getSelectionAsWebArchiveData(toGenericCallbackFunction(context, callback));
2335 }
2336
2337 void WKPageGetContentsAsMHTMLData(WKPageRef pageRef, void* context, WKPageGetContentsAsMHTMLDataFunction callback)
2338 {
2339 #if ENABLE(MHTML)
2340     toImpl(pageRef)->getContentsAsMHTMLData(toGenericCallbackFunction(context, callback));
2341 #else
2342     UNUSED_PARAM(pageRef);
2343     UNUSED_PARAM(context);
2344     UNUSED_PARAM(callback);
2345 #endif
2346 }
2347
2348 void WKPageForceRepaint(WKPageRef pageRef, void* context, WKPageForceRepaintFunction callback)
2349 {
2350     toImpl(pageRef)->forceRepaint(VoidCallback::create([context, callback](WebKit::CallbackBase::Error error) {
2351         callback(error == WebKit::CallbackBase::Error::None ? nullptr : toAPI(API::Error::create().ptr()), context);
2352     }));
2353 }
2354
2355 WK_EXPORT WKURLRef WKPageCopyPendingAPIRequestURL(WKPageRef pageRef)
2356 {
2357     const String& pendingAPIRequestURL = toImpl(pageRef)->pageLoadState().pendingAPIRequestURL();
2358
2359     if (pendingAPIRequestURL.isNull())
2360         return nullptr;
2361
2362     return toCopiedURLAPI(pendingAPIRequestURL);
2363 }
2364
2365 WKURLRef WKPageCopyActiveURL(WKPageRef pageRef)
2366 {
2367     return toCopiedURLAPI(toImpl(pageRef)->pageLoadState().activeURL());
2368 }
2369
2370 WKURLRef WKPageCopyProvisionalURL(WKPageRef pageRef)
2371 {
2372     return toCopiedURLAPI(toImpl(pageRef)->pageLoadState().provisionalURL());
2373 }
2374
2375 WKURLRef WKPageCopyCommittedURL(WKPageRef pageRef)
2376 {
2377     return toCopiedURLAPI(toImpl(pageRef)->pageLoadState().url());
2378 }
2379
2380 WKStringRef WKPageCopyStandardUserAgentWithApplicationName(WKStringRef applicationName)
2381 {
2382     return toCopiedAPI(WebPageProxy::standardUserAgent(toImpl(applicationName)->string()));
2383 }
2384
2385 void WKPageValidateCommand(WKPageRef pageRef, WKStringRef command, void* context, WKPageValidateCommandCallback callback)
2386 {
2387     toImpl(pageRef)->validateCommand(toImpl(command)->string(), [context, callback](const String& commandName, bool isEnabled, int32_t state, WebKit::CallbackBase::Error error) {
2388         callback(toAPI(API::String::create(commandName).ptr()), isEnabled, state, error != WebKit::CallbackBase::Error::None ? toAPI(API::Error::create().ptr()) : 0, context);
2389     });
2390 }
2391
2392 void WKPageExecuteCommand(WKPageRef pageRef, WKStringRef command)
2393 {
2394     toImpl(pageRef)->executeEditCommand(toImpl(command)->string());
2395 }
2396
2397 #if PLATFORM(COCOA)
2398 static PrintInfo printInfoFromWKPrintInfo(const WKPrintInfo& printInfo)
2399 {
2400     PrintInfo result;
2401     result.pageSetupScaleFactor = printInfo.pageSetupScaleFactor;
2402     result.availablePaperWidth = printInfo.availablePaperWidth;
2403     result.availablePaperHeight = printInfo.availablePaperHeight;
2404     return result;
2405 }
2406
2407 void WKPageComputePagesForPrinting(WKPageRef page, WKFrameRef frame, WKPrintInfo printInfo, WKPageComputePagesForPrintingFunction callback, void* context)
2408 {
2409     toImpl(page)->computePagesForPrinting(toImpl(frame), printInfoFromWKPrintInfo(printInfo), ComputedPagesCallback::create([context, callback](const Vector<WebCore::IntRect>& rects, double scaleFactor, WebKit::CallbackBase::Error error) {
2410         Vector<WKRect> wkRects(rects.size());
2411         for (size_t i = 0; i < rects.size(); ++i)
2412             wkRects[i] = toAPI(rects[i]);
2413         callback(wkRects.data(), wkRects.size(), scaleFactor, error != WebKit::CallbackBase::Error::None ? toAPI(API::Error::create().ptr()) : 0, context);
2414     }));
2415 }
2416
2417 void WKPageBeginPrinting(WKPageRef page, WKFrameRef frame, WKPrintInfo printInfo)
2418 {
2419     toImpl(page)->beginPrinting(toImpl(frame), printInfoFromWKPrintInfo(printInfo));
2420 }
2421
2422 void WKPageDrawPagesToPDF(WKPageRef page, WKFrameRef frame, WKPrintInfo printInfo, uint32_t first, uint32_t count, WKPageDrawToPDFFunction callback, void* context)
2423 {
2424     toImpl(page)->drawPagesToPDF(toImpl(frame), printInfoFromWKPrintInfo(printInfo), first, count, DataCallback::create(toGenericCallbackFunction(context, callback)));
2425 }
2426
2427 void WKPageEndPrinting(WKPageRef page)
2428 {
2429     toImpl(page)->endPrinting();
2430 }
2431 #endif
2432
2433 bool WKPageGetIsControlledByAutomation(WKPageRef page)
2434 {
2435     return toImpl(page)->isControlledByAutomation();
2436 }
2437
2438 void WKPageSetControlledByAutomation(WKPageRef page, bool controlled)
2439 {
2440     toImpl(page)->setControlledByAutomation(controlled);
2441 }
2442
2443 bool WKPageGetAllowsRemoteInspection(WKPageRef page)
2444 {
2445 #if ENABLE(REMOTE_INSPECTOR)
2446     return toImpl(page)->allowsRemoteInspection();
2447 #else
2448     UNUSED_PARAM(page);
2449     return false;
2450 #endif    
2451 }
2452
2453 void WKPageSetAllowsRemoteInspection(WKPageRef page, bool allow)
2454 {
2455 #if ENABLE(REMOTE_INSPECTOR)
2456     toImpl(page)->setAllowsRemoteInspection(allow);
2457 #else
2458     UNUSED_PARAM(page);
2459     UNUSED_PARAM(allow);
2460 #endif
2461 }
2462
2463 void WKPageSetMediaVolume(WKPageRef page, float volume)
2464 {
2465     toImpl(page)->setMediaVolume(volume);    
2466 }
2467
2468 void WKPageSetMuted(WKPageRef page, WKMediaMutedState muted)
2469 {
2470     toImpl(page)->setMuted(muted);
2471 }
2472
2473 void WKPageSetMediaCaptureEnabled(WKPageRef page, bool enabled)
2474 {
2475     toImpl(page)->setMediaCaptureEnabled(enabled);
2476 }
2477
2478 bool WKPageGetMediaCaptureEnabled(WKPageRef page)
2479 {
2480     return toImpl(page)->mediaCaptureEnabled();
2481 }
2482
2483 void WKPageDidAllowPointerLock(WKPageRef page)
2484 {
2485 #if ENABLE(POINTER_LOCK)
2486     toImpl(page)->didAllowPointerLock();
2487 #else
2488     UNUSED_PARAM(page);
2489 #endif
2490 }
2491
2492 void WKPageClearUserMediaState(WKPageRef page)
2493 {
2494 #if ENABLE(MEDIA_STREAM)
2495     toImpl(page)->clearUserMediaState();
2496 #else
2497     UNUSED_PARAM(page);
2498 #endif
2499 }
2500
2501 void WKPageDidDenyPointerLock(WKPageRef page)
2502 {
2503 #if ENABLE(POINTER_LOCK)
2504     toImpl(page)->didDenyPointerLock();
2505 #else
2506     UNUSED_PARAM(page);
2507 #endif
2508 }
2509
2510 bool WKPageHasMediaSessionWithActiveMediaElements(WKPageRef page)
2511 {
2512 #if ENABLE(MEDIA_SESSION)
2513     return toImpl(page)->hasMediaSessionWithActiveMediaElements();
2514 #else
2515     UNUSED_PARAM(page);
2516     return false;
2517 #endif
2518 }
2519
2520 void WKPageHandleMediaEvent(WKPageRef page, WKMediaEventType wkEventType)
2521 {
2522 #if ENABLE(MEDIA_SESSION)
2523     MediaEventType eventType;
2524
2525     switch (wkEventType) {
2526     case kWKMediaEventTypePlayPause:
2527         eventType = MediaEventType::PlayPause;
2528         break;
2529     case kWKMediaEventTypeTrackNext:
2530         eventType = MediaEventType::TrackNext;
2531         break;
2532     case kWKMediaEventTypeTrackPrevious:
2533         eventType = MediaEventType::TrackPrevious;
2534         break;
2535     default:
2536         ASSERT_NOT_REACHED();
2537         return;
2538     }
2539
2540     toImpl(page)->handleMediaEvent(eventType);
2541 #else
2542     UNUSED_PARAM(page);
2543     UNUSED_PARAM(wkEventType);
2544 #endif
2545 }
2546
2547 void WKPagePostMessageToInjectedBundle(WKPageRef pageRef, WKStringRef messageNameRef, WKTypeRef messageBodyRef)
2548 {
2549     toImpl(pageRef)->postMessageToInjectedBundle(toImpl(messageNameRef)->string(), toImpl(messageBodyRef));
2550 }
2551
2552 WKArrayRef WKPageCopyRelatedPages(WKPageRef pageRef)
2553 {
2554     Vector<RefPtr<API::Object>> relatedPages;
2555
2556     for (auto& page : toImpl(pageRef)->process().pages()) {
2557         if (page != toImpl(pageRef))
2558             relatedPages.append(page);
2559     }
2560
2561     return toAPI(&API::Array::create(WTFMove(relatedPages)).leakRef());
2562 }
2563
2564 WKFrameRef WKPageLookUpFrameFromHandle(WKPageRef pageRef, WKFrameHandleRef handleRef)
2565 {
2566     auto page = toImpl(pageRef);
2567     auto frame = page->process().webFrame(toImpl(handleRef)->frameID());
2568     if (!frame || frame->page() != page)
2569         return nullptr;
2570
2571     return toAPI(frame);
2572 }
2573
2574 void WKPageSetMayStartMediaWhenInWindow(WKPageRef pageRef, bool mayStartMedia)
2575 {
2576     toImpl(pageRef)->setMayStartMediaWhenInWindow(mayStartMedia);
2577 }
2578
2579
2580 void WKPageSelectContextMenuItem(WKPageRef page, WKContextMenuItemRef item)
2581 {
2582 #if ENABLE(CONTEXT_MENUS)
2583     toImpl(page)->contextMenuItemSelected((toImpl(item)->data()));
2584 #else
2585     UNUSED_PARAM(page);
2586     UNUSED_PARAM(item);
2587 #endif
2588 }
2589
2590 WKScrollPinningBehavior WKPageGetScrollPinningBehavior(WKPageRef page)
2591 {
2592     ScrollPinningBehavior pinning = toImpl(page)->scrollPinningBehavior();
2593     
2594     switch (pinning) {
2595     case WebCore::ScrollPinningBehavior::DoNotPin:
2596         return kWKScrollPinningBehaviorDoNotPin;
2597     case WebCore::ScrollPinningBehavior::PinToTop:
2598         return kWKScrollPinningBehaviorPinToTop;
2599     case WebCore::ScrollPinningBehavior::PinToBottom:
2600         return kWKScrollPinningBehaviorPinToBottom;
2601     }
2602     
2603     ASSERT_NOT_REACHED();
2604     return kWKScrollPinningBehaviorDoNotPin;
2605 }
2606
2607 void WKPageSetScrollPinningBehavior(WKPageRef page, WKScrollPinningBehavior pinning)
2608 {
2609     ScrollPinningBehavior corePinning = ScrollPinningBehavior::DoNotPin;
2610
2611     switch (pinning) {
2612     case kWKScrollPinningBehaviorDoNotPin:
2613         corePinning = ScrollPinningBehavior::DoNotPin;
2614         break;
2615     case kWKScrollPinningBehaviorPinToTop:
2616         corePinning = ScrollPinningBehavior::PinToTop;
2617         break;
2618     case kWKScrollPinningBehaviorPinToBottom:
2619         corePinning = ScrollPinningBehavior::PinToBottom;
2620         break;
2621     default:
2622         ASSERT_NOT_REACHED();
2623     }
2624     
2625     toImpl(page)->setScrollPinningBehavior(corePinning);
2626 }
2627
2628 bool WKPageGetAddsVisitedLinks(WKPageRef page)
2629 {
2630     return toImpl(page)->addsVisitedLinks();
2631 }
2632
2633 void WKPageSetAddsVisitedLinks(WKPageRef page, bool addsVisitedLinks)
2634 {
2635     toImpl(page)->setAddsVisitedLinks(addsVisitedLinks);
2636 }
2637
2638 bool WKPageIsPlayingAudio(WKPageRef page)
2639 {
2640     return toImpl(page)->isPlayingAudio();
2641 }
2642
2643 WKMediaState WKPageGetMediaState(WKPageRef page)
2644 {
2645     WebCore::MediaProducer::MediaStateFlags coreState = toImpl(page)->mediaStateFlags();
2646     WKMediaState state = kWKMediaIsNotPlaying;
2647
2648     if (coreState & WebCore::MediaProducer::IsPlayingAudio)
2649         state |= kWKMediaIsPlayingAudio;
2650     if (coreState & WebCore::MediaProducer::IsPlayingVideo)
2651         state |= kWKMediaIsPlayingVideo;
2652     if (coreState & WebCore::MediaProducer::HasActiveAudioCaptureDevice)
2653         state |= kWKMediaHasActiveAudioCaptureDevice;
2654     if (coreState & WebCore::MediaProducer::HasActiveVideoCaptureDevice)
2655         state |= kWKMediaHasActiveVideoCaptureDevice;
2656     if (coreState & WebCore::MediaProducer::HasMutedAudioCaptureDevice)
2657         state |= kWKMediaHasMutedAudioCaptureDevice;
2658     if (coreState & WebCore::MediaProducer::HasMutedVideoCaptureDevice)
2659         state |= kWKMediaHasMutedVideoCaptureDevice;
2660     if (coreState & WebCore::MediaProducer::HasActiveDisplayCaptureDevice)
2661         state |= kWKMediaHasActiveDisplayCaptureDevice;
2662     if (coreState & WebCore::MediaProducer::HasMutedDisplayCaptureDevice)
2663         state |= kWKMediaHasMutedDisplayCaptureDevice;
2664
2665     return state;
2666 }
2667
2668 void WKPageClearWheelEventTestTrigger(WKPageRef pageRef)
2669 {
2670     toImpl(pageRef)->clearWheelEventTestTrigger();
2671 }
2672
2673 void WKPageCallAfterNextPresentationUpdate(WKPageRef pageRef, void* context, WKPagePostPresentationUpdateFunction callback)
2674 {
2675     toImpl(pageRef)->callAfterNextPresentationUpdate([context, callback](WebKit::CallbackBase::Error error) {
2676         callback(error != WebKit::CallbackBase::Error::None ? toAPI(API::Error::create().ptr()) : 0, context);
2677     });
2678 }
2679
2680 bool WKPageGetResourceCachingDisabled(WKPageRef page)
2681 {
2682     return toImpl(page)->isResourceCachingDisabled();
2683 }
2684
2685 void WKPageSetResourceCachingDisabled(WKPageRef page, bool disabled)
2686 {
2687     toImpl(page)->setResourceCachingDisabled(disabled);
2688 }
2689
2690 void WKPageSetIgnoresViewportScaleLimits(WKPageRef page, bool ignoresViewportScaleLimits)
2691 {
2692 #if PLATFORM(IOS_FAMILY)
2693     toImpl(page)->setForceAlwaysUserScalable(ignoresViewportScaleLimits);
2694 #endif
2695 }
2696
2697 ProcessID WKPageGetProcessIdentifier(WKPageRef page)
2698 {
2699     return toImpl(page)->processIdentifier();
2700 }
2701
2702 #ifdef __BLOCKS__
2703 void WKPageGetApplicationManifest_b(WKPageRef page, WKPageGetApplicationManifestBlock block)
2704 {
2705 #if ENABLE(APPLICATION_MANIFEST)
2706     toImpl(page)->getApplicationManifest([block](const Optional<WebCore::ApplicationManifest> &manifest, CallbackBase::Error) {
2707         block();
2708     });
2709 #else // ENABLE(APPLICATION_MANIFEST)
2710     UNUSED_PARAM(page);
2711     block();
2712 #endif // not ENABLE(APPLICATION_MANIFEST)
2713 }
2714 #endif
2715
2716 void WKPageDumpAdClickAttribution(WKPageRef page, WKPageDumpAdClickAttributionFunction callback, void* callbackContext)
2717 {
2718     toImpl(page)->dumpAdClickAttribution([callbackContext, callback] (const String& adClickAttribution) {
2719         callback(WebKit::toAPI(adClickAttribution.impl()), callbackContext);
2720     });
2721 }
2722
2723 void WKPageClearAdClickAttribution(WKPageRef page, WKPageClearAdClickAttributionFunction callback, void* callbackContext)
2724 {
2725     toImpl(page)->clearAdClickAttribution([callbackContext, callback] () {
2726         callback(callbackContext);
2727     });
2728 }