Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / ChromeClientImpl.cpp
1 /*
2  * Copyright (C) 2009 Google 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 are
7  * met:
8  *
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.
18  *
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.
30  */
31
32 #include "config.h"
33 #include "web/ChromeClientImpl.h"
34
35 #include "bindings/core/v8/ScriptController.h"
36 #include "core/HTMLNames.h"
37 #include "core/accessibility/AXObject.h"
38 #include "core/accessibility/AXObjectCache.h"
39 #include "core/dom/Document.h"
40 #include "core/dom/Fullscreen.h"
41 #include "core/dom/Node.h"
42 #include "core/events/KeyboardEvent.h"
43 #include "core/events/MouseEvent.h"
44 #include "core/events/WheelEvent.h"
45 #include "core/frame/Console.h"
46 #include "core/frame/FrameView.h"
47 #include "core/frame/Settings.h"
48 #include "core/html/HTMLInputElement.h"
49 #include "core/html/forms/ColorChooser.h"
50 #include "core/html/forms/ColorChooserClient.h"
51 #include "core/html/forms/DateTimeChooser.h"
52 #include "core/loader/DocumentLoader.h"
53 #include "core/loader/FrameLoadRequest.h"
54 #include "core/page/Page.h"
55 #include "core/page/PagePopupDriver.h"
56 #include "core/page/WindowFeatures.h"
57 #include "core/rendering/HitTestResult.h"
58 #include "core/rendering/RenderPart.h"
59 #include "core/rendering/RenderWidget.h"
60 #include "core/rendering/compositing/CompositedSelectionBound.h"
61 #include "platform/Cursor.h"
62 #include "platform/FileChooser.h"
63 #include "platform/NotImplemented.h"
64 #include "platform/PlatformScreen.h"
65 #include "platform/RuntimeEnabledFeatures.h"
66 #include "platform/exported/WrappedResourceRequest.h"
67 #include "platform/geometry/FloatRect.h"
68 #include "platform/geometry/IntRect.h"
69 #include "platform/graphics/GraphicsLayer.h"
70 #include "platform/weborigin/SecurityOrigin.h"
71 #include "public/platform/Platform.h"
72 #include "public/platform/WebCursorInfo.h"
73 #include "public/platform/WebRect.h"
74 #include "public/platform/WebSelectionBound.h"
75 #include "public/platform/WebURLRequest.h"
76 #include "public/web/WebAXObject.h"
77 #include "public/web/WebAutofillClient.h"
78 #include "public/web/WebColorChooser.h"
79 #include "public/web/WebColorSuggestion.h"
80 #include "public/web/WebConsoleMessage.h"
81 #include "public/web/WebFrameClient.h"
82 #include "public/web/WebInputElement.h"
83 #include "public/web/WebInputEvent.h"
84 #include "public/web/WebKit.h"
85 #include "public/web/WebNode.h"
86 #include "public/web/WebPlugin.h"
87 #include "public/web/WebPopupMenuInfo.h"
88 #include "public/web/WebSettings.h"
89 #include "public/web/WebTextDirection.h"
90 #include "public/web/WebTouchAction.h"
91 #include "public/web/WebUserGestureIndicator.h"
92 #include "public/web/WebUserGestureToken.h"
93 #include "public/web/WebViewClient.h"
94 #include "public/web/WebWindowFeatures.h"
95 #include "web/ColorChooserPopupUIController.h"
96 #include "web/ColorChooserUIController.h"
97 #include "web/DateTimeChooserImpl.h"
98 #include "web/ExternalDateTimeChooser.h"
99 #include "web/ExternalPopupMenu.h"
100 #include "web/PopupMenuChromium.h"
101 #include "web/WebFileChooserCompletionImpl.h"
102 #include "web/WebInputEventConversion.h"
103 #include "web/WebLocalFrameImpl.h"
104 #include "web/WebPluginContainerImpl.h"
105 #include "web/WebPopupMenuImpl.h"
106 #include "web/WebSettingsImpl.h"
107 #include "web/WebViewImpl.h"
108 #include "wtf/text/CString.h"
109 #include "wtf/text/StringBuilder.h"
110 #include "wtf/text/StringConcatenate.h"
111 #include "wtf/unicode/CharacterNames.h"
112
113 namespace blink {
114
115 // Converts a AXObjectCache::AXNotification to a WebAXEvent
116 static WebAXEvent toWebAXEvent(AXObjectCache::AXNotification notification)
117 {
118     // These enums have the same values; enforced in AssertMatchingEnums.cpp.
119     return static_cast<WebAXEvent>(notification);
120 }
121
122 static WebSelectionBound toWebSelectionBound(const CompositedSelectionBound& bound)
123 {
124     ASSERT(bound.layer);
125
126     // These enums have the same values; enforced in AssertMatchingEnums.cpp.
127     WebSelectionBound result(static_cast<WebSelectionBound::Type>(bound.type));
128     result.layerId = bound.layer->platformLayer()->id();
129     result.edgeTopInLayer = roundedIntPoint(bound.edgeTopInLayer);
130     result.edgeBottomInLayer = roundedIntPoint(bound.edgeBottomInLayer);
131     return result;
132 }
133
134 ChromeClientImpl::ChromeClientImpl(WebViewImpl* webView)
135     : m_webView(webView)
136     , m_toolbarsVisible(true)
137     , m_statusbarVisible(true)
138     , m_scrollbarsVisible(true)
139     , m_menubarVisible(true)
140     , m_resizable(true)
141     , m_pagePopupDriver(webView)
142 {
143 }
144
145 ChromeClientImpl::~ChromeClientImpl()
146 {
147 }
148
149 void* ChromeClientImpl::webView() const
150 {
151     return static_cast<void*>(m_webView);
152 }
153
154 void ChromeClientImpl::chromeDestroyed()
155 {
156     // Our lifetime is bound to the WebViewImpl.
157 }
158
159 void ChromeClientImpl::setWindowRect(const FloatRect& r)
160 {
161     if (m_webView->client())
162         m_webView->client()->setWindowRect(IntRect(r));
163 }
164
165 FloatRect ChromeClientImpl::windowRect()
166 {
167     WebRect rect;
168     if (m_webView->client())
169         rect = m_webView->client()->rootWindowRect();
170     else {
171         // These numbers will be fairly wrong. The window's x/y coordinates will
172         // be the top left corner of the screen and the size will be the content
173         // size instead of the window size.
174         rect.width = m_webView->size().width;
175         rect.height = m_webView->size().height;
176     }
177     return FloatRect(rect);
178 }
179
180 FloatRect ChromeClientImpl::pageRect()
181 {
182     // We hide the details of the window's border thickness from the web page by
183     // simple re-using the window position here.  So, from the point-of-view of
184     // the web page, the window has no border.
185     return windowRect();
186 }
187
188 void ChromeClientImpl::focus()
189 {
190     if (m_webView->client())
191         m_webView->client()->didFocus();
192 }
193
194 bool ChromeClientImpl::canTakeFocus(FocusType)
195 {
196     // For now the browser can always take focus if we're not running layout
197     // tests.
198     return !layoutTestMode();
199 }
200
201 void ChromeClientImpl::takeFocus(FocusType type)
202 {
203     if (!m_webView->client())
204         return;
205     if (type == FocusTypeBackward)
206         m_webView->client()->focusPrevious();
207     else
208         m_webView->client()->focusNext();
209 }
210
211 void ChromeClientImpl::focusedNodeChanged(Node* node)
212 {
213     m_webView->client()->focusedNodeChanged(WebNode(node));
214
215     WebURL focusURL;
216     if (node && node->isElementNode() && toElement(node)->isLiveLink())
217         focusURL = toElement(node)->hrefURL();
218     m_webView->client()->setKeyboardFocusURL(focusURL);
219 }
220
221 void ChromeClientImpl::focusedFrameChanged(LocalFrame* frame)
222 {
223     WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
224     if (webframe && webframe->client())
225         webframe->client()->frameFocused();
226 }
227
228 Page* ChromeClientImpl::createWindow(LocalFrame* frame, const FrameLoadRequest& r, const WindowFeatures& features,
229     NavigationPolicy navigationPolicy, ShouldSendReferrer shouldSendReferrer)
230 {
231     if (!m_webView->client())
232         return 0;
233
234     WebNavigationPolicy policy = static_cast<WebNavigationPolicy>(navigationPolicy);
235     if (policy == WebNavigationPolicyIgnore)
236         policy = getNavigationPolicy();
237
238     ASSERT(frame->document());
239     Fullscreen::fullyExitFullscreen(*frame->document());
240
241     WebViewImpl* newView = toWebViewImpl(
242         m_webView->client()->createView(WebLocalFrameImpl::fromFrame(frame), WrappedResourceRequest(r.resourceRequest()), features, r.frameName(), policy, shouldSendReferrer == NeverSendReferrer));
243     if (!newView)
244         return 0;
245     return newView->page();
246 }
247
248 static inline void updatePolicyForEvent(const WebInputEvent* inputEvent, NavigationPolicy* policy)
249 {
250     if (!inputEvent || inputEvent->type != WebInputEvent::MouseUp)
251         return;
252
253     const WebMouseEvent* mouseEvent = static_cast<const WebMouseEvent*>(inputEvent);
254
255     unsigned short buttonNumber;
256     switch (mouseEvent->button) {
257     case WebMouseEvent::ButtonLeft:
258         buttonNumber = 0;
259         break;
260     case WebMouseEvent::ButtonMiddle:
261         buttonNumber = 1;
262         break;
263     case WebMouseEvent::ButtonRight:
264         buttonNumber = 2;
265         break;
266     default:
267         return;
268     }
269     bool ctrl = mouseEvent->modifiers & WebMouseEvent::ControlKey;
270     bool shift = mouseEvent->modifiers & WebMouseEvent::ShiftKey;
271     bool alt = mouseEvent->modifiers & WebMouseEvent::AltKey;
272     bool meta = mouseEvent->modifiers & WebMouseEvent::MetaKey;
273
274     NavigationPolicy userPolicy = *policy;
275     navigationPolicyFromMouseEvent(buttonNumber, ctrl, shift, alt, meta, &userPolicy);
276     // User and app agree that we want a new window; let the app override the decorations.
277     if (userPolicy == NavigationPolicyNewWindow && *policy == NavigationPolicyNewPopup)
278         return;
279     *policy = userPolicy;
280 }
281
282 WebNavigationPolicy ChromeClientImpl::getNavigationPolicy()
283 {
284     // If our default configuration was modified by a script or wasn't
285     // created by a user gesture, then show as a popup. Else, let this
286     // new window be opened as a toplevel window.
287     bool asPopup = !m_toolbarsVisible
288         || !m_statusbarVisible
289         || !m_scrollbarsVisible
290         || !m_menubarVisible
291         || !m_resizable;
292
293     NavigationPolicy policy = NavigationPolicyNewForegroundTab;
294     if (asPopup)
295         policy = NavigationPolicyNewPopup;
296     updatePolicyForEvent(WebViewImpl::currentInputEvent(), &policy);
297
298     return static_cast<WebNavigationPolicy>(policy);
299 }
300
301 void ChromeClientImpl::show(NavigationPolicy navigationPolicy)
302 {
303     if (!m_webView->client())
304         return;
305
306     WebNavigationPolicy policy = static_cast<WebNavigationPolicy>(navigationPolicy);
307     if (policy == WebNavigationPolicyIgnore)
308         policy = getNavigationPolicy();
309     m_webView->client()->show(policy);
310 }
311
312 bool ChromeClientImpl::canRunModal()
313 {
314     return !!m_webView->client();
315 }
316
317 void ChromeClientImpl::runModal()
318 {
319     if (m_webView->client())
320         m_webView->client()->runModal();
321 }
322
323 void ChromeClientImpl::setToolbarsVisible(bool value)
324 {
325     m_toolbarsVisible = value;
326 }
327
328 bool ChromeClientImpl::toolbarsVisible()
329 {
330     return m_toolbarsVisible;
331 }
332
333 void ChromeClientImpl::setStatusbarVisible(bool value)
334 {
335     m_statusbarVisible = value;
336 }
337
338 bool ChromeClientImpl::statusbarVisible()
339 {
340     return m_statusbarVisible;
341 }
342
343 void ChromeClientImpl::setScrollbarsVisible(bool value)
344 {
345     m_scrollbarsVisible = value;
346     WebLocalFrameImpl* webFrame = toWebLocalFrameImpl(m_webView->mainFrame());
347     if (webFrame)
348         webFrame->setCanHaveScrollbars(value);
349 }
350
351 bool ChromeClientImpl::scrollbarsVisible()
352 {
353     return m_scrollbarsVisible;
354 }
355
356 void ChromeClientImpl::setMenubarVisible(bool value)
357 {
358     m_menubarVisible = value;
359 }
360
361 bool ChromeClientImpl::menubarVisible()
362 {
363     return m_menubarVisible;
364 }
365
366 void ChromeClientImpl::setResizable(bool value)
367 {
368     m_resizable = value;
369 }
370
371 bool ChromeClientImpl::shouldReportDetailedMessageForSource(const String& url)
372 {
373     WebLocalFrameImpl* webframe = m_webView->localFrameRootTemporary();
374     return webframe->client() && webframe->client()->shouldReportDetailedMessageForSource(url);
375 }
376
377 void ChromeClientImpl::addMessageToConsole(LocalFrame* localFrame, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID, const String& stackTrace)
378 {
379     WebLocalFrameImpl* frame = WebLocalFrameImpl::fromFrame(localFrame);
380     if (frame && frame->client()) {
381         frame->client()->didAddMessageToConsole(
382             WebConsoleMessage(static_cast<WebConsoleMessage::Level>(level), message),
383             sourceID,
384             lineNumber,
385             stackTrace);
386     }
387 }
388
389 bool ChromeClientImpl::canRunBeforeUnloadConfirmPanel()
390 {
391     return !!m_webView->client();
392 }
393
394 bool ChromeClientImpl::runBeforeUnloadConfirmPanel(const String& message, LocalFrame* frame)
395 {
396     WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
397
398     bool isReload = false;
399     WebDataSource* ds = webframe->provisionalDataSource();
400     if (ds)
401         isReload = (ds->navigationType() == WebNavigationTypeReload);
402
403     if (webframe->client())
404         return webframe->client()->runModalBeforeUnloadDialog(isReload, message);
405     return false;
406 }
407
408 void ChromeClientImpl::closeWindowSoon()
409 {
410     // Make sure this Page can no longer be found by JS.
411     Page::ordinaryPages().remove(m_webView->page());
412
413     // Make sure that all loading is stopped.  Ensures that JS stops executing!
414     m_webView->mainFrame()->stopLoading();
415
416     if (m_webView->client())
417         m_webView->client()->closeWidgetSoon();
418 }
419
420 // Although a LocalFrame is passed in, we don't actually use it, since we
421 // already know our own m_webView.
422 void ChromeClientImpl::runJavaScriptAlert(LocalFrame* frame, const String& message)
423 {
424     WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
425     if (webframe->client()) {
426         if (WebUserGestureIndicator::isProcessingUserGesture())
427             WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt();
428         webframe->client()->runModalAlertDialog(message);
429     }
430 }
431
432 // See comments for runJavaScriptAlert().
433 bool ChromeClientImpl::runJavaScriptConfirm(LocalFrame* frame, const String& message)
434 {
435     WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
436     if (webframe->client()) {
437         if (WebUserGestureIndicator::isProcessingUserGesture())
438             WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt();
439         return webframe->client()->runModalConfirmDialog(message);
440     }
441     return false;
442 }
443
444 // See comments for runJavaScriptAlert().
445 bool ChromeClientImpl::runJavaScriptPrompt(LocalFrame* frame,
446                                            const String& message,
447                                            const String& defaultValue,
448                                            String& result)
449 {
450     WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
451     if (webframe->client()) {
452         if (WebUserGestureIndicator::isProcessingUserGesture())
453             WebUserGestureIndicator::currentUserGestureToken().setJavascriptPrompt();
454         WebString actualValue;
455         bool ok = webframe->client()->runModalPromptDialog(
456             message,
457             defaultValue,
458             &actualValue);
459         if (ok)
460             result = actualValue;
461         return ok;
462     }
463     return false;
464 }
465
466 void ChromeClientImpl::setStatusbarText(const String& message)
467 {
468     if (m_webView->client())
469         m_webView->client()->setStatusText(message);
470 }
471
472 bool ChromeClientImpl::tabsToLinks()
473 {
474     return m_webView->tabsToLinks();
475 }
476
477 IntRect ChromeClientImpl::windowResizerRect() const
478 {
479     IntRect result;
480     if (m_webView->client())
481         result = m_webView->client()->windowResizerRect();
482     return result;
483 }
484
485 void ChromeClientImpl::invalidateContentsAndRootView(const IntRect& updateRect)
486 {
487     if (updateRect.isEmpty())
488         return;
489     m_webView->invalidateRect(updateRect);
490 }
491
492 void ChromeClientImpl::invalidateContentsForSlowScroll(const IntRect& updateRect)
493 {
494     invalidateContentsAndRootView(updateRect);
495 }
496
497 void ChromeClientImpl::scheduleAnimation()
498 {
499     m_webView->scheduleAnimation();
500 }
501
502 IntRect ChromeClientImpl::rootViewToScreen(const IntRect& rect) const
503 {
504     IntRect screenRect(rect);
505
506     if (m_webView->client()) {
507         WebRect windowRect = m_webView->client()->windowRect();
508         screenRect.move(windowRect.x, windowRect.y);
509     }
510
511     return screenRect;
512 }
513
514 WebScreenInfo ChromeClientImpl::screenInfo() const
515 {
516     return m_webView->client() ? m_webView->client()->screenInfo() : WebScreenInfo();
517 }
518
519 void ChromeClientImpl::contentsSizeChanged(LocalFrame* frame, const IntSize& size) const
520 {
521     m_webView->didChangeContentsSize();
522
523     WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(frame);
524     webframe->didChangeContentsSize(size);
525
526     frame->loader().restoreScrollPositionAndViewState();
527 }
528
529 void ChromeClientImpl::deviceOrPageScaleFactorChanged() const
530 {
531     m_webView->deviceOrPageScaleFactorChanged();
532 }
533
534 void ChromeClientImpl::layoutUpdated(LocalFrame* frame) const
535 {
536     m_webView->layoutUpdated(WebLocalFrameImpl::fromFrame(frame));
537 }
538
539 void ChromeClientImpl::mouseDidMoveOverElement(
540     const HitTestResult& result, unsigned modifierFlags)
541 {
542     if (!m_webView->client())
543         return;
544
545     WebURL url;
546     // Find out if the mouse is over a link, and if so, let our UI know...
547     if (result.isLiveLink() && !result.absoluteLinkURL().string().isEmpty()) {
548         url = result.absoluteLinkURL();
549     } else if (result.innerNonSharedNode()
550         && (isHTMLObjectElement(*result.innerNonSharedNode())
551             || isHTMLEmbedElement(*result.innerNonSharedNode()))) {
552         RenderObject* object = result.innerNonSharedNode()->renderer();
553         if (object && object->isWidget()) {
554             Widget* widget = toRenderWidget(object)->widget();
555             if (widget && widget->isPluginContainer()) {
556                 WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget);
557                 url = plugin->plugin()->linkAtPosition(result.roundedPointInInnerNodeFrame());
558             }
559         }
560     }
561
562     m_webView->client()->setMouseOverURL(url);
563 }
564
565 void ChromeClientImpl::setToolTip(const String& tooltipText, TextDirection dir)
566 {
567     if (m_webView->client())
568         m_webView->client()->setToolTipText(tooltipText, toWebTextDirection(dir));
569 }
570
571 void ChromeClientImpl::dispatchViewportPropertiesDidChange(const ViewportDescription& description) const
572 {
573     m_webView->updatePageDefinedViewportConstraints(description);
574 }
575
576 void ChromeClientImpl::print(LocalFrame* frame)
577 {
578     if (m_webView->client())
579         m_webView->client()->printPage(WebLocalFrameImpl::fromFrame(frame));
580 }
581
582 PassOwnPtr<ColorChooser> ChromeClientImpl::createColorChooser(LocalFrame* frame, ColorChooserClient* chooserClient, const Color&)
583 {
584     OwnPtr<ColorChooserUIController> controller;
585     if (RuntimeEnabledFeatures::pagePopupEnabled())
586         controller = adoptPtr(new ColorChooserPopupUIController(frame, this, chooserClient));
587     else
588         controller = adoptPtr(new ColorChooserUIController(frame, chooserClient));
589     controller->openUI();
590     return controller.release();
591 }
592
593 PassRefPtr<DateTimeChooser> ChromeClientImpl::openDateTimeChooser(DateTimeChooserClient* pickerClient, const DateTimeChooserParameters& parameters)
594 {
595 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
596     return DateTimeChooserImpl::create(this, pickerClient, parameters);
597 #else
598     return ExternalDateTimeChooser::create(this, m_webView->client(), pickerClient, parameters);
599 #endif
600 }
601
602 void ChromeClientImpl::runOpenPanel(LocalFrame* frame, PassRefPtr<FileChooser> fileChooser)
603 {
604     WebViewClient* client = m_webView->client();
605     if (!client)
606         return;
607
608     WebFileChooserParams params;
609     params.multiSelect = fileChooser->settings().allowsMultipleFiles;
610     params.directory = fileChooser->settings().allowsDirectoryUpload;
611     params.acceptTypes = fileChooser->settings().acceptTypes();
612     params.selectedFiles = fileChooser->settings().selectedFiles;
613     if (params.selectedFiles.size() > 0)
614         params.initialValue = params.selectedFiles[0];
615     params.useMediaCapture = fileChooser->settings().useMediaCapture;
616
617     WebFileChooserCompletionImpl* chooserCompletion =
618         new WebFileChooserCompletionImpl(fileChooser);
619
620     if (client->runFileChooser(params, chooserCompletion))
621         return;
622
623     // Choosing failed, so do callback with an empty list.
624     chooserCompletion->didChooseFile(WebVector<WebString>());
625 }
626
627 void ChromeClientImpl::enumerateChosenDirectory(FileChooser* fileChooser)
628 {
629     WebViewClient* client = m_webView->client();
630     if (!client)
631         return;
632
633     WebFileChooserCompletionImpl* chooserCompletion =
634         new WebFileChooserCompletionImpl(fileChooser);
635
636     ASSERT(fileChooser && fileChooser->settings().selectedFiles.size());
637
638     // If the enumeration can't happen, call the callback with an empty list.
639     if (!client->enumerateChosenDirectory(fileChooser->settings().selectedFiles[0], chooserCompletion))
640         chooserCompletion->didChooseFile(WebVector<WebString>());
641 }
642
643 void ChromeClientImpl::setCursor(const Cursor& cursor)
644 {
645     setCursor(WebCursorInfo(cursor));
646 }
647
648 void ChromeClientImpl::setCursor(const WebCursorInfo& cursor)
649 {
650 #if OS(MACOSX)
651     // On Mac the mousemove event propagates to both the popup and main window.
652     // If a popup is open we don't want the main window to change the cursor.
653     if (m_webView->hasOpenedPopup())
654         return;
655 #endif
656     if (m_webView->client())
657         m_webView->client()->didChangeCursor(cursor);
658 }
659
660 void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor)
661 {
662     setCursor(cursor);
663 }
664
665 void ChromeClientImpl::postAccessibilityNotification(AXObject* obj, AXObjectCache::AXNotification notification)
666 {
667     // Alert assistive technology about the accessibility object notification.
668     if (!obj || !obj->documentFrameView())
669         return;
670
671     WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(obj->documentFrameView()->frame());
672     if (webframe && webframe->client())
673         webframe->client()->postAccessibilityEvent(WebAXObject(obj), toWebAXEvent(notification));
674
675     // FIXME: delete these lines once Chrome only uses the frame client interface, above.
676     if (m_webView->client())
677         m_webView->client()->postAccessibilityEvent(WebAXObject(obj), toWebAXEvent(notification));
678 }
679
680 String ChromeClientImpl::acceptLanguages()
681 {
682     return m_webView->client()->acceptLanguages();
683 }
684
685 bool ChromeClientImpl::paintCustomOverhangArea(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
686 {
687     LocalFrame* frame = m_webView->mainFrameImpl()->frame();
688     WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
689     if (pluginContainer)
690         return pluginContainer->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
691     return false;
692 }
693
694 GraphicsLayerFactory* ChromeClientImpl::graphicsLayerFactory() const
695 {
696     return m_webView->graphicsLayerFactory();
697 }
698
699 void ChromeClientImpl::attachRootGraphicsLayer(GraphicsLayer* rootLayer)
700 {
701     m_webView->setRootGraphicsLayer(rootLayer);
702 }
703
704 void ChromeClientImpl::enterFullScreenForElement(Element* element)
705 {
706     m_webView->enterFullScreenForElement(element);
707 }
708
709 void ChromeClientImpl::exitFullScreenForElement(Element* element)
710 {
711     m_webView->exitFullScreenForElement(element);
712 }
713
714 void ChromeClientImpl::clearCompositedSelectionBounds()
715 {
716     m_webView->clearCompositedSelectionBounds();
717 }
718
719 void ChromeClientImpl::updateCompositedSelectionBounds(const CompositedSelectionBound& anchor, const CompositedSelectionBound& focus)
720 {
721     m_webView->updateCompositedSelectionBounds(toWebSelectionBound(anchor), toWebSelectionBound(focus));
722 }
723
724 bool ChromeClientImpl::hasOpenedPopup() const
725 {
726     return m_webView->hasOpenedPopup();
727 }
728
729 PassRefPtrWillBeRawPtr<PopupMenu> ChromeClientImpl::createPopupMenu(LocalFrame& frame, PopupMenuClient* client) const
730 {
731     if (WebViewImpl::useExternalPopupMenus())
732         return adoptRefWillBeNoop(new ExternalPopupMenu(frame, client, *m_webView));
733
734     return adoptRefWillBeNoop(new PopupMenuChromium(frame, client));
735 }
736
737 PagePopup* ChromeClientImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
738 {
739     ASSERT(m_pagePopupDriver);
740     return m_pagePopupDriver->openPagePopup(client, originBoundsInRootView);
741 }
742
743 void ChromeClientImpl::closePagePopup(PagePopup* popup)
744 {
745     ASSERT(m_pagePopupDriver);
746     m_pagePopupDriver->closePagePopup(popup);
747 }
748
749 void ChromeClientImpl::setPagePopupDriver(PagePopupDriver* driver)
750 {
751     ASSERT(driver);
752     m_pagePopupDriver = driver;
753 }
754
755 void ChromeClientImpl::resetPagePopupDriver()
756 {
757     m_pagePopupDriver = m_webView;
758 }
759
760 bool ChromeClientImpl::shouldRunModalDialogDuringPageDismissal(const DialogType& dialogType, const String& dialogMessage, Document::PageDismissalType dismissalType) const
761 {
762     const char* kDialogs[] = {"alert", "confirm", "prompt", "showModalDialog"};
763     int dialog = static_cast<int>(dialogType);
764     ASSERT_WITH_SECURITY_IMPLICATION(0 <= dialog && dialog < static_cast<int>(arraysize(kDialogs)));
765
766     const char* kDismissals[] = {"beforeunload", "pagehide", "unload"};
767     int dismissal = static_cast<int>(dismissalType) - 1; // Exclude NoDismissal.
768     ASSERT_WITH_SECURITY_IMPLICATION(0 <= dismissal && dismissal < static_cast<int>(arraysize(kDismissals)));
769
770     Platform::current()->histogramEnumeration("Renderer.ModalDialogsDuringPageDismissal", dismissal * arraysize(kDialogs) + dialog, arraysize(kDialogs) * arraysize(kDismissals));
771
772     String message = String("Blocked ") + kDialogs[dialog] + "('" + dialogMessage + "') during " + kDismissals[dismissal] + ".";
773     m_webView->mainFrame()->addMessageToConsole(WebConsoleMessage(WebConsoleMessage::LevelError, message));
774
775     return false;
776 }
777
778 void ChromeClientImpl::needTouchEvents(bool needsTouchEvents)
779 {
780     m_webView->hasTouchEventHandlers(needsTouchEvents);
781 }
782
783 void ChromeClientImpl::setTouchAction(TouchAction touchAction)
784 {
785     if (WebViewClient* client = m_webView->client()) {
786         WebTouchAction webTouchAction = static_cast<WebTouchAction>(touchAction);
787         client->setTouchAction(webTouchAction);
788     }
789 }
790
791 bool ChromeClientImpl::requestPointerLock()
792 {
793     return m_webView->requestPointerLock();
794 }
795
796 void ChromeClientImpl::requestPointerUnlock()
797 {
798     return m_webView->requestPointerUnlock();
799 }
800
801 void ChromeClientImpl::annotatedRegionsChanged()
802 {
803     WebViewClient* client = m_webView->client();
804     if (client)
805         client->draggableRegionsChanged();
806 }
807
808 void ChromeClientImpl::didAssociateFormControls(const WillBeHeapVector<RefPtrWillBeMember<Element> >& elements)
809 {
810     if (m_webView->autofillClient())
811         m_webView->autofillClient()->didAssociateFormControls(elements);
812 }
813
814 void ChromeClientImpl::didCancelCompositionOnSelectionChange()
815 {
816     if (m_webView->client())
817         m_webView->client()->didCancelCompositionOnSelectionChange();
818 }
819
820 void ChromeClientImpl::willSetInputMethodState()
821 {
822     if (m_webView->client())
823         m_webView->client()->resetInputMethod();
824 }
825
826 void ChromeClientImpl::didUpdateTextOfFocusedElementByNonUserInput()
827 {
828     if (m_webView->client())
829         m_webView->client()->didUpdateTextOfFocusedElementByNonUserInput();
830 }
831
832 void ChromeClientImpl::showImeIfNeeded()
833 {
834     if (m_webView->client())
835         m_webView->client()->showImeIfNeeded();
836 }
837
838 void ChromeClientImpl::handleKeyboardEventOnTextField(HTMLInputElement& inputElement, KeyboardEvent& event)
839 {
840     if (!m_webView->autofillClient())
841         return;
842     m_webView->autofillClient()->textFieldDidReceiveKeyDown(WebInputElement(&inputElement), WebKeyboardEventBuilder(event));
843 }
844
845 // FIXME: Remove this code once we have input routing in the browser
846 // process. See http://crbug.com/339659.
847 void ChromeClientImpl::forwardInputEvent(
848     Frame* frame, Event* event)
849 {
850     // FIXME: Input event forwarding to out-of-process frames is broken until
851     // WebRemoteFrameImpl has a WebFrameClient.
852     if (frame->isRemoteFrame())
853         return;
854
855     WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(toLocalFrame(frame));
856
857     // This is only called when we have out-of-process iframes, which
858     // need to forward input events across processes.
859     // FIXME: Add a check for out-of-process iframes enabled.
860     if (event->isKeyboardEvent()) {
861         WebKeyboardEventBuilder webEvent(*static_cast<KeyboardEvent*>(event));
862         webFrame->client()->forwardInputEvent(&webEvent);
863     } else if (event->isMouseEvent()) {
864         WebMouseEventBuilder webEvent(webFrame->frameView(), frame->ownerRenderer(), *static_cast<MouseEvent*>(event));
865         // Internal Blink events should not be forwarded.
866         if (webEvent.type == WebInputEvent::Undefined)
867             return;
868
869         webFrame->client()->forwardInputEvent(&webEvent);
870     } else if (event->isWheelEvent()) {
871         WebMouseWheelEventBuilder webEvent(webFrame->frameView(), frame->ownerRenderer(), *static_cast<WheelEvent*>(event));
872         if (webEvent.type == WebInputEvent::Undefined)
873             return;
874         webFrame->client()->forwardInputEvent(&webEvent);
875     }
876 }
877
878 void ChromeClientImpl::didChangeValueInTextField(HTMLFormControlElement& element)
879 {
880     if (!m_webView->autofillClient())
881         return;
882     m_webView->autofillClient()->textFieldDidChange(WebFormControlElement(&element));
883 }
884
885 void ChromeClientImpl::didEndEditingOnTextField(HTMLInputElement& inputElement)
886 {
887     if (m_webView->autofillClient())
888         m_webView->autofillClient()->textFieldDidEndEditing(WebInputElement(&inputElement));
889 }
890
891 void ChromeClientImpl::openTextDataListChooser(HTMLInputElement& input)
892 {
893     if (m_webView->autofillClient())
894         m_webView->autofillClient()->openTextDataListChooser(WebInputElement(&input));
895 }
896
897 } // namespace blink