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