Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / web / ChromeClientImpl.cpp
blob75d76a9b20d39fa8306b9ddbd9849d641f01dcba
1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "config.h"
33 #include "web/ChromeClientImpl.h"
35 #include "bindings/core/v8/ScriptController.h"
36 #include "core/HTMLNames.h"
37 #include "core/dom/AXObjectCache.h"
38 #include "core/dom/Document.h"
39 #include "core/dom/Fullscreen.h"
40 #include "core/dom/Node.h"
41 #include "core/events/UIEventWithKeyState.h"
42 #include "core/frame/Console.h"
43 #include "core/frame/FrameHost.h"
44 #include "core/frame/FrameView.h"
45 #include "core/frame/Settings.h"
46 #include "core/html/HTMLInputElement.h"
47 #include "core/html/forms/ColorChooser.h"
48 #include "core/html/forms/ColorChooserClient.h"
49 #include "core/html/forms/DateTimeChooser.h"
50 #include "core/layout/HitTestResult.h"
51 #include "core/layout/LayoutPart.h"
52 #include "core/layout/compositing/CompositedSelection.h"
53 #include "core/loader/DocumentLoader.h"
54 #include "core/loader/FrameLoadRequest.h"
55 #include "core/page/Page.h"
56 #include "core/page/PopupOpeningObserver.h"
57 #include "modules/accessibility/AXObject.h"
58 #include "platform/Cursor.h"
59 #include "platform/FileChooser.h"
60 #include "platform/KeyboardCodes.h"
61 #include "platform/RuntimeEnabledFeatures.h"
62 #include "platform/exported/WrappedResourceRequest.h"
63 #include "platform/geometry/IntRect.h"
64 #include "platform/graphics/GraphicsLayer.h"
65 #include "platform/weborigin/SecurityOrigin.h"
66 #include "public/platform/Platform.h"
67 #include "public/platform/WebCursorInfo.h"
68 #include "public/platform/WebRect.h"
69 #include "public/platform/WebURLRequest.h"
70 #include "public/web/WebAXObject.h"
71 #include "public/web/WebAutofillClient.h"
72 #include "public/web/WebColorChooser.h"
73 #include "public/web/WebColorSuggestion.h"
74 #include "public/web/WebConsoleMessage.h"
75 #include "public/web/WebFrameClient.h"
76 #include "public/web/WebInputElement.h"
77 #include "public/web/WebInputEvent.h"
78 #include "public/web/WebKit.h"
79 #include "public/web/WebNode.h"
80 #include "public/web/WebPlugin.h"
81 #include "public/web/WebPopupMenuInfo.h"
82 #include "public/web/WebSelection.h"
83 #include "public/web/WebSettings.h"
84 #include "public/web/WebTextDirection.h"
85 #include "public/web/WebTouchAction.h"
86 #include "public/web/WebUserGestureIndicator.h"
87 #include "public/web/WebUserGestureToken.h"
88 #include "public/web/WebViewClient.h"
89 #include "public/web/WebWindowFeatures.h"
90 #include "web/ColorChooserPopupUIController.h"
91 #include "web/ColorChooserUIController.h"
92 #include "web/DateTimeChooserImpl.h"
93 #include "web/ExternalDateTimeChooser.h"
94 #include "web/ExternalPopupMenu.h"
95 #include "web/PopupMenuImpl.h"
96 #include "web/WebFileChooserCompletionImpl.h"
97 #include "web/WebFrameWidgetImpl.h"
98 #include "web/WebInputEventConversion.h"
99 #include "web/WebLocalFrameImpl.h"
100 #include "web/WebPluginContainerImpl.h"
101 #include "web/WebSettingsImpl.h"
102 #include "web/WebViewImpl.h"
103 #include "wtf/text/CString.h"
104 #include "wtf/text/CharacterNames.h"
105 #include "wtf/text/StringBuilder.h"
106 #include "wtf/text/StringConcatenate.h"
108 namespace blink {
110 class WebCompositorAnimationTimeline;
112 // Converts a AXObjectCache::AXNotification to a WebAXEvent
113 static WebAXEvent toWebAXEvent(AXObjectCache::AXNotification notification)
115 // These enums have the same values; enforced in AssertMatchingEnums.cpp.
116 return static_cast<WebAXEvent>(notification);
119 ChromeClientImpl::ChromeClientImpl(WebViewImpl* webView)
120 : m_webView(webView)
121 , m_cursorOverridden(false)
125 ChromeClientImpl::~ChromeClientImpl()
129 PassOwnPtrWillBeRawPtr<ChromeClientImpl> ChromeClientImpl::create(WebViewImpl* webView)
131 return adoptPtrWillBeNoop(new ChromeClientImpl(webView));
134 void* ChromeClientImpl::webView() const
136 return static_cast<void*>(m_webView);
139 void ChromeClientImpl::chromeDestroyed()
141 // Our lifetime is bound to the WebViewImpl.
144 void ChromeClientImpl::setWindowRect(const IntRect& r)
146 if (m_webView->client())
147 m_webView->client()->setWindowRect(r);
150 IntRect ChromeClientImpl::windowRect()
152 WebRect rect;
153 if (m_webView->client()) {
154 rect = m_webView->client()->rootWindowRect();
155 } else {
156 // These numbers will be fairly wrong. The window's x/y coordinates will
157 // be the top left corner of the screen and the size will be the content
158 // size instead of the window size.
159 rect.width = m_webView->size().width;
160 rect.height = m_webView->size().height;
162 return IntRect(rect);
165 IntRect ChromeClientImpl::pageRect()
167 // We hide the details of the window's border thickness from the web page by
168 // simple re-using the window position here. So, from the point-of-view of
169 // the web page, the window has no border.
170 return windowRect();
173 void ChromeClientImpl::focus()
175 if (m_webView->client())
176 m_webView->client()->didFocus();
179 bool ChromeClientImpl::canTakeFocus(WebFocusType)
181 // For now the browser can always take focus if we're not running layout
182 // tests.
183 return !layoutTestMode();
186 void ChromeClientImpl::takeFocus(WebFocusType type)
188 if (!m_webView->client())
189 return;
190 if (type == WebFocusTypeBackward)
191 m_webView->client()->focusPrevious();
192 else
193 m_webView->client()->focusNext();
196 void ChromeClientImpl::focusedNodeChanged(Node* fromNode, Node* toNode)
198 if (!m_webView->client())
199 return;
201 m_webView->client()->focusedNodeChanged(WebNode(fromNode), WebNode(toNode));
203 WebURL focusURL;
204 if (toNode && toNode->isElementNode() && toElement(toNode)->isLiveLink() && toNode->shouldHaveFocusAppearance())
205 focusURL = toElement(toNode)->hrefURL();
206 m_webView->client()->setKeyboardFocusURL(focusURL);
209 void ChromeClientImpl::focusedFrameChanged(LocalFrame* frame)
211 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
212 if (webframe && webframe->client())
213 webframe->client()->frameFocused();
216 bool ChromeClientImpl::hadFormInteraction() const
218 return m_webView->pageImportanceSignals() && m_webView->pageImportanceSignals()->hadFormInteraction();
221 namespace {
223 void updatePolicyForEvent(const WebInputEvent* inputEvent, NavigationPolicy* policy)
225 if (!inputEvent)
226 return;
228 unsigned short buttonNumber = 0;
229 if (inputEvent->type == WebInputEvent::MouseUp) {
231 const WebMouseEvent* mouseEvent = static_cast<const WebMouseEvent*>(inputEvent);
233 switch (mouseEvent->button) {
234 case WebMouseEvent::ButtonLeft:
235 buttonNumber = 0;
236 break;
237 case WebMouseEvent::ButtonMiddle:
238 buttonNumber = 1;
239 break;
240 case WebMouseEvent::ButtonRight:
241 buttonNumber = 2;
242 break;
243 default:
244 return;
246 } else if ((WebInputEvent::isKeyboardEventType(inputEvent->type) && static_cast<const WebKeyboardEvent*>(inputEvent)->windowsKeyCode == VKEY_RETURN) || WebInputEvent::isGestureEventType(inputEvent->type)) {
247 // Keyboard and gesture events can simulate mouse events.
248 buttonNumber = 0;
249 } else {
250 return;
253 bool ctrl = inputEvent->modifiers & WebInputEvent::ControlKey;
254 bool shift = inputEvent->modifiers & WebInputEvent::ShiftKey;
255 bool alt = inputEvent->modifiers & WebInputEvent::AltKey;
256 bool meta = inputEvent->modifiers & WebInputEvent::MetaKey;
258 NavigationPolicy userPolicy = *policy;
259 navigationPolicyFromMouseEvent(buttonNumber, ctrl, shift, alt, meta, &userPolicy);
261 // When the input event suggests a download, but the navigation was initiated
262 // by script, we should not override it.
263 if (userPolicy == NavigationPolicyDownload && *policy != NavigationPolicyIgnore)
264 return;
266 // User and app agree that we want a new window; let the app override the decorations.
267 if (userPolicy == NavigationPolicyNewWindow && *policy == NavigationPolicyNewPopup)
268 return;
269 *policy = userPolicy;
272 WebNavigationPolicy getNavigationPolicy(const WindowFeatures& features)
274 // If our default configuration was modified by a script or wasn't
275 // created by a user gesture, then show as a popup. Else, let this
276 // new window be opened as a toplevel window.
277 bool asPopup = !features.toolBarVisible
278 || !features.statusBarVisible
279 || !features.scrollbarsVisible
280 || !features.menuBarVisible
281 || !features.resizable;
283 NavigationPolicy policy = NavigationPolicyNewForegroundTab;
284 if (asPopup)
285 policy = NavigationPolicyNewPopup;
286 updatePolicyForEvent(WebViewImpl::currentInputEvent(), &policy);
288 return static_cast<WebNavigationPolicy>(policy);
291 WebNavigationPolicy effectiveNavigationPolicy(NavigationPolicy navigationPolicy, const WindowFeatures& features)
293 WebNavigationPolicy policy = static_cast<WebNavigationPolicy>(navigationPolicy);
294 if (policy == WebNavigationPolicyIgnore)
295 return getNavigationPolicy(features);
296 if (policy == WebNavigationPolicyNewBackgroundTab && getNavigationPolicy(features) != WebNavigationPolicyNewBackgroundTab && !UIEventWithKeyState::newTabModifierSetFromIsolatedWorld())
297 return WebNavigationPolicyNewForegroundTab;
299 return policy;
302 } // namespace
304 Page* ChromeClientImpl::createWindow(LocalFrame* frame, const FrameLoadRequest& r, const WindowFeatures& features,
305 NavigationPolicy navigationPolicy, ShouldSendReferrer shouldSendReferrer)
307 if (!m_webView->client())
308 return nullptr;
310 WebNavigationPolicy policy = effectiveNavigationPolicy(navigationPolicy, features);
311 ASSERT(frame->document());
312 Fullscreen::fullyExitFullscreen(*frame->document());
314 WebViewImpl* newView = toWebViewImpl(
315 m_webView->client()->createView(WebLocalFrameImpl::fromFrame(frame), WrappedResourceRequest(r.resourceRequest()), features, r.frameName(), policy, shouldSendReferrer == NeverSendReferrer));
316 if (!newView)
317 return nullptr;
318 return newView->page();
321 void ChromeClientImpl::didOverscroll(const FloatSize& unusedDelta, const FloatSize& accumulatedRootOverScroll, const FloatPoint& position, const FloatSize& velocity)
323 if (!m_webView->client())
324 return;
326 m_webView->client()->didOverscroll(unusedDelta, accumulatedRootOverScroll, position, velocity);
329 void ChromeClientImpl::show(NavigationPolicy navigationPolicy)
331 if (m_webView->client())
332 m_webView->client()->show(effectiveNavigationPolicy(navigationPolicy, m_windowFeatures));
335 void ChromeClientImpl::setToolbarsVisible(bool value)
337 m_windowFeatures.toolBarVisible = value;
340 bool ChromeClientImpl::toolbarsVisible()
342 return m_windowFeatures.toolBarVisible;
345 void ChromeClientImpl::setStatusbarVisible(bool value)
347 m_windowFeatures.statusBarVisible = value;
350 bool ChromeClientImpl::statusbarVisible()
352 return m_windowFeatures.statusBarVisible;
355 void ChromeClientImpl::setScrollbarsVisible(bool value)
357 m_windowFeatures.scrollbarsVisible = value;
358 if (WebLocalFrameImpl* webFrame = toWebLocalFrameImpl(m_webView->mainFrame()))
359 webFrame->setCanHaveScrollbars(value);
362 bool ChromeClientImpl::scrollbarsVisible()
364 return m_windowFeatures.scrollbarsVisible;
367 void ChromeClientImpl::setMenubarVisible(bool value)
369 m_windowFeatures.menuBarVisible = value;
372 bool ChromeClientImpl::menubarVisible()
374 return m_windowFeatures.menuBarVisible;
377 void ChromeClientImpl::setResizable(bool value)
379 m_windowFeatures.resizable = value;
382 bool ChromeClientImpl::shouldReportDetailedMessageForSource(LocalFrame& localFrame, const String& url)
384 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(localFrame.localFrameRoot());
385 return webframe && webframe->client() && webframe->client()->shouldReportDetailedMessageForSource(url);
388 void ChromeClientImpl::addMessageToConsole(LocalFrame* localFrame, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID, const String& stackTrace)
390 WebLocalFrameImpl* frame = WebLocalFrameImpl::fromFrame(localFrame);
391 if (frame && frame->client()) {
392 frame->client()->didAddMessageToConsole(
393 WebConsoleMessage(static_cast<WebConsoleMessage::Level>(level), message),
394 sourceID,
395 lineNumber,
396 stackTrace);
400 bool ChromeClientImpl::canOpenBeforeUnloadConfirmPanel()
402 return !!m_webView->client();
405 bool ChromeClientImpl::openBeforeUnloadConfirmPanelDelegate(LocalFrame* frame, const String& message)
407 notifyPopupOpeningObservers();
408 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
410 WebDataSource* ds = webframe->provisionalDataSource();
411 bool isReload = ds && (ds->navigationType() == WebNavigationTypeReload);
413 if (webframe->client())
414 return webframe->client()->runModalBeforeUnloadDialog(isReload, message);
415 return false;
418 void ChromeClientImpl::closeWindowSoon()
420 // Make sure this Page can no longer be found by JS.
421 Page::ordinaryPages().remove(m_webView->page());
423 // Make sure that all loading is stopped. Ensures that JS stops executing!
424 m_webView->mainFrame()->stopLoading();
426 if (m_webView->client())
427 m_webView->client()->closeWidgetSoon();
430 // Although a LocalFrame is passed in, we don't actually use it, since we
431 // already know our own m_webView.
432 bool ChromeClientImpl::openJavaScriptAlertDelegate(LocalFrame* frame, const String& message)
434 notifyPopupOpeningObservers();
435 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
436 if (webframe->client()) {
437 if (WebUserGestureIndicator::isProcessingUserGesture())
438 WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt();
439 webframe->client()->runModalAlertDialog(message);
440 return true;
442 return false;
445 // See comments for openJavaScriptAlertDelegate().
446 bool ChromeClientImpl::openJavaScriptConfirmDelegate(LocalFrame* frame, const String& message)
448 notifyPopupOpeningObservers();
449 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
450 if (webframe->client()) {
451 if (WebUserGestureIndicator::isProcessingUserGesture())
452 WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt();
453 return webframe->client()->runModalConfirmDialog(message);
455 return false;
458 // See comments for openJavaScriptAlertDelegate().
459 bool ChromeClientImpl::openJavaScriptPromptDelegate(LocalFrame* frame, const String& message, const String& defaultValue, String& result)
461 notifyPopupOpeningObservers();
462 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
463 if (webframe->client()) {
464 if (WebUserGestureIndicator::isProcessingUserGesture())
465 WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt();
466 WebString actualValue;
467 bool ok = webframe->client()->runModalPromptDialog(message, defaultValue, &actualValue);
468 if (ok)
469 result = actualValue;
470 return ok;
472 return false;
475 void ChromeClientImpl::setStatusbarText(const String& message)
477 if (m_webView->client())
478 m_webView->client()->setStatusText(message);
481 bool ChromeClientImpl::tabsToLinks()
483 return m_webView->tabsToLinks();
486 IntRect ChromeClientImpl::windowResizerRect() const
488 if (m_webView->client())
489 return m_webView->client()->windowResizerRect();
490 return IntRect();
493 void ChromeClientImpl::invalidateRect(const IntRect& updateRect)
495 if (!updateRect.isEmpty())
496 m_webView->invalidateRect(updateRect);
499 void ChromeClientImpl::scheduleAnimation()
501 m_webView->scheduleAnimation();
504 void ChromeClientImpl::scheduleAnimationForFrame(LocalFrame* localRoot)
506 ASSERT(WebLocalFrameImpl::fromFrame(localRoot));
507 // If the frame is still being created, it might not yet have a WebWidget.
508 // FIXME: Is this the right thing to do? Is there a way to avoid having
509 // a local frame root that doesn't have a WebWidget? During initialization
510 // there is no content to draw so this call serves no purpose.
511 if (WebLocalFrameImpl::fromFrame(localRoot)->frameWidget())
512 toWebFrameWidgetImpl(WebLocalFrameImpl::fromFrame(localRoot)->frameWidget())->scheduleAnimation();
515 IntRect ChromeClientImpl::viewportToScreen(const IntRect& rectInViewport) const
517 IntRect screenRect(rectInViewport);
519 if (m_webView->client()) {
520 WebRect windowRect = m_webView->client()->windowRect();
521 screenRect.move(windowRect.x, windowRect.y);
524 return screenRect;
527 WebScreenInfo ChromeClientImpl::screenInfo() const
529 return m_webView->client() ? m_webView->client()->screenInfo() : WebScreenInfo();
532 void ChromeClientImpl::contentsSizeChanged(LocalFrame* frame, const IntSize& size) const
534 m_webView->didChangeContentsSize();
536 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
537 webframe->didChangeContentsSize(size);
540 void ChromeClientImpl::pageScaleFactorChanged() const
542 m_webView->pageScaleFactorChanged();
545 float ChromeClientImpl::clampPageScaleFactorToLimits(float scale) const
547 return m_webView->clampPageScaleFactorToLimits(scale);
550 void ChromeClientImpl::layoutUpdated(LocalFrame* frame) const
552 m_webView->layoutUpdated(WebLocalFrameImpl::fromFrame(frame));
555 void ChromeClientImpl::showMouseOverURL(const HitTestResult& result)
557 if (!m_webView->client())
558 return;
560 WebURL url;
561 // Find out if the mouse is over a link, and if so, let our UI know...
562 if (result.isLiveLink() && !result.absoluteLinkURL().string().isEmpty()) {
563 url = result.absoluteLinkURL();
564 } else if (result.innerNode()
565 && (isHTMLObjectElement(*result.innerNode())
566 || isHTMLEmbedElement(*result.innerNode()))) {
567 LayoutObject* object = result.innerNode()->layoutObject();
568 if (object && object->isLayoutPart()) {
569 Widget* widget = toLayoutPart(object)->widget();
570 if (widget && widget->isPluginContainer()) {
571 WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget);
572 url = plugin->plugin()->linkAtPosition(result.roundedPointInInnerNodeFrame());
577 m_webView->client()->setMouseOverURL(url);
580 void ChromeClientImpl::setToolTip(const String& tooltipText, TextDirection dir)
582 if (m_webView->client())
583 m_webView->client()->setToolTipText(tooltipText, toWebTextDirection(dir));
586 void ChromeClientImpl::dispatchViewportPropertiesDidChange(const ViewportDescription& description) const
588 m_webView->updatePageDefinedViewportConstraints(description);
591 void ChromeClientImpl::printDelegate(LocalFrame* frame)
593 if (m_webView->client())
594 m_webView->client()->printPage(WebLocalFrameImpl::fromFrame(frame));
597 PassOwnPtrWillBeRawPtr<ColorChooser> ChromeClientImpl::openColorChooser(LocalFrame* frame, ColorChooserClient* chooserClient, const Color&)
599 notifyPopupOpeningObservers();
600 OwnPtrWillBeRawPtr<ColorChooserUIController> controller = nullptr;
601 if (RuntimeEnabledFeatures::pagePopupEnabled())
602 controller = ColorChooserPopupUIController::create(frame, this, chooserClient);
603 else
604 controller = ColorChooserUIController::create(frame, chooserClient);
605 controller->openUI();
606 return controller.release();
609 PassRefPtr<DateTimeChooser> ChromeClientImpl::openDateTimeChooser(DateTimeChooserClient* pickerClient, const DateTimeChooserParameters& parameters)
611 notifyPopupOpeningObservers();
612 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
613 return DateTimeChooserImpl::create(this, pickerClient, parameters);
614 #else
615 return ExternalDateTimeChooser::create(this, m_webView->client(), pickerClient, parameters);
616 #endif
619 void ChromeClientImpl::openFileChooser(LocalFrame* frame, PassRefPtr<FileChooser> fileChooser)
621 notifyPopupOpeningObservers();
622 WebViewClient* client = m_webView->client();
623 if (!client)
624 return;
626 WebFileChooserParams params;
627 params.multiSelect = fileChooser->settings().allowsMultipleFiles;
628 params.directory = fileChooser->settings().allowsDirectoryUpload;
629 params.acceptTypes = fileChooser->settings().acceptTypes();
630 params.selectedFiles = fileChooser->settings().selectedFiles;
631 if (params.selectedFiles.size() > 0)
632 params.initialValue = params.selectedFiles[0];
633 params.useMediaCapture = fileChooser->settings().useMediaCapture;
634 params.needLocalPath = fileChooser->settings().allowsDirectoryUpload;
636 WebFileChooserCompletionImpl* chooserCompletion = new WebFileChooserCompletionImpl(fileChooser);
637 if (client->runFileChooser(params, chooserCompletion))
638 return;
639 // Choosing failed, so do callback with an empty list.
640 chooserCompletion->didChooseFile(WebVector<WebString>());
643 void ChromeClientImpl::enumerateChosenDirectory(FileChooser* fileChooser)
645 WebViewClient* client = m_webView->client();
646 if (!client)
647 return;
649 WebFileChooserCompletionImpl* chooserCompletion = new WebFileChooserCompletionImpl(fileChooser);
651 ASSERT(fileChooser);
652 ASSERT(fileChooser->settings().selectedFiles.size());
654 // If the enumeration can't happen, call the callback with an empty list.
655 if (!client->enumerateChosenDirectory(fileChooser->settings().selectedFiles[0], chooserCompletion))
656 chooserCompletion->didChooseFile(WebVector<WebString>());
659 Cursor ChromeClientImpl::lastSetCursorForTesting() const
661 return m_lastSetMouseCursorForTesting;
664 void ChromeClientImpl::setCursor(const Cursor& cursor)
666 m_lastSetMouseCursorForTesting = cursor;
667 setCursor(WebCursorInfo(cursor));
670 void ChromeClientImpl::setCursor(const WebCursorInfo& cursor)
672 if (m_cursorOverridden)
673 return;
675 #if OS(MACOSX)
676 // On Mac the mousemove event propagates to both the popup and main window.
677 // If a popup is open we don't want the main window to change the cursor.
678 if (m_webView->hasOpenedPopup())
679 return;
680 #endif
681 if (m_webView->client())
682 m_webView->client()->didChangeCursor(cursor);
685 void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor)
687 setCursor(cursor);
690 void ChromeClientImpl::setCursorOverridden(bool overridden)
692 m_cursorOverridden = overridden;
695 void ChromeClientImpl::postAccessibilityNotification(AXObject* obj, AXObjectCache::AXNotification notification)
697 // Alert assistive technology about the accessibility object notification.
698 if (!obj || !obj->document())
699 return;
701 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(obj->document()->axObjectCacheOwner().frame());
702 if (webframe && webframe->client())
703 webframe->client()->postAccessibilityEvent(WebAXObject(obj), toWebAXEvent(notification));
706 String ChromeClientImpl::acceptLanguages()
708 return m_webView->client()->acceptLanguages();
711 GraphicsLayerFactory* ChromeClientImpl::graphicsLayerFactory() const
713 return m_webView->graphicsLayerFactory();
716 void ChromeClientImpl::attachRootGraphicsLayer(GraphicsLayer* rootLayer, LocalFrame* localRoot)
718 // FIXME: For top-level frames we still use the WebView as a WebWidget. This
719 // special case will be removed when top-level frames get WebFrameWidgets.
720 if (localRoot->isMainFrame()) {
721 m_webView->setRootGraphicsLayer(rootLayer);
722 } else {
723 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(localRoot);
724 // FIXME: The following conditional is only needed for staging until the
725 // Chromium patch lands that instantiates a WebFrameWidget.
726 if (!webFrame->frameWidget()) {
727 m_webView->setRootGraphicsLayer(rootLayer);
728 return;
730 ASSERT(webFrame);
731 ASSERT(webFrame->frameWidget());
732 toWebFrameWidgetImpl(webFrame->frameWidget())->setRootGraphicsLayer(rootLayer);
736 void ChromeClientImpl::setCompositedDisplayList(PassOwnPtr<CompositedDisplayList> compositedDisplayList)
738 m_webView->setCompositedDisplayList(compositedDisplayList);
741 CompositedDisplayList* ChromeClientImpl::compositedDisplayListForTesting()
743 if (WebCompositedDisplayList* compositedDisplayList = m_webView->compositedDisplayList())
744 return compositedDisplayList->compositedDisplayListForTesting();
745 return nullptr;
748 void ChromeClientImpl::attachCompositorAnimationTimeline(WebCompositorAnimationTimeline* compositorTimeline, LocalFrame* localRoot)
750 // FIXME: For top-level frames we still use the WebView as a WebWidget. This
751 // special case will be removed when top-level frames get WebFrameWidgets.
752 if (localRoot->isMainFrame()) {
753 m_webView->attachCompositorAnimationTimeline(compositorTimeline);
754 } else {
755 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(localRoot);
756 // FIXME: The following conditional is only needed for staging until the
757 // Chromium patch lands that instantiates a WebFrameWidget.
758 if (!webFrame->frameWidget()) {
759 m_webView->attachCompositorAnimationTimeline(compositorTimeline);
760 return;
762 ASSERT(webFrame);
763 ASSERT(webFrame->frameWidget());
764 toWebFrameWidgetImpl(webFrame->frameWidget())->attachCompositorAnimationTimeline(compositorTimeline);
768 void ChromeClientImpl::detachCompositorAnimationTimeline(WebCompositorAnimationTimeline* compositorTimeline, LocalFrame* localRoot)
770 // FIXME: For top-level frames we still use the WebView as a WebWidget. This
771 // special case will be removed when top-level frames get WebFrameWidgets.
772 if (localRoot->isMainFrame()) {
773 m_webView->detachCompositorAnimationTimeline(compositorTimeline);
774 } else {
775 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(localRoot);
776 // FIXME: The following conditional is only needed for staging until the
777 // Chromium patch lands that instantiates a WebFrameWidget.
778 if (!webFrame->frameWidget()) {
779 m_webView->detachCompositorAnimationTimeline(compositorTimeline);
780 return;
782 ASSERT(webFrame);
783 ASSERT(webFrame->frameWidget());
784 toWebFrameWidgetImpl(webFrame->frameWidget())->detachCompositorAnimationTimeline(compositorTimeline);
788 void ChromeClientImpl::enterFullScreenForElement(Element* element)
790 m_webView->enterFullScreenForElement(element);
793 void ChromeClientImpl::exitFullScreenForElement(Element* element)
795 m_webView->exitFullScreenForElement(element);
798 void ChromeClientImpl::clearCompositedSelection()
800 m_webView->clearCompositedSelection();
803 void ChromeClientImpl::updateCompositedSelection(const CompositedSelection& selection)
805 m_webView->updateCompositedSelection(WebSelection(selection));
808 bool ChromeClientImpl::hasOpenedPopup() const
810 return m_webView->hasOpenedPopup();
813 PassRefPtrWillBeRawPtr<PopupMenu> ChromeClientImpl::openPopupMenu(LocalFrame& frame, HTMLSelectElement& select)
815 notifyPopupOpeningObservers();
816 if (WebViewImpl::useExternalPopupMenus())
817 return adoptRefWillBeNoop(new ExternalPopupMenu(frame, select, *m_webView));
819 ASSERT(RuntimeEnabledFeatures::pagePopupEnabled());
820 return PopupMenuImpl::create(this, select);
823 PagePopup* ChromeClientImpl::openPagePopup(PagePopupClient* client)
825 return m_webView->openPagePopup(client);
828 void ChromeClientImpl::closePagePopup(PagePopup* popup)
830 m_webView->closePagePopup(popup);
833 DOMWindow* ChromeClientImpl::pagePopupWindowForTesting() const
835 return m_webView->pagePopupWindow();
838 bool ChromeClientImpl::shouldOpenModalDialogDuringPageDismissal(const DialogType& dialogType, const String& dialogMessage, Document::PageDismissalType dismissalType) const
840 const char* kDialogs[] = {"alert", "confirm", "prompt"};
841 int dialog = static_cast<int>(dialogType);
842 ASSERT_WITH_SECURITY_IMPLICATION(0 <= dialog);
843 ASSERT_WITH_SECURITY_IMPLICATION(dialog < static_cast<int>(arraysize(kDialogs)));
845 const char* kDismissals[] = {"beforeunload", "pagehide", "unload"};
846 int dismissal = static_cast<int>(dismissalType) - 1; // Exclude NoDismissal.
847 ASSERT_WITH_SECURITY_IMPLICATION(0 <= dismissal);
848 ASSERT_WITH_SECURITY_IMPLICATION(dismissal < static_cast<int>(arraysize(kDismissals)));
850 Platform::current()->histogramEnumeration("Renderer.ModalDialogsDuringPageDismissal", dismissal * arraysize(kDialogs) + dialog, arraysize(kDialogs) * arraysize(kDismissals));
852 String message = String("Blocked ") + kDialogs[dialog] + "('" + dialogMessage + "') during " + kDismissals[dismissal] + ".";
853 m_webView->mainFrame()->addMessageToConsole(WebConsoleMessage(WebConsoleMessage::LevelError, message));
855 return false;
858 void ChromeClientImpl::needTouchEvents(bool needsTouchEvents)
860 m_webView->hasTouchEventHandlers(needsTouchEvents);
863 void ChromeClientImpl::setTouchAction(TouchAction touchAction)
865 if (WebViewClient* client = m_webView->client())
866 client->setTouchAction(static_cast<WebTouchAction>(touchAction));
869 bool ChromeClientImpl::requestPointerLock()
871 return m_webView->requestPointerLock();
874 void ChromeClientImpl::requestPointerUnlock()
876 return m_webView->requestPointerUnlock();
879 void ChromeClientImpl::annotatedRegionsChanged()
881 if (WebViewClient* client = m_webView->client())
882 client->draggableRegionsChanged();
885 void ChromeClientImpl::didAssociateFormControls(const WillBeHeapVector<RefPtrWillBeMember<Element>>& elements, LocalFrame* frame)
887 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
888 if (webframe->autofillClient())
889 webframe->autofillClient()->didAssociateFormControls(elements);
892 void ChromeClientImpl::didCancelCompositionOnSelectionChange()
894 if (m_webView->client())
895 m_webView->client()->didCancelCompositionOnSelectionChange();
898 void ChromeClientImpl::willSetInputMethodState()
900 if (m_webView->client())
901 m_webView->client()->resetInputMethod();
904 void ChromeClientImpl::didUpdateTextOfFocusedElementByNonUserInput()
906 if (m_webView->client())
907 m_webView->client()->didUpdateTextOfFocusedElementByNonUserInput();
910 void ChromeClientImpl::showImeIfNeeded()
912 if (m_webView->client())
913 m_webView->client()->showImeIfNeeded();
916 void ChromeClientImpl::showUnhandledTapUIIfNeeded(IntPoint tappedPositionInViewport, Node* tappedNode, bool pageChanged)
918 if (m_webView->client())
919 m_webView->client()->showUnhandledTapUIIfNeeded(WebPoint(tappedPositionInViewport), WebNode(tappedNode), pageChanged);
922 void ChromeClientImpl::onMouseDown(Node* mouseDownNode)
924 if (m_webView->client())
925 m_webView->client()->onMouseDown(WebNode(mouseDownNode));
928 void ChromeClientImpl::handleKeyboardEventOnTextField(HTMLInputElement& inputElement, KeyboardEvent& event)
930 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(inputElement.document().frame());
931 if (webframe->autofillClient())
932 webframe->autofillClient()->textFieldDidReceiveKeyDown(WebInputElement(&inputElement), WebKeyboardEventBuilder(event));
935 void ChromeClientImpl::didChangeValueInTextField(HTMLFormControlElement& element)
937 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(element.document().frame());
938 if (webframe->autofillClient())
939 webframe->autofillClient()->textFieldDidChange(WebFormControlElement(&element));
941 m_webView->pageImportanceSignals()->setHadFormInteraction();
944 void ChromeClientImpl::didEndEditingOnTextField(HTMLInputElement& inputElement)
946 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(inputElement.document().frame());
947 if (webframe->autofillClient())
948 webframe->autofillClient()->textFieldDidEndEditing(WebInputElement(&inputElement));
951 void ChromeClientImpl::openTextDataListChooser(HTMLInputElement& input)
953 notifyPopupOpeningObservers();
954 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(input.document().frame());
955 if (webframe->autofillClient())
956 webframe->autofillClient()->openTextDataListChooser(WebInputElement(&input));
959 void ChromeClientImpl::textFieldDataListChanged(HTMLInputElement& input)
961 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(input.document().frame());
962 if (webframe->autofillClient())
963 webframe->autofillClient()->dataListOptionsChanged(WebInputElement(&input));
966 void ChromeClientImpl::ajaxSucceeded(LocalFrame* frame)
968 WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
969 if (webframe->autofillClient())
970 webframe->autofillClient()->ajaxSucceeded();
973 void ChromeClientImpl::registerViewportLayers() const
975 if (m_webView->rootGraphicsLayer() && m_webView->layerTreeView())
976 m_webView->page()->frameHost().visualViewport().registerLayersWithTreeView(m_webView->layerTreeView());
979 void ChromeClientImpl::didUpdateTopControls() const
981 m_webView->didUpdateTopControls();
984 void ChromeClientImpl::registerPopupOpeningObserver(PopupOpeningObserver* observer)
986 ASSERT(observer);
987 m_popupOpeningObservers.append(observer);
990 void ChromeClientImpl::unregisterPopupOpeningObserver(PopupOpeningObserver* observer)
992 size_t index = m_popupOpeningObservers.find(observer);
993 ASSERT(index != kNotFound);
994 m_popupOpeningObservers.remove(index);
997 void ChromeClientImpl::notifyPopupOpeningObservers() const
999 const Vector<PopupOpeningObserver*> observers(m_popupOpeningObservers);
1000 for (const auto& observer : observers)
1001 observer->willOpenPopup();
1004 FloatSize ChromeClientImpl::elasticOverscroll() const
1006 return m_webView->elasticOverscroll();
1009 } // namespace blink