Home | History | Annotate | Download | only in src
      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.
     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
    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 
    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 
    161 ChromeClientImpl::~ChromeClientImpl()
    162 {
    163 }
    164 
    165 void* ChromeClientImpl::webView() const
    166 {
    167     return static_cast<void*>(m_webView);
    168 }
    169 
    170 void ChromeClientImpl::chromeDestroyed()
    171 {
    172     // Our lifetime is bound to the WebViewImpl.
    173 }
    174 
    175 void ChromeClientImpl::setWindowRect(const FloatRect& r)
    176 {
    177     if (m_webView->client())
    178         m_webView->client()->setWindowRect(IntRect(r));
    179 }
    180 
    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 
    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 
    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 
    216 void ChromeClientImpl::focus()
    217 {
    218     if (m_webView->client())
    219         m_webView->client()->didFocus();
    220 }
    221 
    222 void ChromeClientImpl::unfocus()
    223 {
    224     if (m_webView->client())
    225         m_webView->client()->didBlur();
    226 }
    227 
    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 
    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 
    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 
    262 void ChromeClientImpl::focusedFrameChanged(Frame*)
    263 {
    264 }
    265 
    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 
    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 
    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 
    342 bool ChromeClientImpl::canRunModal()
    343 {
    344     return !!m_webView->client();
    345 }
    346 
    347 void ChromeClientImpl::runModal()
    348 {
    349     if (m_webView->client())
    350         m_webView->client()->runModal();
    351 }
    352 
    353 void ChromeClientImpl::setToolbarsVisible(bool value)
    354 {
    355     m_toolbarsVisible = value;
    356 }
    357 
    358 bool ChromeClientImpl::toolbarsVisible()
    359 {
    360     return m_toolbarsVisible;
    361 }
    362 
    363 void ChromeClientImpl::setStatusbarVisible(bool value)
    364 {
    365     m_statusbarVisible = value;
    366 }
    367 
    368 bool ChromeClientImpl::statusbarVisible()
    369 {
    370     return m_statusbarVisible;
    371 }
    372 
    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 
    381 bool ChromeClientImpl::scrollbarsVisible()
    382 {
    383     return m_scrollbarsVisible;
    384 }
    385 
    386 void ChromeClientImpl::setMenubarVisible(bool value)
    387 {
    388     m_menubarVisible = value;
    389 }
    390 
    391 bool ChromeClientImpl::menubarVisible()
    392 {
    393     return m_menubarVisible;
    394 }
    395 
    396 void ChromeClientImpl::setResizable(bool value)
    397 {
    398     m_resizable = value;
    399 }
    400 
    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 
    416 bool ChromeClientImpl::canRunBeforeUnloadConfirmPanel()
    417 {
    418     return !!m_webView->client();
    419 }
    420 
    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 
    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.
    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().
    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().
    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 
    482 void ChromeClientImpl::setStatusbarText(const String& message)
    483 {
    484     if (m_webView->client())
    485         m_webView->client()->setStatusText(message);
    486 }
    487 
    488 bool ChromeClientImpl::shouldInterruptJavaScript()
    489 {
    490     // FIXME: implement me
    491     return false;
    492 }
    493 
    494 KeyboardUIMode ChromeClientImpl::keyboardUIMode()
    495 {
    496     return m_webView->tabsToLinks() ? KeyboardAccessTabsToLinks : KeyboardAccessDefault;
    497 }
    498 
    499 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)
    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 
    514 void ChromeClientImpl::invalidateWindow(const IntRect&, bool)
    515 {
    516     notImplemented();
    517 }
    518 
    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 
    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)
    541 void ChromeClientImpl::scheduleAnimation()
    542 {
    543     m_webView->client()->scheduleAnimation();
    544 }
    545 #endif
    546 
    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 
    566 IntPoint ChromeClientImpl::screenToWindow(const IntPoint&) const
    567 {
    568     notImplemented();
    569     return IntPoint();
    570 }
    571 
    572 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 
    584 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 
    591 void ChromeClientImpl::scrollbarsModeDidChange() const
    592 {
    593 }
    594 
    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 
    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 
    632 void ChromeClientImpl::print(Frame* frame)
    633 {
    634     if (m_webView->client())
    635         m_webView->client()->printPage(WebFrameImpl::fromFrame(frame));
    636 }
    637 
    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)
    644 void ChromeClientImpl::reachedMaxAppCacheSize(int64_t spaceNeeded)
    645 {
    646     ASSERT_NOT_REACHED();
    647 }
    648 
    649 void ChromeClientImpl::reachedApplicationCacheOriginQuota(SecurityOrigin*)
    650 {
    651     ASSERT_NOT_REACHED();
    652 }
    653 #endif
    654 
    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 
    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)
    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 
    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 
    730 void ChromeClientImpl::popupClosed(WebCore::PopupContainer* popupContainer)
    731 {
    732     m_webView->popupClosed(popupContainer);
    733 }
    734 
    735 void ChromeClientImpl::setCursor(const WebCore::Cursor& cursor)
    736 {
    737     setCursor(WebCursorInfo(cursor));
    738 }
    739 
    740 void ChromeClientImpl::setCursor(const WebCursorInfo& cursor)
    741 {
    742     if (m_webView->client())
    743         m_webView->client()->didChangeCursor(cursor);
    744 }
    745 
    746 void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor)
    747 {
    748     setCursor(cursor);
    749 }
    750 
    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 
    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 
    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)
    809 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 ).
    819 void ChromeClientImpl::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
    820 {
    821     ASSERT_NOT_REACHED();
    822 }
    823 
    824 void ChromeClientImpl::cancelGeolocationPermissionRequestForFrame(Frame* frame, Geolocation* geolocation)
    825 {
    826     ASSERT_NOT_REACHED();
    827 }
    828 
    829 #if USE(ACCELERATED_COMPOSITING)
    830 void ChromeClientImpl::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
    831 {
    832     m_webView->setRootGraphicsLayer(graphicsLayer ? graphicsLayer->platformLayer() : 0);
    833 }
    834 
    835 void ChromeClientImpl::scheduleCompositingLayerSync()
    836 {
    837     m_webView->setRootLayerNeedsDisplay();
    838 }
    839 
    840 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 
    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 
    870 void ChromeClientImpl::enterFullscreenForNode(WebCore::Node* node)
    871 {
    872     if (m_webView->client())
    873         m_webView->client()->enterFullscreenForNode(WebNode(node));
    874 }
    875 
    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)
    883 bool ChromeClientImpl::supportsFullScreenForElement(const WebCore::Element* element, bool withKeyboard)
    884 {
    885     return m_webView->page()->settings()->fullScreenEnabled();
    886 }
    887 
    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 
    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 
    902 void ChromeClientImpl::fullScreenRendererChanged(RenderBox*)
    903 {
    904     notImplemented();
    905 }
    906 #endif
    907 
    908 bool ChromeClientImpl::selectItemWritingDirectionIsNatural()
    909 {
    910     return false;
    911 }
    912 
    913 bool ChromeClientImpl::selectItemAlignmentFollowsMenuWritingDirection()
    914 {
    915     return true;
    916 }
    917 
    918 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 
    926 PassRefPtr<SearchPopupMenu> ChromeClientImpl::createSearchPopupMenu(PopupMenuClient* client) const
    927 {
    928     return adoptRef(new SearchPopupMenuChromium(client));
    929 }
    930 
    931 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