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