Allow specifying which plug-ins are supported
[WebKit-https.git] / Source / WebKit / WebProcess / WebCoreSupport / WebChromeClient.cpp
1 /*
2  * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebChromeClient.h"
29
30 #include "APIArray.h"
31 #include "APISecurityOrigin.h"
32 #include "DrawingArea.h"
33 #include "FindController.h"
34 #include "FrameInfoData.h"
35 #include "HangDetectionDisabler.h"
36 #include "InjectedBundleNavigationAction.h"
37 #include "InjectedBundleNodeHandle.h"
38 #include "NavigationActionData.h"
39 #include "PageBanner.h"
40 #include "UserData.h"
41 #include "WebColorChooser.h"
42 #include "WebCoreArgumentCoders.h"
43 #include "WebFrame.h"
44 #include "WebFrameLoaderClient.h"
45 #include "WebFullScreenManager.h"
46 #include "WebHitTestResultData.h"
47 #include "WebImage.h"
48 #include "WebOpenPanelResultListener.h"
49 #include "WebPage.h"
50 #include "WebPageCreationParameters.h"
51 #include "WebPageProxyMessages.h"
52 #include "WebPopupMenu.h"
53 #include "WebProcess.h"
54 #include "WebProcessPoolMessages.h"
55 #include "WebProcessProxyMessages.h"
56 #include "WebSearchPopupMenu.h"
57 #include <WebCore/ApplicationCacheStorage.h>
58 #include <WebCore/AXObjectCache.h>
59 #include <WebCore/ColorChooser.h>
60 #include <WebCore/DatabaseTracker.h>
61 #include <WebCore/DocumentLoader.h>
62 #include <WebCore/FileChooser.h>
63 #include <WebCore/FileIconLoader.h>
64 #include <WebCore/FrameLoadRequest.h>
65 #include <WebCore/FrameLoader.h>
66 #include <WebCore/FrameView.h>
67 #include <WebCore/HTMLInputElement.h>
68 #include <WebCore/HTMLNames.h>
69 #include <WebCore/HTMLParserIdioms.h>
70 #include <WebCore/HTMLPlugInImageElement.h>
71 #include <WebCore/Icon.h>
72 #include <WebCore/MainFrame.h>
73 #include <WebCore/NotImplemented.h>
74 #include <WebCore/Page.h>
75 #include <WebCore/ScriptController.h>
76 #include <WebCore/SecurityOrigin.h>
77 #include <WebCore/SecurityOriginData.h>
78 #include <WebCore/Settings.h>
79
80 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
81 #include "PlaybackSessionManager.h"
82 #include "VideoFullscreenManager.h"
83 #endif
84
85 #if ENABLE(ASYNC_SCROLLING)
86 #include "RemoteScrollingCoordinator.h"
87 #endif
88
89 #if PLATFORM(GTK)
90 #include "PrinterListGtk.h"
91 #endif
92
93 using namespace WebCore;
94 using namespace HTMLNames;
95
96 namespace WebKit {
97
98 static double area(WebFrame* frame)
99 {
100     IntSize size = frame->visibleContentBoundsExcludingScrollbars().size();
101     return static_cast<double>(size.height()) * size.width();
102 }
103
104 static WebFrame* findLargestFrameInFrameSet(WebPage& page)
105 {
106     // Approximate what a user could consider a default target frame for application menu operations.
107
108     WebFrame* mainFrame = page.mainWebFrame();
109     if (!mainFrame || !mainFrame->isFrameSet())
110         return nullptr;
111
112     WebFrame* largestSoFar = nullptr;
113
114     Ref<API::Array> frameChildren = mainFrame->childFrames();
115     size_t count = frameChildren->size();
116     for (size_t i = 0; i < count; ++i) {
117         auto* childFrame = frameChildren->at<WebFrame>(i);
118         if (!largestSoFar || area(childFrame) > area(largestSoFar))
119             largestSoFar = childFrame;
120     }
121
122     return largestSoFar;
123 }
124
125 WebChromeClient::WebChromeClient(WebPage& page)
126     : m_page(page)
127 {
128 }
129
130 void WebChromeClient::didInsertMenuElement(HTMLMenuElement& element)
131 {
132     m_page.didInsertMenuElement(element);
133 }
134
135 void WebChromeClient::didRemoveMenuElement(HTMLMenuElement& element)
136 {
137     m_page.didRemoveMenuElement(element);
138 }
139
140 void WebChromeClient::didInsertMenuItemElement(HTMLMenuItemElement& element)
141 {
142     m_page.didInsertMenuItemElement(element);
143 }
144
145 void WebChromeClient::didRemoveMenuItemElement(HTMLMenuItemElement& element)
146 {
147     m_page.didRemoveMenuItemElement(element);
148 }
149
150 inline WebChromeClient::~WebChromeClient()
151 {
152 }
153
154 void WebChromeClient::chromeDestroyed()
155 {
156     delete this;
157 }
158
159 void WebChromeClient::setWindowRect(const FloatRect& windowFrame)
160 {
161     m_page.sendSetWindowFrame(windowFrame);
162 }
163
164 FloatRect WebChromeClient::windowRect()
165 {
166 #if PLATFORM(IOS)
167     return FloatRect();
168 #else
169 #if PLATFORM(MAC)
170     if (m_page.hasCachedWindowFrame())
171         return m_page.windowFrameInUnflippedScreenCoordinates();
172 #endif
173
174     FloatRect newWindowFrame;
175
176     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::GetWindowFrame(), Messages::WebPageProxy::GetWindowFrame::Reply(newWindowFrame), m_page.pageID()))
177         return FloatRect();
178
179     return newWindowFrame;
180 #endif
181 }
182
183 FloatRect WebChromeClient::pageRect()
184 {
185     return FloatRect(FloatPoint(), m_page.size());
186 }
187
188 void WebChromeClient::focus()
189 {
190     m_page.send(Messages::WebPageProxy::SetFocus(true));
191 }
192
193 void WebChromeClient::unfocus()
194 {
195     m_page.send(Messages::WebPageProxy::SetFocus(false));
196 }
197
198 #if PLATFORM(COCOA)
199
200 void WebChromeClient::elementDidFocus(Element& element)
201 {
202     m_page.elementDidFocus(&element);
203 }
204
205 void WebChromeClient::elementDidBlur(Element& element)
206 {
207     m_page.elementDidBlur(&element);
208 }
209
210 void WebChromeClient::makeFirstResponder()
211 {
212     m_page.send(Messages::WebPageProxy::MakeFirstResponder());
213 }
214
215 #endif    
216
217 bool WebChromeClient::canTakeFocus(FocusDirection)
218 {
219     notImplemented();
220     return true;
221 }
222
223 void WebChromeClient::takeFocus(FocusDirection direction)
224 {
225     m_page.send(Messages::WebPageProxy::TakeFocus(direction));
226 }
227
228 void WebChromeClient::focusedElementChanged(Element* element)
229 {
230     if (!is<HTMLInputElement>(element))
231         return;
232
233     HTMLInputElement& inputElement = downcast<HTMLInputElement>(*element);
234     if (!inputElement.isText())
235         return;
236
237     WebFrame* webFrame = WebFrame::fromCoreFrame(*element->document().frame());
238     ASSERT(webFrame);
239     m_page.injectedBundleFormClient().didFocusTextField(&m_page, &inputElement, webFrame);
240 }
241
242 void WebChromeClient::focusedFrameChanged(Frame* frame)
243 {
244     WebFrame* webFrame = frame ? WebFrame::fromCoreFrame(*frame) : nullptr;
245
246     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPageProxy::FocusedFrameChanged(webFrame ? webFrame->frameID() : 0), m_page.pageID());
247 }
248
249 Page* WebChromeClient::createWindow(Frame& frame, const FrameLoadRequest& request, const WindowFeatures& windowFeatures, const NavigationAction& navigationAction)
250 {
251 #if ENABLE(FULLSCREEN_API)
252     if (frame.document() && frame.document()->webkitCurrentFullScreenElement())
253         frame.document()->webkitCancelFullScreen();
254 #endif
255
256     auto& webProcess = WebProcess::singleton();
257
258     NavigationActionData navigationActionData;
259     navigationActionData.navigationType = navigationAction.type();
260     navigationActionData.modifiers = InjectedBundleNavigationAction::modifiersForNavigationAction(navigationAction);
261     navigationActionData.mouseButton = InjectedBundleNavigationAction::mouseButtonForNavigationAction(navigationAction);
262     navigationActionData.syntheticClickType = InjectedBundleNavigationAction::syntheticClickTypeForNavigationAction(navigationAction);
263     navigationActionData.clickLocationInRootViewCoordinates = InjectedBundleNavigationAction::clickLocationInRootViewCoordinatesForNavigationAction(navigationAction);
264     navigationActionData.userGestureTokenIdentifier = webProcess.userGestureTokenIdentifier(navigationAction.userGestureToken());
265     navigationActionData.canHandleRequest = m_page.canHandleRequest(request.resourceRequest());
266     navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
267     navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
268
269     WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
270
271     uint64_t newPageID = 0;
272     WebPageCreationParameters parameters;
273     if (!webProcess.parentProcessConnection()->sendSync(Messages::WebPageProxy::CreateNewPage(webFrame->info(), webFrame->page()->pageID(), request.resourceRequest(), windowFeatures, navigationActionData), Messages::WebPageProxy::CreateNewPage::Reply(newPageID, parameters), m_page.pageID()))
274         return nullptr;
275
276     if (!newPageID)
277         return nullptr;
278
279     webProcess.createWebPage(newPageID, WTFMove(parameters));
280     return webProcess.webPage(newPageID)->corePage();
281 }
282
283 void WebChromeClient::show()
284 {
285     m_page.show();
286 }
287
288 bool WebChromeClient::canRunModal()
289 {
290     return m_page.canRunModal();
291 }
292
293 void WebChromeClient::runModal()
294 {
295     m_page.runModal();
296 }
297
298 void WebChromeClient::reportProcessCPUTime(Seconds cpuTime, ActivityStateForCPUSampling activityState)
299 {
300     WebProcess::singleton().send(Messages::WebProcessPool::ReportWebContentCPUTime(cpuTime, static_cast<uint64_t>(activityState)), 0);
301 }
302
303 void WebChromeClient::setToolbarsVisible(bool toolbarsAreVisible)
304 {
305     m_page.send(Messages::WebPageProxy::SetToolbarsAreVisible(toolbarsAreVisible));
306 }
307
308 bool WebChromeClient::toolbarsVisible()
309 {
310     API::InjectedBundle::PageUIClient::UIElementVisibility toolbarsVisibility = m_page.injectedBundleUIClient().toolbarsAreVisible(&m_page);
311     if (toolbarsVisibility != API::InjectedBundle::PageUIClient::UIElementVisibility::Unknown)
312         return toolbarsVisibility == API::InjectedBundle::PageUIClient::UIElementVisibility::Visible;
313     
314     bool toolbarsAreVisible = true;
315     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::GetToolbarsAreVisible(), Messages::WebPageProxy::GetToolbarsAreVisible::Reply(toolbarsAreVisible), m_page.pageID()))
316         return true;
317
318     return toolbarsAreVisible;
319 }
320
321 void WebChromeClient::setStatusbarVisible(bool statusBarIsVisible)
322 {
323     m_page.send(Messages::WebPageProxy::SetStatusBarIsVisible(statusBarIsVisible));
324 }
325
326 bool WebChromeClient::statusbarVisible()
327 {
328     API::InjectedBundle::PageUIClient::UIElementVisibility statusbarVisibility = m_page.injectedBundleUIClient().statusBarIsVisible(&m_page);
329     if (statusbarVisibility != API::InjectedBundle::PageUIClient::UIElementVisibility::Unknown)
330         return statusbarVisibility == API::InjectedBundle::PageUIClient::UIElementVisibility::Visible;
331
332     bool statusBarIsVisible = true;
333     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::GetStatusBarIsVisible(), Messages::WebPageProxy::GetStatusBarIsVisible::Reply(statusBarIsVisible), m_page.pageID()))
334         return true;
335
336     return statusBarIsVisible;
337 }
338
339 void WebChromeClient::setScrollbarsVisible(bool)
340 {
341     notImplemented();
342 }
343
344 bool WebChromeClient::scrollbarsVisible()
345 {
346     notImplemented();
347     return true;
348 }
349
350 void WebChromeClient::setMenubarVisible(bool menuBarVisible)
351 {
352     m_page.send(Messages::WebPageProxy::SetMenuBarIsVisible(menuBarVisible));
353 }
354
355 bool WebChromeClient::menubarVisible()
356 {
357     API::InjectedBundle::PageUIClient::UIElementVisibility menubarVisibility = m_page.injectedBundleUIClient().menuBarIsVisible(&m_page);
358     if (menubarVisibility != API::InjectedBundle::PageUIClient::UIElementVisibility::Unknown)
359         return menubarVisibility == API::InjectedBundle::PageUIClient::UIElementVisibility::Visible;
360     
361     bool menuBarIsVisible = true;
362     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::GetMenuBarIsVisible(), Messages::WebPageProxy::GetMenuBarIsVisible::Reply(menuBarIsVisible), m_page.pageID()))
363         return true;
364
365     return menuBarIsVisible;
366 }
367
368 void WebChromeClient::setResizable(bool resizable)
369 {
370     m_page.send(Messages::WebPageProxy::SetIsResizable(resizable));
371 }
372
373 void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned columnNumber, const String& sourceID)
374 {
375     // Notify the bundle client.
376     m_page.injectedBundleUIClient().willAddMessageToConsole(&m_page, source, level, message, lineNumber, columnNumber, sourceID);
377 }
378
379 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
380 {
381     return m_page.canRunBeforeUnloadConfirmPanel();
382 }
383
384 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame& frame)
385 {
386     WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
387
388     bool shouldClose = false;
389
390     HangDetectionDisabler hangDetectionDisabler;
391
392     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunBeforeUnloadConfirmPanel(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::Reply(shouldClose), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))
393         return false;
394
395     return shouldClose;
396 }
397
398 void WebChromeClient::closeWindowSoon()
399 {
400     // FIXME: This code assumes that the client will respond to a close page
401     // message by actually closing the page. Safari does this, but there is
402     // no guarantee that other applications will, which will leave this page
403     // half detached. This approach is an inherent limitation making parts of
404     // a close execute synchronously as part of window.close, but other parts
405     // later on.
406
407     m_page.corePage()->setGroupName(String());
408
409     if (WebFrame* frame = m_page.mainWebFrame()) {
410         if (Frame* coreFrame = frame->coreFrame())
411             coreFrame->loader().stopForUserCancel();
412     }
413
414     m_page.sendClose();
415 }
416
417 static bool shouldSuppressJavaScriptDialogs(Frame& frame)
418 {
419     if (frame.loader().opener() && frame.loader().stateMachine().isDisplayingInitialEmptyDocument() && frame.loader().provisionalDocumentLoader())
420         return true;
421
422     return false;
423 }
424
425 void WebChromeClient::runJavaScriptAlert(Frame& frame, const String& alertText)
426 {
427     if (shouldSuppressJavaScriptDialogs(frame))
428         return;
429
430     WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
431     ASSERT(webFrame);
432
433     // Notify the bundle client.
434     m_page.injectedBundleUIClient().willRunJavaScriptAlert(&m_page, alertText, webFrame);
435
436     HangDetectionDisabler hangDetectionDisabler;
437
438     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply(), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
439 }
440
441 bool WebChromeClient::runJavaScriptConfirm(Frame& frame, const String& message)
442 {
443     if (shouldSuppressJavaScriptDialogs(frame))
444         return false;
445
446     WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
447     ASSERT(webFrame);
448
449     // Notify the bundle client.
450     m_page.injectedBundleUIClient().willRunJavaScriptConfirm(&m_page, message, webFrame);
451
452     HangDetectionDisabler hangDetectionDisabler;
453
454     bool result = false;
455     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))
456         return false;
457
458     return result;
459 }
460
461 bool WebChromeClient::runJavaScriptPrompt(Frame& frame, const String& message, const String& defaultValue, String& result)
462 {
463     if (shouldSuppressJavaScriptDialogs(frame))
464         return false;
465
466     WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
467     ASSERT(webFrame);
468
469     // Notify the bundle client.
470     m_page.injectedBundleUIClient().willRunJavaScriptPrompt(&m_page, message, defaultValue, webFrame);
471
472     HangDetectionDisabler hangDetectionDisabler;
473
474     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))
475         return false;
476
477     return !result.isNull();
478 }
479
480 void WebChromeClient::setStatusbarText(const String& statusbarText)
481 {
482     // Notify the bundle client.
483     m_page.injectedBundleUIClient().willSetStatusbarText(&m_page, statusbarText);
484
485     m_page.send(Messages::WebPageProxy::SetStatusText(statusbarText));
486 }
487
488 KeyboardUIMode WebChromeClient::keyboardUIMode()
489 {
490     return m_page.keyboardUIMode();
491 }
492
493 #if ENABLE(POINTER_LOCK)
494
495 bool WebChromeClient::requestPointerLock()
496 {
497     m_page.send(Messages::WebPageProxy::RequestPointerLock());
498     return true;
499 }
500
501 void WebChromeClient::requestPointerUnlock()
502 {
503     m_page.send(Messages::WebPageProxy::RequestPointerUnlock());
504 }
505
506 #endif
507
508 void WebChromeClient::invalidateRootView(const IntRect&)
509 {
510     // Do nothing here, there's no concept of invalidating the window in the web process.
511 }
512
513 void WebChromeClient::invalidateContentsAndRootView(const IntRect& rect)
514 {
515     if (Document* document = m_page.corePage()->mainFrame().document()) {
516         if (document->printing())
517             return;
518     }
519
520     m_page.drawingArea()->setNeedsDisplayInRect(rect);
521 }
522
523 void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& rect)
524 {
525     if (Document* document = m_page.corePage()->mainFrame().document()) {
526         if (document->printing())
527             return;
528     }
529
530     m_page.pageDidScroll();
531 #if USE(COORDINATED_GRAPHICS)
532     FrameView* frameView = m_page.mainFrame()->view();
533     if (frameView && frameView->delegatesScrolling()) {
534         m_page.drawingArea()->scroll(rect, IntSize());
535         return;
536     }
537 #endif
538     m_page.drawingArea()->setNeedsDisplayInRect(rect);
539 }
540
541 void WebChromeClient::scroll(const IntSize& scrollDelta, const IntRect& scrollRect, const IntRect& clipRect)
542 {
543     m_page.pageDidScroll();
544     m_page.drawingArea()->scroll(intersection(scrollRect, clipRect), scrollDelta);
545 }
546
547 #if USE(COORDINATED_GRAPHICS)
548 void WebChromeClient::delegatedScrollRequested(const IntPoint& scrollOffset)
549 {
550     m_page.pageDidRequestScroll(scrollOffset);
551 }
552
553 void WebChromeClient::resetUpdateAtlasForTesting()
554 {
555     m_page.drawingArea()->resetUpdateAtlasForTesting();
556 }
557 #endif
558
559 IntPoint WebChromeClient::screenToRootView(const IntPoint& point) const
560 {
561     return m_page.screenToRootView(point);
562 }
563
564 IntRect WebChromeClient::rootViewToScreen(const IntRect& rect) const
565 {
566     return m_page.rootViewToScreen(rect);
567 }
568     
569 #if PLATFORM(IOS)
570 IntPoint WebChromeClient::accessibilityScreenToRootView(const IntPoint& point) const
571 {
572     return m_page.accessibilityScreenToRootView(point);
573 }
574
575 IntRect WebChromeClient::rootViewToAccessibilityScreen(const IntRect& rect) const
576 {
577     return m_page.rootViewToAccessibilityScreen(rect);
578 }
579 #endif
580
581 PlatformPageClient WebChromeClient::platformPageClient() const
582 {
583     notImplemented();
584     return 0;
585 }
586
587 void WebChromeClient::contentsSizeChanged(Frame& frame, const IntSize& size) const
588 {
589     FrameView* frameView = frame.view();
590
591     if (frameView && frameView->effectiveFrameFlattening() == FrameFlattening::Disabled) {
592         WebFrame* largestFrame = findLargestFrameInFrameSet(m_page);
593         if (largestFrame != m_cachedFrameSetLargestFrame.get()) {
594             m_cachedFrameSetLargestFrame = largestFrame;
595             m_page.send(Messages::WebPageProxy::FrameSetLargestFrameChanged(largestFrame ? largestFrame->frameID() : 0));
596         }
597     }
598
599     if (&frame.page()->mainFrame() != &frame)
600         return;
601
602     m_page.send(Messages::WebPageProxy::DidChangeContentSize(size));
603
604     m_page.drawingArea()->mainFrameContentSizeChanged(size);
605
606     if (frameView && !frameView->delegatesScrolling())  {
607         bool hasHorizontalScrollbar = frameView->horizontalScrollbar();
608         bool hasVerticalScrollbar = frameView->verticalScrollbar();
609
610         if (hasHorizontalScrollbar != m_cachedMainFrameHasHorizontalScrollbar || hasVerticalScrollbar != m_cachedMainFrameHasVerticalScrollbar) {
611             m_page.send(Messages::WebPageProxy::DidChangeScrollbarsForMainFrame(hasHorizontalScrollbar, hasVerticalScrollbar));
612
613             m_cachedMainFrameHasHorizontalScrollbar = hasHorizontalScrollbar;
614             m_cachedMainFrameHasVerticalScrollbar = hasVerticalScrollbar;
615         }
616     }
617 }
618
619 void WebChromeClient::scrollRectIntoView(const IntRect&) const
620 {
621     notImplemented();
622 }
623
624 bool WebChromeClient::shouldUnavailablePluginMessageBeButton(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
625 {
626     switch (pluginUnavailabilityReason) {
627     case RenderEmbeddedObject::PluginMissing:
628         // FIXME: <rdar://problem/8794397> We should only return true when there is a
629         // missingPluginButtonClicked callback defined on the Page UI client.
630     case RenderEmbeddedObject::InsecurePluginVersion:
631         return true;
632
633
634     case RenderEmbeddedObject::PluginCrashed:
635     case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
636     case RenderEmbeddedObject::UnsupportedPlugin:
637         return false;
638     }
639
640     ASSERT_NOT_REACHED();
641     return false;
642 }
643     
644 void WebChromeClient::unavailablePluginButtonClicked(Element& element, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
645 {
646 #if ENABLE(NETSCAPE_PLUGIN_API)
647     ASSERT(element.hasTagName(objectTag) || element.hasTagName(embedTag) || element.hasTagName(appletTag));
648     ASSERT(pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing || pluginUnavailabilityReason == RenderEmbeddedObject::InsecurePluginVersion || pluginUnavailabilityReason);
649
650     auto& pluginElement = downcast<HTMLPlugInImageElement>(element);
651
652     String frameURLString = pluginElement.document().frame()->loader().documentLoader()->responseURL().string();
653     String pageURLString = m_page.mainFrame()->loader().documentLoader()->responseURL().string();
654     String pluginURLString = pluginElement.document().completeURL(pluginElement.url()).string();
655     URL pluginspageAttributeURL = pluginElement.document().completeURL(stripLeadingAndTrailingHTMLSpaces(pluginElement.attributeWithoutSynchronization(pluginspageAttr)));
656     if (!pluginspageAttributeURL.protocolIsInHTTPFamily())
657         pluginspageAttributeURL = URL();
658     m_page.send(Messages::WebPageProxy::UnavailablePluginButtonClicked(pluginUnavailabilityReason, pluginElement.serviceType(), pluginURLString, pluginspageAttributeURL.string(), frameURLString, pageURLString));
659 #else
660     UNUSED_PARAM(element);
661     UNUSED_PARAM(pluginUnavailabilityReason);
662 #endif // ENABLE(NETSCAPE_PLUGIN_API)
663 }
664
665 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& hitTestResult, unsigned modifierFlags)
666 {
667     RefPtr<API::Object> userData;
668
669     // Notify the bundle client.
670     m_page.injectedBundleUIClient().mouseDidMoveOverElement(&m_page, hitTestResult, static_cast<WebEvent::Modifiers>(modifierFlags), userData);
671
672     // Notify the UIProcess.
673     WebHitTestResultData webHitTestResultData(hitTestResult);
674     m_page.send(Messages::WebPageProxy::MouseDidMoveOverElement(webHitTestResultData, modifierFlags, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
675 }
676
677 void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
678 {
679     // Only send a tool tip to the WebProcess if it has changed since the last time this function was called.
680
681     if (toolTip == m_cachedToolTip)
682         return;
683     m_cachedToolTip = toolTip;
684
685     m_page.send(Messages::WebPageProxy::SetToolTip(m_cachedToolTip));
686 }
687
688 void WebChromeClient::print(Frame& frame)
689 {
690     WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
691     ASSERT(webFrame);
692
693 #if PLATFORM(GTK) && HAVE(GTK_UNIX_PRINTING)
694     // When printing synchronously in GTK+ we need to make sure that we have a list of Printers before starting the print operation.
695     // Getting the list of printers is done synchronously by GTK+, but using a nested main loop that might process IPC messages
696     // comming from the UI process like EndPrinting. When the EndPriting message is received while the printer list is being populated,
697     // the print operation is finished unexpectely and the web process crashes, see https://bugs.webkit.org/show_bug.cgi?id=126979.
698     // The PrinterListGtk class gets the list of printers in the constructor so we just need to ensure there's an instance alive
699     // during the synchronous print operation.
700     RefPtr<PrinterListGtk> printerList = PrinterListGtk::getOrCreate();
701     if (!printerList) {
702         // PrinterListGtk::getOrCreate() returns nullptr when called while a printers enumeration is ongoing.
703         // This can happen if a synchronous print is started by a JavaScript and another one is inmeditaley started
704         // from a JavaScript event listener. The second print operation is handled by the nested main loop used by GTK+
705         // to enumerate the printers, and we end up here trying to get a reference of an object that is being constructed.
706         // It's very unlikely that the user wants to print twice in a row, and other browsers don't do two print operations
707         // in this particular case either. So, the safest solution is to return early here and ignore the second print.
708         // See https://bugs.webkit.org/show_bug.cgi?id=141035
709         return;
710     }
711 #endif
712
713     m_page.sendSync(Messages::WebPageProxy::PrintFrame(webFrame->frameID()), Messages::WebPageProxy::PrintFrame::Reply(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
714 }
715
716 void WebChromeClient::testIncomingSyncIPCMessageWhileWaitingForSyncReply()
717 {
718     bool wasHandled = false;
719     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebProcessProxy::TestIncomingSyncIPCMessageWhileWaitingForSyncReply(), Messages::WebProcessProxy::TestIncomingSyncIPCMessageWhileWaitingForSyncReply::Reply(wasHandled), 0, Seconds::infinity(), IPC::SendSyncOption::DoNotProcessIncomingMessagesWhenWaitingForSyncReply);
720     RELEASE_ASSERT(wasHandled);
721 }
722
723 void WebChromeClient::exceededDatabaseQuota(Frame& frame, const String& databaseName, DatabaseDetails details)
724 {
725     WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
726     ASSERT(webFrame);
727     
728     auto& origin = frame.document()->securityOrigin();
729     auto originData = SecurityOriginData::fromSecurityOrigin(origin);
730     auto& tracker = DatabaseTracker::singleton();
731     auto currentQuota = tracker.quota(originData);
732     auto currentOriginUsage = tracker.usage(originData);
733     uint64_t newQuota = 0;
734     RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(SecurityOriginData::fromSecurityOrigin(origin).databaseIdentifier())->securityOrigin());
735     newQuota = m_page.injectedBundleUIClient().didExceedDatabaseQuota(&m_page, securityOrigin.get(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage());
736
737     if (!newQuota) {
738         WebProcess::singleton().parentProcessConnection()->sendSync(
739             Messages::WebPageProxy::ExceededDatabaseQuota(webFrame->frameID(), SecurityOriginData::fromSecurityOrigin(origin).databaseIdentifier(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage()),
740             Messages::WebPageProxy::ExceededDatabaseQuota::Reply(newQuota), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
741     }
742
743     tracker.setQuota(originData, newQuota);
744 }
745
746 void WebChromeClient::reachedMaxAppCacheSize(int64_t)
747 {
748     notImplemented();
749 }
750
751 void WebChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin& origin, int64_t totalBytesNeeded)
752 {
753     RefPtr<API::SecurityOrigin> securityOrigin = API::SecurityOrigin::createFromString(origin.toString());
754     if (m_page.injectedBundleUIClient().didReachApplicationCacheOriginQuota(&m_page, securityOrigin.get(), totalBytesNeeded))
755         return;
756
757     auto& cacheStorage = m_page.corePage()->applicationCacheStorage();
758     int64_t currentQuota = 0;
759     if (!cacheStorage.calculateQuotaForOrigin(origin, currentQuota))
760         return;
761
762     uint64_t newQuota = 0;
763     WebProcess::singleton().parentProcessConnection()->sendSync(
764         Messages::WebPageProxy::ReachedApplicationCacheOriginQuota(SecurityOriginData::fromSecurityOrigin(origin).databaseIdentifier(), currentQuota, totalBytesNeeded),
765         Messages::WebPageProxy::ReachedApplicationCacheOriginQuota::Reply(newQuota), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
766
767     cacheStorage.storeUpdatedQuotaForOrigin(&origin, newQuota);
768 }
769
770 #if ENABLE(DASHBOARD_SUPPORT)
771
772 void WebChromeClient::annotatedRegionsChanged()
773 {
774     notImplemented();
775 }
776
777 #endif
778
779 bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
780 {
781     generatedFilename = m_page.injectedBundleUIClient().shouldGenerateFileForUpload(&m_page, path);
782     return !generatedFilename.isNull();
783 }
784
785 String WebChromeClient::generateReplacementFile(const String& path)
786 {
787     return m_page.injectedBundleUIClient().generateFileForUpload(&m_page, path);
788 }
789
790 #if ENABLE(INPUT_TYPE_COLOR)
791
792 std::unique_ptr<ColorChooser> WebChromeClient::createColorChooser(ColorChooserClient& client, const Color& initialColor)
793 {
794     return std::make_unique<WebColorChooser>(&m_page, &client, initialColor);
795 }
796
797 #endif
798
799 void WebChromeClient::runOpenPanel(Frame& frame, FileChooser& fileChooser)
800 {
801     if (m_page.activeOpenPanelResultListener())
802         return;
803
804     m_page.setActiveOpenPanelResultListener(WebOpenPanelResultListener::create(m_page, fileChooser));
805
806     auto* webFrame = WebFrame::fromCoreFrame(frame);
807     ASSERT(webFrame);
808     m_page.send(Messages::WebPageProxy::RunOpenPanel(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), fileChooser.settings()));
809 }
810
811 void WebChromeClient::loadIconForFiles(const Vector<String>& filenames, FileIconLoader& loader)
812 {
813     loader.iconLoaded(createIconForFiles(filenames));
814 }
815
816 #if !PLATFORM(IOS)
817
818 void WebChromeClient::setCursor(const Cursor& cursor)
819 {
820     m_page.send(Messages::WebPageProxy::SetCursor(cursor));
821 }
822
823 void WebChromeClient::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
824 {
825     m_page.send(Messages::WebPageProxy::SetCursorHiddenUntilMouseMoves(hiddenUntilMouseMoves));
826 }
827
828 RefPtr<Icon> WebChromeClient::createIconForFiles(const Vector<String>& filenames)
829 {
830     return Icon::createIconForFiles(filenames);
831 }
832
833 #endif
834
835 void WebChromeClient::didAssociateFormControls(const Vector<RefPtr<Element>>& elements)
836 {
837     return m_page.injectedBundleFormClient().didAssociateFormControls(&m_page, elements);
838 }
839
840 bool WebChromeClient::shouldNotifyOnFormChanges()
841 {
842     return m_page.injectedBundleFormClient().shouldNotifyOnFormChanges(&m_page);
843 }
844
845 bool WebChromeClient::selectItemWritingDirectionIsNatural()
846 {
847     return false;
848 }
849
850 bool WebChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
851 {
852     return true;
853 }
854
855 RefPtr<PopupMenu> WebChromeClient::createPopupMenu(PopupMenuClient& client) const
856 {
857     return WebPopupMenu::create(&m_page, &client);
858 }
859
860 RefPtr<SearchPopupMenu> WebChromeClient::createSearchPopupMenu(PopupMenuClient& client) const
861 {
862     return WebSearchPopupMenu::create(&m_page, &client);
863 }
864
865 GraphicsLayerFactory* WebChromeClient::graphicsLayerFactory() const
866 {
867     if (auto drawingArea = m_page.drawingArea())
868         return drawingArea->graphicsLayerFactory();
869     return nullptr;
870 }
871
872 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
873
874 RefPtr<DisplayRefreshMonitor> WebChromeClient::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
875 {
876     return m_page.drawingArea()->createDisplayRefreshMonitor(displayID);
877 }
878
879 #endif
880
881 void WebChromeClient::attachRootGraphicsLayer(Frame&, GraphicsLayer* layer)
882 {
883     if (layer)
884         m_page.enterAcceleratedCompositingMode(layer);
885     else
886         m_page.exitAcceleratedCompositingMode();
887 }
888
889 void WebChromeClient::attachViewOverlayGraphicsLayer(Frame& frame, GraphicsLayer* graphicsLayer)
890 {
891     if (auto drawingArea = m_page.drawingArea())
892         drawingArea->attachViewOverlayGraphicsLayer(&frame, graphicsLayer);
893 }
894
895 void WebChromeClient::setNeedsOneShotDrawingSynchronization()
896 {
897     notImplemented();
898 }
899
900 void WebChromeClient::scheduleCompositingLayerFlush()
901 {
902     if (m_page.drawingArea())
903         m_page.drawingArea()->scheduleCompositingLayerFlush();
904 }
905
906 void WebChromeClient::contentRuleListNotification(const URL& url, const HashSet<std::pair<String, String>>& notificationPairs)
907 {
908     Vector<String> identifiers;
909     Vector<String> notifications;
910     identifiers.reserveInitialCapacity(notificationPairs.size());
911     notifications.reserveInitialCapacity(notificationPairs.size());
912     for (auto& notification : notificationPairs) {
913         identifiers.uncheckedAppend(notification.first);
914         notifications.uncheckedAppend(notification.second);
915     }
916
917     m_page.send(Messages::WebPageProxy::ContentRuleListNotification(url, identifiers, notifications));
918 }
919
920 bool WebChromeClient::adjustLayerFlushThrottling(LayerFlushThrottleState::Flags flags)
921 {
922     return m_page.drawingArea() && m_page.drawingArea()->adjustLayerFlushThrottling(flags);
923 }
924
925 bool WebChromeClient::layerTreeStateIsFrozen() const
926 {
927     if (m_page.drawingArea())
928         return m_page.drawingArea()->layerTreeStateIsFrozen();
929
930     return false;
931 }
932
933 #if ENABLE(ASYNC_SCROLLING)
934
935 RefPtr<ScrollingCoordinator> WebChromeClient::createScrollingCoordinator(Page& page) const
936 {
937     ASSERT_UNUSED(page, m_page.corePage() == &page);
938     if (m_page.drawingArea()->type() != DrawingAreaTypeRemoteLayerTree)
939         return nullptr;
940     return RemoteScrollingCoordinator::create(&m_page);
941 }
942
943 #endif
944
945 #if (PLATFORM(IOS) && HAVE(AVKIT)) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
946
947 bool WebChromeClient::supportsVideoFullscreen(HTMLMediaElementEnums::VideoFullscreenMode mode)
948 {
949     return m_page.videoFullscreenManager().supportsVideoFullscreen(mode);
950 }
951
952 bool WebChromeClient::supportsVideoFullscreenStandby()
953 {
954     return m_page.videoFullscreenManager().supportsVideoFullscreenStandby();
955 }
956
957 void WebChromeClient::setUpPlaybackControlsManager(HTMLMediaElement& mediaElement)
958 {
959     m_page.playbackSessionManager().setUpPlaybackControlsManager(mediaElement);
960 }
961
962 void WebChromeClient::clearPlaybackControlsManager()
963 {
964     m_page.playbackSessionManager().clearPlaybackControlsManager();
965 }
966
967 void WebChromeClient::enterVideoFullscreenForVideoElement(HTMLVideoElement& videoElement, HTMLMediaElementEnums::VideoFullscreenMode mode, bool standby)
968 {
969 #if ENABLE(FULLSCREEN_API) && PLATFORM(IOS)
970     ASSERT(standby || mode != HTMLMediaElementEnums::VideoFullscreenModeNone);
971 #else
972     ASSERT(mode != HTMLMediaElementEnums::VideoFullscreenModeNone);
973 #endif
974     m_page.videoFullscreenManager().enterVideoFullscreenForVideoElement(videoElement, mode, standby);
975 }
976
977 void WebChromeClient::exitVideoFullscreenForVideoElement(HTMLVideoElement& videoElement)
978 {
979     m_page.videoFullscreenManager().exitVideoFullscreenForVideoElement(videoElement);
980 }
981
982 #endif
983
984 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
985
986 void WebChromeClient::exitVideoFullscreenToModeWithoutAnimation(HTMLVideoElement& videoElement, HTMLMediaElementEnums::VideoFullscreenMode targetMode)
987 {
988     m_page.videoFullscreenManager().exitVideoFullscreenToModeWithoutAnimation(videoElement, targetMode);
989 }
990
991 #endif
992
993 #if ENABLE(FULLSCREEN_API)
994
995 bool WebChromeClient::supportsFullScreenForElement(const Element&, bool withKeyboard)
996 {
997     return m_page.fullScreenManager()->supportsFullScreen(withKeyboard);
998 }
999
1000 void WebChromeClient::enterFullScreenForElement(Element& element)
1001 {
1002     m_page.fullScreenManager()->enterFullScreenForElement(&element);
1003 }
1004
1005 void WebChromeClient::exitFullScreenForElement(Element* element)
1006 {
1007     m_page.fullScreenManager()->exitFullScreenForElement(element);
1008 }
1009
1010 #endif
1011
1012 #if PLATFORM(IOS)
1013
1014 FloatSize WebChromeClient::screenSize() const
1015 {
1016     return m_page.screenSize();
1017 }
1018
1019 FloatSize WebChromeClient::availableScreenSize() const
1020 {
1021     return m_page.availableScreenSize();
1022 }
1023
1024 #endif
1025
1026 void WebChromeClient::dispatchViewportPropertiesDidChange(const ViewportArguments& viewportArguments) const
1027 {
1028     m_page.viewportPropertiesDidChange(viewportArguments);
1029 }
1030
1031 void WebChromeClient::notifyScrollerThumbIsVisibleInRect(const IntRect& scrollerThumb)
1032 {
1033     m_page.send(Messages::WebPageProxy::NotifyScrollerThumbIsVisibleInRect(scrollerThumb));
1034 }
1035
1036 void WebChromeClient::recommendedScrollbarStyleDidChange(ScrollbarStyle newStyle)
1037 {
1038     m_page.send(Messages::WebPageProxy::RecommendedScrollbarStyleDidChange(static_cast<int32_t>(newStyle)));
1039 }
1040
1041 std::optional<ScrollbarOverlayStyle> WebChromeClient::preferredScrollbarOverlayStyle()
1042 {
1043     return m_page.scrollbarOverlayStyle();
1044 }
1045
1046 Color WebChromeClient::underlayColor() const
1047 {
1048     return m_page.underlayColor();
1049 }
1050
1051 void WebChromeClient::pageExtendedBackgroundColorDidChange(Color backgroundColor) const
1052 {
1053 #if PLATFORM(MAC)
1054     m_page.send(Messages::WebPageProxy::PageExtendedBackgroundColorDidChange(backgroundColor));
1055 #else
1056     UNUSED_PARAM(backgroundColor);
1057 #endif
1058 }
1059
1060 void WebChromeClient::wheelEventHandlersChanged(bool hasHandlers)
1061 {
1062     m_page.wheelEventHandlersChanged(hasHandlers);
1063 }
1064
1065 String WebChromeClient::plugInStartLabelTitle(const String& mimeType) const
1066 {
1067     return m_page.injectedBundleUIClient().plugInStartLabelTitle(mimeType);
1068 }
1069
1070 String WebChromeClient::plugInStartLabelSubtitle(const String& mimeType) const
1071 {
1072     return m_page.injectedBundleUIClient().plugInStartLabelSubtitle(mimeType);
1073 }
1074
1075 String WebChromeClient::plugInExtraStyleSheet() const
1076 {
1077     return m_page.injectedBundleUIClient().plugInExtraStyleSheet();
1078 }
1079
1080 String WebChromeClient::plugInExtraScript() const
1081 {
1082     return m_page.injectedBundleUIClient().plugInExtraScript();
1083 }
1084
1085 void WebChromeClient::enableSuddenTermination()
1086 {
1087     m_page.send(Messages::WebProcessProxy::EnableSuddenTermination());
1088 }
1089
1090 void WebChromeClient::disableSuddenTermination()
1091 {
1092     m_page.send(Messages::WebProcessProxy::DisableSuddenTermination());
1093 }
1094
1095 void WebChromeClient::didAddHeaderLayer(GraphicsLayer& headerParent)
1096 {
1097 #if ENABLE(RUBBER_BANDING)
1098     if (PageBanner* banner = m_page.headerPageBanner())
1099         banner->didAddParentLayer(&headerParent);
1100 #else
1101     UNUSED_PARAM(headerParent);
1102 #endif
1103 }
1104
1105 void WebChromeClient::didAddFooterLayer(GraphicsLayer& footerParent)
1106 {
1107 #if ENABLE(RUBBER_BANDING)
1108     if (PageBanner* banner = m_page.footerPageBanner())
1109         banner->didAddParentLayer(&footerParent);
1110 #else
1111     UNUSED_PARAM(footerParent);
1112 #endif
1113 }
1114
1115 bool WebChromeClient::shouldUseTiledBackingForFrameView(const FrameView& frameView) const
1116 {
1117     return m_page.drawingArea()->shouldUseTiledBackingForFrameView(frameView);
1118 }
1119
1120 void WebChromeClient::isPlayingMediaDidChange(MediaProducer::MediaStateFlags state, uint64_t sourceElementID)
1121 {
1122     m_page.send(Messages::WebPageProxy::IsPlayingMediaDidChange(state, sourceElementID));
1123 }
1124
1125 void WebChromeClient::handleAutoplayEvent(AutoplayEvent event, OptionSet<AutoplayEventFlags> flags)
1126 {
1127     m_page.send(Messages::WebPageProxy::HandleAutoplayEvent(event, flags));
1128 }
1129
1130 #if ENABLE(MEDIA_SESSION)
1131
1132 void WebChromeClient::hasMediaSessionWithActiveMediaElementsDidChange(bool state)
1133 {
1134     m_page.send(Messages::WebPageProxy::HasMediaSessionWithActiveMediaElementsDidChange(state));
1135 }
1136
1137 void WebChromeClient::mediaSessionMetadataDidChange(const MediaSessionMetadata& metadata)
1138 {
1139     m_page.send(Messages::WebPageProxy::MediaSessionMetadataDidChange(metadata));
1140 }
1141
1142 void WebChromeClient::focusedContentMediaElementDidChange(uint64_t elementID)
1143 {
1144     m_page.send(Messages::WebPageProxy::FocusedContentMediaElementDidChange(elementID));
1145 }
1146
1147 #endif
1148
1149 #if ENABLE(SUBTLE_CRYPTO)
1150
1151 bool WebChromeClient::wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) const
1152 {
1153     bool succeeded;
1154     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::WrapCryptoKey(key), Messages::WebPageProxy::WrapCryptoKey::Reply(succeeded, wrappedKey), m_page.pageID()))
1155         return false;
1156     return succeeded;
1157 }
1158
1159 bool WebChromeClient::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) const
1160 {
1161     bool succeeded;
1162     if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::UnwrapCryptoKey(wrappedKey), Messages::WebPageProxy::UnwrapCryptoKey::Reply(succeeded, key), m_page.pageID()))
1163         return false;
1164     return succeeded;
1165 }
1166
1167 #endif
1168
1169 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(MAC)
1170
1171 void WebChromeClient::handleTelephoneNumberClick(const String& number, const IntPoint& point)
1172 {
1173     m_page.handleTelephoneNumberClick(number, point);
1174 }
1175
1176 #endif
1177
1178 #if ENABLE(SERVICE_CONTROLS)
1179
1180 void WebChromeClient::handleSelectionServiceClick(FrameSelection& selection, const Vector<String>& telephoneNumbers, const IntPoint& point)
1181 {
1182     m_page.handleSelectionServiceClick(selection, telephoneNumbers, point);
1183 }
1184
1185 bool WebChromeClient::hasRelevantSelectionServices(bool isTextOnly) const
1186 {
1187     return (isTextOnly && WebProcess::singleton().hasSelectionServices()) || WebProcess::singleton().hasRichContentServices();
1188 }
1189
1190 #endif
1191
1192 bool WebChromeClient::shouldDispatchFakeMouseMoveEvents() const
1193 {
1194     return m_page.shouldDispatchFakeMouseMoveEvents();
1195 }
1196
1197 void WebChromeClient::handleAutoFillButtonClick(HTMLInputElement& inputElement)
1198 {
1199     RefPtr<API::Object> userData;
1200
1201     // Notify the bundle client.
1202     auto nodeHandle = InjectedBundleNodeHandle::getOrCreate(inputElement);
1203     m_page.injectedBundleUIClient().didClickAutoFillButton(m_page, nodeHandle.get(), userData);
1204
1205     // Notify the UIProcess.
1206     m_page.send(Messages::WebPageProxy::HandleAutoFillButtonClick(UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1207 }
1208
1209 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
1210
1211 void WebChromeClient::addPlaybackTargetPickerClient(uint64_t contextId)
1212 {
1213     m_page.send(Messages::WebPageProxy::AddPlaybackTargetPickerClient(contextId));
1214 }
1215
1216 void WebChromeClient::removePlaybackTargetPickerClient(uint64_t contextId)
1217 {
1218     m_page.send(Messages::WebPageProxy::RemovePlaybackTargetPickerClient(contextId));
1219 }
1220
1221 void WebChromeClient::showPlaybackTargetPicker(uint64_t contextId, const IntPoint& position, bool isVideo)
1222 {
1223     FrameView* frameView = m_page.mainFrame()->view();
1224     FloatRect rect(frameView->contentsToRootView(frameView->windowToContents(position)), FloatSize());
1225     m_page.send(Messages::WebPageProxy::ShowPlaybackTargetPicker(contextId, rect, isVideo));
1226 }
1227
1228 void WebChromeClient::playbackTargetPickerClientStateDidChange(uint64_t contextId, MediaProducer::MediaStateFlags state)
1229 {
1230     m_page.send(Messages::WebPageProxy::PlaybackTargetPickerClientStateDidChange(contextId, state));
1231 }
1232
1233 void WebChromeClient::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
1234 {
1235     m_page.send(Messages::WebPageProxy::SetMockMediaPlaybackTargetPickerEnabled(enabled));
1236 }
1237
1238 void WebChromeClient::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
1239 {
1240     m_page.send(Messages::WebPageProxy::SetMockMediaPlaybackTargetPickerState(name, state));
1241 }
1242
1243 #endif
1244
1245 void WebChromeClient::imageOrMediaDocumentSizeChanged(const IntSize& newSize)
1246 {
1247     m_page.imageOrMediaDocumentSizeChanged(newSize);
1248 }
1249
1250 #if ENABLE(VIDEO) && USE(GSTREAMER)
1251
1252 void WebChromeClient::requestInstallMissingMediaPlugins(const String& details, const String& description, MediaPlayerRequestInstallMissingPluginsCallback& callback)
1253 {
1254     m_page.requestInstallMissingMediaPlugins(details, description, callback);
1255 }
1256
1257 #endif
1258
1259 void WebChromeClient::didInvalidateDocumentMarkerRects()
1260 {
1261     m_page.findController().didInvalidateDocumentMarkerRects();
1262 }
1263
1264 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
1265 void WebChromeClient::hasStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void (bool)>&& callback)
1266 {
1267     m_page.hasStorageAccess(WTFMove(subFrameHost), WTFMove(topFrameHost), frameID, pageID, WTFMove(callback));
1268 }
1269
1270 void WebChromeClient::requestStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void (bool)>&& callback)
1271 {
1272     m_page.requestStorageAccess(WTFMove(subFrameHost), WTFMove(topFrameHost), frameID, pageID, WTFMove(callback));
1273 }
1274 #endif
1275
1276 } // namespace WebKit