47f2eab808d6b1a5e043e18ea69975acfc6e41ac
[WebKit.git] / Source / WebKit / chromium / src / 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 "ChromeClientImpl.h"
34
35 #include "AXObjectCache.h"
36 #include "AccessibilityObject.h"
37 #include "Console.h"
38 #include "Cursor.h"
39 #include "DatabaseTracker.h"
40 #include "Document.h"
41 #include "DocumentLoader.h"
42 #include "ExternalPopupMenu.h"
43 #include "FileChooser.h"
44 #include "FloatRect.h"
45 #include "FrameLoadRequest.h"
46 #include "FrameView.h"
47 #include "Geolocation.h"
48 #include "GeolocationService.h"
49 #include "GraphicsLayer.h"
50 #include "HTMLNames.h"
51 #include "HitTestResult.h"
52 #include "IntRect.h"
53 #include "NavigationAction.h"
54 #include "Node.h"
55 #include "NotificationPresenterImpl.h"
56 #include "Page.h"
57 #include "PopupMenuChromium.h"
58 #include "RenderWidget.h"
59 #include "ScriptController.h"
60 #include "SearchPopupMenuChromium.h"
61 #include "SecurityOrigin.h"
62 #include "Settings.h"
63 #if USE(V8)
64 #include "V8Proxy.h"
65 #endif
66 #include "WebAccessibilityObject.h"
67 #include "WebConsoleMessage.h"
68 #include "WebCursorInfo.h"
69 #include "WebFileChooserCompletionImpl.h"
70 #include "WebFrameClient.h"
71 #include "WebFrameImpl.h"
72 #include "WebIconLoadingCompletionImpl.h"
73 #include "WebInputEvent.h"
74 #include "WebKit.h"
75 #include "WebNode.h"
76 #include "WebPlugin.h"
77 #include "WebPluginContainerImpl.h"
78 #include "WebPopupMenuImpl.h"
79 #include "WebPopupMenuInfo.h"
80 #include "WebPopupType.h"
81 #include "WebRect.h"
82 #include "WebTextDirection.h"
83 #include "WebURLRequest.h"
84 #include "WebViewClient.h"
85 #include "WebViewImpl.h"
86 #include "WebWindowFeatures.h"
87 #include "WindowFeatures.h"
88 #include "WrappedResourceRequest.h"
89 #include <wtf/unicode/CharacterNames.h>
90
91 using namespace WebCore;
92
93 namespace WebKit {
94
95 // Converts a WebCore::PopupContainerType to a WebKit::WebPopupType.
96 static WebPopupType convertPopupType(PopupContainer::PopupType type)
97 {
98     switch (type) {
99     case PopupContainer::Select:
100         return WebPopupTypeSelect;
101     case PopupContainer::Suggestion:
102         return WebPopupTypeSuggestion;
103     default:
104         ASSERT_NOT_REACHED();
105         return WebPopupTypeNone;
106     }
107 }
108
109 // Converts a WebCore::AXObjectCache::AXNotification to a WebKit::WebAccessibilityNotification
110 static WebAccessibilityNotification toWebAccessibilityNotification(AXObjectCache::AXNotification notification)
111 {
112     switch (notification) {
113     case AXObjectCache::AXActiveDescendantChanged:
114         return WebAccessibilityNotificationActiveDescendantChanged;
115     case AXObjectCache::AXCheckedStateChanged:
116         return WebAccessibilityNotificationCheckedStateChanged;
117     case AXObjectCache::AXChildrenChanged:
118         return WebAccessibilityNotificationChildrenChanged;
119     case AXObjectCache::AXFocusedUIElementChanged:
120         return WebAccessibilityNotificationFocusedUIElementChanged;
121     case AXObjectCache::AXLayoutComplete:
122         return WebAccessibilityNotificationLayoutComplete;
123     case AXObjectCache::AXLoadComplete:
124         return WebAccessibilityNotificationLoadComplete;
125     case AXObjectCache::AXSelectedChildrenChanged:
126         return WebAccessibilityNotificationSelectedChildrenChanged;
127     case AXObjectCache::AXSelectedTextChanged:
128         return WebAccessibilityNotificationSelectedTextChanged;
129     case AXObjectCache::AXValueChanged:
130         return WebAccessibilityNotificationValueChanged;
131     case AXObjectCache::AXScrolledToAnchor:
132         return WebAccessibilityNotificationScrolledToAnchor;
133     case AXObjectCache::AXLiveRegionChanged:
134         return WebAccessibilityNotificationLiveRegionChanged;
135     case AXObjectCache::AXMenuListValueChanged:
136         return WebAccessibilityNotificationMenuListValueChanged;
137     case AXObjectCache::AXRowCountChanged:
138         return WebAccessibilityNotificationRowCountChanged;
139     case AXObjectCache::AXRowCollapsed:
140         return WebAccessibilityNotificationRowCollapsed;
141     case AXObjectCache::AXRowExpanded:
142         return WebAccessibilityNotificationRowExpanded;
143     default:
144         ASSERT_NOT_REACHED();
145         return WebAccessibilityNotificationInvalid;
146     }
147 }
148
149 ChromeClientImpl::ChromeClientImpl(WebViewImpl* webView)
150     : m_webView(webView)
151     , m_toolbarsVisible(true)
152     , m_statusbarVisible(true)
153     , m_scrollbarsVisible(true)
154     , m_menubarVisible(true)
155     , m_resizable(true)
156 {
157 }
158
159 ChromeClientImpl::~ChromeClientImpl()
160 {
161 }
162
163 void ChromeClientImpl::chromeDestroyed()
164 {
165     // Our lifetime is bound to the WebViewImpl.
166 }
167
168 void ChromeClientImpl::setWindowRect(const FloatRect& r)
169 {
170     if (m_webView->client())
171         m_webView->client()->setWindowRect(IntRect(r));
172 }
173
174 FloatRect ChromeClientImpl::windowRect()
175 {
176     WebRect rect;
177     if (m_webView->client())
178         rect = m_webView->client()->rootWindowRect();
179     else {
180         // These numbers will be fairly wrong. The window's x/y coordinates will
181         // be the top left corner of the screen and the size will be the content
182         // size instead of the window size.
183         rect.width = m_webView->size().width;
184         rect.height = m_webView->size().height;
185     }
186     return FloatRect(rect);
187 }
188
189 FloatRect ChromeClientImpl::pageRect()
190 {
191     // We hide the details of the window's border thickness from the web page by
192     // simple re-using the window position here.  So, from the point-of-view of
193     // the web page, the window has no border.
194     return windowRect();
195 }
196
197 float ChromeClientImpl::scaleFactor()
198 {
199     // This is supposed to return the scale factor of the web page. It looks like
200     // the implementor of the graphics layer is responsible for doing most of the
201     // operations associated with scaling. However, this value is used ins some
202     // cases by WebCore. For example, this is used as a scaling factor in canvas
203     // so that things drawn in it are scaled just like the web page is.
204     //
205     // We don't currently implement scaling, so just return 1.0 (no scaling).
206     return 1.0;
207 }
208
209 void ChromeClientImpl::focus()
210 {
211     if (m_webView->client())
212         m_webView->client()->didFocus();
213 }
214
215 void ChromeClientImpl::unfocus()
216 {
217     if (m_webView->client())
218         m_webView->client()->didBlur();
219 }
220
221 bool ChromeClientImpl::canTakeFocus(FocusDirection)
222 {
223     // For now the browser can always take focus if we're not running layout
224     // tests.
225     return !layoutTestMode();
226 }
227
228 void ChromeClientImpl::takeFocus(FocusDirection direction)
229 {
230     if (!m_webView->client())
231         return;
232     if (direction == FocusDirectionBackward)
233         m_webView->client()->focusPrevious();
234     else
235         m_webView->client()->focusNext();
236 }
237
238 void ChromeClientImpl::focusedNodeChanged(Node* node)
239 {
240     m_webView->client()->focusedNodeChanged(WebNode(node));
241
242     WebURL focusURL;
243     if (node && node->isLink()) {
244         // This HitTestResult hack is the easiest way to get a link URL out of a
245         // WebCore::Node.
246         HitTestResult hitTest(IntPoint(0, 0));
247         // This cast must be valid because of the isLink() check.
248         hitTest.setURLElement(static_cast<Element*>(node));
249         if (hitTest.isLiveLink())
250             focusURL = hitTest.absoluteLinkURL();
251     }
252     m_webView->client()->setKeyboardFocusURL(focusURL);
253 }
254
255 void ChromeClientImpl::focusedFrameChanged(Frame*)
256 {
257 }
258
259 Page* ChromeClientImpl::createWindow(
260     Frame* frame, const FrameLoadRequest& r, const WindowFeatures& features, const NavigationAction&)
261 {
262     if (!m_webView->client())
263         return 0;
264
265     WrappedResourceRequest request;
266     if (!r.resourceRequest().isEmpty())
267         request.bind(r.resourceRequest());
268     WebViewImpl* newView = static_cast<WebViewImpl*>(
269         m_webView->client()->createView(WebFrameImpl::fromFrame(frame), request, features, r.frameName()));
270     if (!newView)
271         return 0;
272
273     return newView->page();
274 }
275
276 static inline bool currentEventShouldCauseBackgroundTab(const WebInputEvent* inputEvent)
277 {
278     if (!inputEvent)
279         return false;
280
281     if (inputEvent->type != WebInputEvent::MouseUp)
282         return false;
283
284     const WebMouseEvent* mouseEvent = static_cast<const WebMouseEvent*>(inputEvent);
285
286     WebNavigationPolicy policy;
287     unsigned short buttonNumber;
288     switch (mouseEvent->button) {
289     case WebMouseEvent::ButtonLeft:
290         buttonNumber = 0;
291         break;
292     case WebMouseEvent::ButtonMiddle:
293         buttonNumber = 1;
294         break;
295     case WebMouseEvent::ButtonRight:
296         buttonNumber = 2;
297         break;
298     default:
299         return false;
300     }
301     bool ctrl = mouseEvent->modifiers & WebMouseEvent::ControlKey;
302     bool shift = mouseEvent->modifiers & WebMouseEvent::ShiftKey;
303     bool alt = mouseEvent->modifiers & WebMouseEvent::AltKey;
304     bool meta = mouseEvent->modifiers & WebMouseEvent::MetaKey;
305
306     if (!WebViewImpl::navigationPolicyFromMouseEvent(buttonNumber, ctrl, shift, alt, meta, &policy))
307         return false;
308
309     return policy == WebNavigationPolicyNewBackgroundTab;
310 }
311
312 void ChromeClientImpl::show()
313 {
314     if (!m_webView->client())
315         return;
316
317     // If our default configuration was modified by a script or wasn't
318     // created by a user gesture, then show as a popup. Else, let this
319     // new window be opened as a toplevel window.
320     bool asPopup = !m_toolbarsVisible
321         || !m_statusbarVisible
322         || !m_scrollbarsVisible
323         || !m_menubarVisible
324         || !m_resizable;
325
326     WebNavigationPolicy policy = WebNavigationPolicyNewForegroundTab;
327     if (asPopup)
328         policy = WebNavigationPolicyNewPopup;
329     if (currentEventShouldCauseBackgroundTab(WebViewImpl::currentInputEvent()))
330         policy = WebNavigationPolicyNewBackgroundTab;
331
332     m_webView->client()->show(policy);
333 }
334
335 bool ChromeClientImpl::canRunModal()
336 {
337     return !!m_webView->client();
338 }
339
340 void ChromeClientImpl::runModal()
341 {
342     if (m_webView->client())
343         m_webView->client()->runModal();
344 }
345
346 void ChromeClientImpl::setToolbarsVisible(bool value)
347 {
348     m_toolbarsVisible = value;
349 }
350
351 bool ChromeClientImpl::toolbarsVisible()
352 {
353     return m_toolbarsVisible;
354 }
355
356 void ChromeClientImpl::setStatusbarVisible(bool value)
357 {
358     m_statusbarVisible = value;
359 }
360
361 bool ChromeClientImpl::statusbarVisible()
362 {
363     return m_statusbarVisible;
364 }
365
366 void ChromeClientImpl::setScrollbarsVisible(bool value)
367 {
368     m_scrollbarsVisible = value;
369     WebFrameImpl* webFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame());
370     if (webFrame)
371         webFrame->setCanHaveScrollbars(value);
372 }
373
374 bool ChromeClientImpl::scrollbarsVisible()
375 {
376     return m_scrollbarsVisible;
377 }
378
379 void ChromeClientImpl::setMenubarVisible(bool value)
380 {
381     m_menubarVisible = value;
382 }
383
384 bool ChromeClientImpl::menubarVisible()
385 {
386     return m_menubarVisible;
387 }
388
389 void ChromeClientImpl::setResizable(bool value)
390 {
391     m_resizable = value;
392 }
393
394 void ChromeClientImpl::addMessageToConsole(MessageSource source,
395                                            MessageType type,
396                                            MessageLevel level,
397                                            const String& message,
398                                            unsigned lineNumber,
399                                            const String& sourceID)
400 {
401     if (m_webView->client()) {
402         m_webView->client()->didAddMessageToConsole(
403             WebConsoleMessage(static_cast<WebConsoleMessage::Level>(level), message),
404             sourceID,
405             lineNumber);
406     }
407 }
408
409 bool ChromeClientImpl::canRunBeforeUnloadConfirmPanel()
410 {
411     return !!m_webView->client();
412 }
413
414 bool ChromeClientImpl::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
415 {
416     if (m_webView->client()) {
417         return m_webView->client()->runModalBeforeUnloadDialog(
418             WebFrameImpl::fromFrame(frame), message);
419     }
420     return false;
421 }
422
423 void ChromeClientImpl::closeWindowSoon()
424 {
425     // Make sure this Page can no longer be found by JS.
426     m_webView->page()->setGroupName(String());
427
428     // Make sure that all loading is stopped.  Ensures that JS stops executing!
429     m_webView->mainFrame()->stopLoading();
430
431     if (m_webView->client())
432         m_webView->client()->closeWidgetSoon();
433 }
434
435 // Although a Frame is passed in, we don't actually use it, since we
436 // already know our own m_webView.
437 void ChromeClientImpl::runJavaScriptAlert(Frame* frame, const String& message)
438 {
439     if (m_webView->client()) {
440         m_webView->client()->runModalAlertDialog(
441             WebFrameImpl::fromFrame(frame), message);
442     }
443 }
444
445 // See comments for runJavaScriptAlert().
446 bool ChromeClientImpl::runJavaScriptConfirm(Frame* frame, const String& message)
447 {
448     if (m_webView->client()) {
449         return m_webView->client()->runModalConfirmDialog(
450             WebFrameImpl::fromFrame(frame), message);
451     }
452     return false;
453 }
454
455 // See comments for runJavaScriptAlert().
456 bool ChromeClientImpl::runJavaScriptPrompt(Frame* frame,
457                                            const String& message,
458                                            const String& defaultValue,
459                                            String& result)
460 {
461     if (m_webView->client()) {
462         WebString actualValue;
463         bool ok = m_webView->client()->runModalPromptDialog(
464             WebFrameImpl::fromFrame(frame),
465             message,
466             defaultValue,
467             &actualValue);
468         if (ok)
469             result = actualValue;
470         return ok;
471     }
472     return false;
473 }
474
475 void ChromeClientImpl::setStatusbarText(const String& message)
476 {
477     if (m_webView->client())
478         m_webView->client()->setStatusText(message);
479 }
480
481 bool ChromeClientImpl::shouldInterruptJavaScript()
482 {
483     // FIXME: implement me
484     return false;
485 }
486
487 bool ChromeClientImpl::tabsToLinks() const
488 {
489     // Returns true if anchors should accept keyboard focus with the tab key.
490     // This method is used in a convoluted fashion by EventHandler::tabsToLinks.
491     // It's a twisted path (self-evident, but more complicated than seems
492     // necessary), but the net result is that returning true from here, on a
493     // platform other than MAC or QT, lets anchors get keyboard focus.
494     return m_webView->tabsToLinks();
495 }
496
497 IntRect ChromeClientImpl::windowResizerRect() const
498 {
499     IntRect result;
500     if (m_webView->client())
501         result = m_webView->client()->windowResizerRect();
502     return result;
503 }
504
505 #if ENABLE(REGISTER_PROTOCOL_HANDLER)
506 void ChromeClientImpl::registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title)
507 {
508     notImplemented();
509 }
510 #endif
511
512 void ChromeClientImpl::invalidateWindow(const IntRect&, bool)
513 {
514     notImplemented();
515 }
516
517 void ChromeClientImpl::invalidateContentsAndWindow(const IntRect& updateRect, bool /*immediate*/)
518 {
519     if (updateRect.isEmpty())
520         return;
521 #if USE(ACCELERATED_COMPOSITING)
522     if (!m_webView->isAcceleratedCompositingActive()) {
523 #endif
524         if (m_webView->client())
525             m_webView->client()->didInvalidateRect(updateRect);
526 #if USE(ACCELERATED_COMPOSITING)
527     } else
528         m_webView->invalidateRootLayerRect(updateRect);
529 #endif
530 }
531
532 void ChromeClientImpl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
533 {
534     m_webView->hidePopups();
535     invalidateContentsAndWindow(updateRect, immediate);
536 }
537
538 #if ENABLE(REQUEST_ANIMATION_FRAME)
539 void ChromeClientImpl::scheduleAnimation()
540 {
541     m_webView->client()->scheduleAnimation();
542 }
543 #endif
544
545 void ChromeClientImpl::scroll(
546     const IntSize& scrollDelta, const IntRect& scrollRect,
547     const IntRect& clipRect)
548 {
549     m_webView->hidePopups();
550 #if USE(ACCELERATED_COMPOSITING)
551     if (!m_webView->isAcceleratedCompositingActive()) {
552 #endif
553         if (m_webView->client()) {
554             int dx = scrollDelta.width();
555             int dy = scrollDelta.height();
556             m_webView->client()->didScrollRect(dx, dy, clipRect);
557         }
558 #if USE(ACCELERATED_COMPOSITING)
559     } else
560         m_webView->scrollRootLayerRect(scrollDelta, clipRect);
561 #endif
562 }
563
564 IntPoint ChromeClientImpl::screenToWindow(const IntPoint&) const
565 {
566     notImplemented();
567     return IntPoint();
568 }
569
570 IntRect ChromeClientImpl::windowToScreen(const IntRect& rect) const
571 {
572     IntRect screenRect(rect);
573
574     if (m_webView->client()) {
575         WebRect windowRect = m_webView->client()->windowRect();
576         screenRect.move(windowRect.x, windowRect.y);
577     }
578
579     return screenRect;
580 }
581
582 void ChromeClientImpl::contentsSizeChanged(Frame* frame, const IntSize& size) const
583 {
584     WebFrameImpl* webframe = WebFrameImpl::fromFrame(frame);
585     if (webframe->client())
586         webframe->client()->didChangeContentsSize(webframe, size);
587 }
588
589 void ChromeClientImpl::scrollbarsModeDidChange() const
590 {
591 }
592
593 void ChromeClientImpl::mouseDidMoveOverElement(
594     const HitTestResult& result, unsigned modifierFlags)
595 {
596     if (!m_webView->client())
597         return;
598
599     WebURL url;
600     // Find out if the mouse is over a link, and if so, let our UI know...
601     if (result.isLiveLink() && !result.absoluteLinkURL().string().isEmpty())
602         url = result.absoluteLinkURL();
603     else if (result.innerNonSharedNode()
604              && (result.innerNonSharedNode()->hasTagName(HTMLNames::objectTag)
605                  || result.innerNonSharedNode()->hasTagName(HTMLNames::embedTag))) {
606         RenderObject* object = result.innerNonSharedNode()->renderer();
607         if (object && object->isWidget()) {
608             Widget* widget = toRenderWidget(object)->widget();
609             if (widget && widget->isPluginContainer()) {
610                 WebPluginContainerImpl* plugin = static_cast<WebPluginContainerImpl*>(widget);
611                 url = plugin->plugin()->linkAtPosition(result.point());
612             }
613         }
614     }
615
616     m_webView->client()->setMouseOverURL(url);
617 }
618
619 void ChromeClientImpl::setToolTip(const String& tooltipText, TextDirection dir)
620 {
621     if (!m_webView->client())
622         return;
623     WebTextDirection textDirection = (dir == RTL) ?
624         WebTextDirectionRightToLeft :
625         WebTextDirectionLeftToRight;
626     m_webView->client()->setToolTipText(
627         tooltipText, textDirection);
628 }
629
630 void ChromeClientImpl::print(Frame* frame)
631 {
632     if (m_webView->client())
633         m_webView->client()->printPage(WebFrameImpl::fromFrame(frame));
634 }
635
636 void ChromeClientImpl::exceededDatabaseQuota(Frame* frame, const String& databaseName)
637 {
638     // Chromium users cannot currently change the default quota
639 }
640
641 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
642 void ChromeClientImpl::reachedMaxAppCacheSize(int64_t spaceNeeded)
643 {
644     ASSERT_NOT_REACHED();
645 }
646
647 void ChromeClientImpl::reachedApplicationCacheOriginQuota(SecurityOrigin*)
648 {
649     ASSERT_NOT_REACHED();
650 }
651 #endif
652
653 void ChromeClientImpl::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser)
654 {
655     WebViewClient* client = m_webView->client();
656     if (!client)
657         return;
658
659     WebFileChooserParams params;
660     params.multiSelect = fileChooser->allowsMultipleFiles();
661 #if ENABLE(DIRECTORY_UPLOAD)
662     params.directory = fileChooser->allowsDirectoryUpload();
663 #else
664     params.directory = false;
665 #endif
666     params.acceptTypes = fileChooser->acceptTypes();
667     params.selectedFiles = fileChooser->filenames();
668     if (params.selectedFiles.size() > 0)
669         params.initialValue = params.selectedFiles[0];
670     WebFileChooserCompletionImpl* chooserCompletion =
671         new WebFileChooserCompletionImpl(fileChooser);
672
673     if (client->runFileChooser(params, chooserCompletion))
674         return;
675
676     // Choosing failed, so do callback with an empty list.
677     chooserCompletion->didChooseFile(WebVector<WebString>());
678 }
679
680 void ChromeClientImpl::chooseIconForFiles(const Vector<String>& filenames, FileChooser* fileChooser)
681 {
682     if (!m_webView->client())
683         return;
684     WebIconLoadingCompletionImpl* iconCompletion = new WebIconLoadingCompletionImpl(fileChooser);
685     if (!m_webView->client()->queryIconForFiles(filenames, iconCompletion))
686         iconCompletion->didLoadIcon(WebData());
687 }
688
689 void ChromeClientImpl::popupOpened(PopupContainer* popupContainer,
690                                    const IntRect& bounds,
691                                    bool handleExternally)
692 {
693     if (!m_webView->client())
694         return;
695
696     WebWidget* webwidget;
697     if (handleExternally) {
698         WebPopupMenuInfo popupInfo;
699         getPopupMenuInfo(popupContainer, &popupInfo);
700         webwidget = m_webView->client()->createPopupMenu(popupInfo);
701     } else {
702         webwidget = m_webView->client()->createPopupMenu(
703             convertPopupType(popupContainer->popupType()));
704         // We only notify when the WebView has to handle the popup, as when
705         // the popup is handled externally, the fact that a popup is showing is
706         // transparent to the WebView.
707         m_webView->popupOpened(popupContainer);
708     }
709     static_cast<WebPopupMenuImpl*>(webwidget)->Init(popupContainer, bounds);
710 }
711
712 void ChromeClientImpl::popupClosed(WebCore::PopupContainer* popupContainer)
713 {
714     m_webView->popupClosed(popupContainer);
715 }
716
717 void ChromeClientImpl::setCursor(const WebCore::Cursor& cursor)
718 {
719     setCursor(WebCursorInfo(cursor));
720 }
721
722 void ChromeClientImpl::setCursor(const WebCursorInfo& cursor)
723 {
724     if (m_webView->client())
725         m_webView->client()->didChangeCursor(cursor);
726 }
727
728 void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor)
729 {
730     setCursor(cursor);
731 }
732
733 void ChromeClientImpl::formStateDidChange(const Node* node)
734 {
735     // The current history item is not updated yet.  That happens lazily when
736     // WebFrame::currentHistoryItem is requested.
737     WebFrameImpl* webframe = WebFrameImpl::fromFrame(node->document()->frame());
738     if (webframe->client())
739         webframe->client()->didUpdateCurrentHistoryItem(webframe);
740 }
741
742 void ChromeClientImpl::getPopupMenuInfo(PopupContainer* popupContainer,
743                                         WebPopupMenuInfo* info)
744 {
745     const Vector<PopupItem*>& inputItems = popupContainer->popupData();
746
747     WebVector<WebPopupMenuInfo::Item> outputItems(inputItems.size());
748
749     for (size_t i = 0; i < inputItems.size(); ++i) {
750         const PopupItem& inputItem = *inputItems[i];
751         WebPopupMenuInfo::Item& outputItem = outputItems[i];
752
753         outputItem.label = inputItem.label;
754         outputItem.enabled = inputItem.enabled;
755
756         switch (inputItem.type) {
757         case PopupItem::TypeOption:
758             outputItem.type = WebPopupMenuInfo::Item::Option;
759             break;
760         case PopupItem::TypeGroup:
761             outputItem.type = WebPopupMenuInfo::Item::Group;
762             break;
763         case PopupItem::TypeSeparator:
764             outputItem.type = WebPopupMenuInfo::Item::Separator;
765             break;
766         default:
767             ASSERT_NOT_REACHED();
768         }
769     }
770
771     info->itemHeight = popupContainer->menuItemHeight();
772     info->itemFontSize = popupContainer->menuItemFontSize();
773     info->selectedIndex = popupContainer->selectedIndex();
774     info->items.swap(outputItems);
775     info->rightAligned = popupContainer->menuStyle().textDirection() == RTL;
776 }
777
778 void ChromeClientImpl::postAccessibilityNotification(AccessibilityObject* obj, AXObjectCache::AXNotification notification)
779 {
780     // Alert assistive technology about the accessibility object notification.
781     if (obj)
782         m_webView->client()->postAccessibilityNotification(WebAccessibilityObject(obj), toWebAccessibilityNotification(notification));
783 }
784
785 #if ENABLE(NOTIFICATIONS)
786 NotificationPresenter* ChromeClientImpl::notificationPresenter() const
787 {
788     return m_webView->notificationPresenterImpl();
789 }
790 #endif
791
792 // FIXME: Remove ChromeClientImpl::requestGeolocationPermissionForFrame and ChromeClientImpl::cancelGeolocationPermissionRequestForFrame
793 // once all ports have moved to client-based geolocation (see https://bugs.webkit.org/show_bug.cgi?id=40373 ).
794 // For client-based geolocation, these methods are now implemented as WebGeolocationClient::requestPermission and WebGeolocationClient::cancelPermissionRequest.
795 // (see https://bugs.webkit.org/show_bug.cgi?id=50061 ).
796 void ChromeClientImpl::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
797 {
798     ASSERT_NOT_REACHED();
799 }
800
801 void ChromeClientImpl::cancelGeolocationPermissionRequestForFrame(Frame* frame, Geolocation* geolocation)
802 {
803     ASSERT_NOT_REACHED();
804 }
805
806 #if USE(ACCELERATED_COMPOSITING)
807 void ChromeClientImpl::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
808 {
809     m_webView->setRootGraphicsLayer(graphicsLayer ? graphicsLayer->platformLayer() : 0);
810 }
811
812 void ChromeClientImpl::scheduleCompositingLayerSync()
813 {
814     m_webView->setRootLayerNeedsDisplay();
815 }
816
817 ChromeClient::CompositingTriggerFlags ChromeClientImpl::allowedCompositingTriggers() const
818 {
819     if (!m_webView->allowsAcceleratedCompositing())
820         return 0;
821
822     CompositingTriggerFlags flags = 0;
823     Settings* settings = m_webView->page()->settings();
824     if (settings->acceleratedCompositingFor3DTransformsEnabled())
825         flags |= ThreeDTransformTrigger;
826     if (settings->acceleratedCompositingForVideoEnabled())
827         flags |= VideoTrigger;
828     if (settings->acceleratedCompositingForPluginsEnabled())
829         flags |= PluginTrigger;
830     if (settings->acceleratedCompositingForAnimationEnabled())
831         flags |= AnimationTrigger;
832     if (settings->acceleratedCompositingForCanvasEnabled())
833         flags |= CanvasTrigger;
834
835     return flags;
836 }
837 #endif
838
839 bool ChromeClientImpl::supportsFullscreenForNode(const WebCore::Node* node)
840 {
841     if (m_webView->client() && node->hasTagName(WebCore::HTMLNames::videoTag))
842         return m_webView->client()->supportsFullscreen();
843     return false;
844 }
845
846 void ChromeClientImpl::enterFullscreenForNode(WebCore::Node* node)
847 {
848     if (m_webView->client())
849         m_webView->client()->enterFullscreenForNode(WebNode(node));
850 }
851
852 void ChromeClientImpl::exitFullscreenForNode(WebCore::Node* node)
853 {
854     if (m_webView->client())
855         m_webView->client()->exitFullscreenForNode(WebNode(node));
856 }
857
858 bool ChromeClientImpl::selectItemWritingDirectionIsNatural()
859 {
860     return false;
861 }
862
863 bool ChromeClientImpl::selectItemAlignmentFollowsMenuWritingDirection()
864 {
865     return false;
866 }
867
868 PassRefPtr<PopupMenu> ChromeClientImpl::createPopupMenu(PopupMenuClient* client) const
869 {
870     if (WebViewImpl::useExternalPopupMenus())
871         return adoptRef(new ExternalPopupMenu(client, m_webView->client()));
872
873     return adoptRef(new PopupMenuChromium(client));
874 }
875
876 PassRefPtr<SearchPopupMenu> ChromeClientImpl::createSearchPopupMenu(PopupMenuClient* client) const
877 {
878     return adoptRef(new SearchPopupMenuChromium(client));
879 }
880
881 } // namespace WebKit