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