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