Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2009 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "ChromeClientImpl.h"
     33 
     34 #include "AccessibilityObject.h"
     35 #include "AXObjectCache.h"
     36 #include "CharacterNames.h"
     37 #include "Console.h"
     38 #include "Cursor.h"
     39 #include "DatabaseTracker.h"
     40 #include "Document.h"
     41 #include "DocumentLoader.h"
     42 #include "FileChooser.h"
     43 #include "FloatRect.h"
     44 #include "FrameLoadRequest.h"
     45 #include "FrameView.h"
     46 #include "HitTestResult.h"
     47 #include "IntRect.h"
     48 #include "Node.h"
     49 #include "NotificationPresenterImpl.h"
     50 #include "Page.h"
     51 #include "PopupMenuChromium.h"
     52 #include "ScriptController.h"
     53 #if USE(V8)
     54 #include "V8Proxy.h"
     55 #endif
     56 #include "WebAccessibilityObject.h"
     57 #include "WebConsoleMessage.h"
     58 #include "WebCursorInfo.h"
     59 #include "WebFileChooserCompletionImpl.h"
     60 #include "WebFrameClient.h"
     61 #include "WebFrameImpl.h"
     62 #include "WebInputEvent.h"
     63 #include "WebKit.h"
     64 #include "WebPopupMenuImpl.h"
     65 #include "WebPopupMenuInfo.h"
     66 #include "WebRect.h"
     67 #include "WebTextDirection.h"
     68 #include "WebURLRequest.h"
     69 #include "WebViewClient.h"
     70 #include "WebViewImpl.h"
     71 #include "WindowFeatures.h"
     72 #include "WrappedResourceRequest.h"
     73 
     74 using namespace WebCore;
     75 
     76 namespace WebKit {
     77 
     78 ChromeClientImpl::ChromeClientImpl(WebViewImpl* webView)
     79     : m_webView(webView)
     80     , m_toolbarsVisible(true)
     81     , m_statusbarVisible(true)
     82     , m_scrollbarsVisible(true)
     83     , m_menubarVisible(true)
     84     , m_resizable(true)
     85     , m_ignoreNextSetCursor(false)
     86 {
     87 }
     88 
     89 ChromeClientImpl::~ChromeClientImpl()
     90 {
     91 }
     92 
     93 void ChromeClientImpl::chromeDestroyed()
     94 {
     95     // Our lifetime is bound to the WebViewImpl.
     96 }
     97 
     98 void ChromeClientImpl::setWindowRect(const FloatRect& r)
     99 {
    100     if (m_webView->client())
    101         m_webView->client()->setWindowRect(IntRect(r));
    102 }
    103 
    104 FloatRect ChromeClientImpl::windowRect()
    105 {
    106     WebRect rect;
    107     if (m_webView->client())
    108         rect = m_webView->client()->rootWindowRect();
    109     else {
    110         // These numbers will be fairly wrong. The window's x/y coordinates will
    111         // be the top left corner of the screen and the size will be the content
    112         // size instead of the window size.
    113         rect.width = m_webView->size().width;
    114         rect.height = m_webView->size().height;
    115     }
    116     return FloatRect(rect);
    117 }
    118 
    119 FloatRect ChromeClientImpl::pageRect()
    120 {
    121     // We hide the details of the window's border thickness from the web page by
    122     // simple re-using the window position here.  So, from the point-of-view of
    123     // the web page, the window has no border.
    124     return windowRect();
    125 }
    126 
    127 float ChromeClientImpl::scaleFactor()
    128 {
    129     // This is supposed to return the scale factor of the web page. It looks like
    130     // the implementor of the graphics layer is responsible for doing most of the
    131     // operations associated with scaling. However, this value is used ins some
    132     // cases by WebCore. For example, this is used as a scaling factor in canvas
    133     // so that things drawn in it are scaled just like the web page is.
    134     //
    135     // We don't currently implement scaling, so just return 1.0 (no scaling).
    136     return 1.0;
    137 }
    138 
    139 void ChromeClientImpl::focus()
    140 {
    141     if (!m_webView->client())
    142         return;
    143 
    144     m_webView->client()->didFocus();
    145 
    146     // If accessibility is enabled, we should notify assistive technology that
    147     // the active AccessibilityObject changed.
    148     const Frame* frame = m_webView->focusedWebCoreFrame();
    149     if (!frame)
    150         return;
    151 
    152     Document* doc = frame->document();
    153 
    154     if (doc && doc->axObjectCache()->accessibilityEnabled()) {
    155         Node* focusedNode = m_webView->focusedWebCoreNode();
    156 
    157         if (!focusedNode) {
    158             // Could not retrieve focused Node.
    159             return;
    160         }
    161 
    162         // Retrieve the focused AccessibilityObject.
    163         AccessibilityObject* focusedAccObj =
    164             doc->axObjectCache()->getOrCreate(focusedNode->renderer());
    165 
    166         // Alert assistive technology that focus changed.
    167         if (focusedAccObj)
    168             m_webView->client()->focusAccessibilityObject(WebAccessibilityObject(focusedAccObj));
    169     }
    170 }
    171 
    172 void ChromeClientImpl::unfocus()
    173 {
    174     if (m_webView->client())
    175         m_webView->client()->didBlur();
    176 }
    177 
    178 bool ChromeClientImpl::canTakeFocus(FocusDirection)
    179 {
    180     // For now the browser can always take focus if we're not running layout
    181     // tests.
    182     return !layoutTestMode();
    183 }
    184 
    185 void ChromeClientImpl::takeFocus(FocusDirection direction)
    186 {
    187     if (!m_webView->client())
    188         return;
    189     if (direction == FocusDirectionBackward)
    190         m_webView->client()->focusPrevious();
    191     else
    192         m_webView->client()->focusNext();
    193 }
    194 
    195 void ChromeClientImpl::focusedNodeChanged(Node* node)
    196 {
    197     WebURL focus_url;
    198     if (node && node->isLink()) {
    199         // This HitTestResult hack is the easiest way to get a link URL out of a
    200         // WebCore::Node.
    201         HitTestResult hit_test(IntPoint(0, 0));
    202         // This cast must be valid because of the isLink() check.
    203         hit_test.setURLElement(reinterpret_cast<Element*>(node));
    204         if (hit_test.isLiveLink())
    205             focus_url = hit_test.absoluteLinkURL();
    206     }
    207     m_webView->client()->setKeyboardFocusURL(focus_url);
    208 }
    209 
    210 Page* ChromeClientImpl::createWindow(
    211     Frame* frame, const FrameLoadRequest& r, const WindowFeatures& features)
    212 {
    213     if (!m_webView->client())
    214         return 0;
    215 
    216     WebViewImpl* newView = static_cast<WebViewImpl*>(
    217         m_webView->client()->createView(WebFrameImpl::fromFrame(frame)));
    218     if (!newView)
    219         return 0;
    220 
    221     // The request is empty when we are just being asked to open a blank window.
    222     // This corresponds to window.open(""), for example.
    223     if (!r.resourceRequest().isEmpty()) {
    224         WrappedResourceRequest request(r.resourceRequest());
    225         newView->mainFrame()->loadRequest(request);
    226     }
    227 
    228     return newView->page();
    229 }
    230 
    231 static inline bool currentEventShouldCauseBackgroundTab(const WebInputEvent* inputEvent)
    232 {
    233     if (!inputEvent)
    234         return false;
    235 
    236     if (inputEvent->type != WebInputEvent::MouseUp)
    237         return false;
    238 
    239     const WebMouseEvent* mouseEvent = static_cast<const WebMouseEvent*>(inputEvent);
    240 
    241     WebNavigationPolicy policy;
    242     unsigned short buttonNumber;
    243     switch (mouseEvent->button) {
    244     case WebMouseEvent::ButtonLeft:
    245         buttonNumber = 0;
    246         break;
    247     case WebMouseEvent::ButtonMiddle:
    248         buttonNumber = 1;
    249         break;
    250     case WebMouseEvent::ButtonRight:
    251         buttonNumber = 2;
    252         break;
    253     default:
    254         return false;
    255     }
    256     bool ctrl = mouseEvent->modifiers & WebMouseEvent::ControlKey;
    257     bool shift = mouseEvent->modifiers & WebMouseEvent::ShiftKey;
    258     bool alt = mouseEvent->modifiers & WebMouseEvent::AltKey;
    259     bool meta = mouseEvent->modifiers & WebMouseEvent::MetaKey;
    260 
    261     if (!WebViewImpl::navigationPolicyFromMouseEvent(buttonNumber, ctrl, shift, alt, meta, &policy))
    262         return false;
    263 
    264     return policy == WebNavigationPolicyNewBackgroundTab;
    265 }
    266 
    267 void ChromeClientImpl::show()
    268 {
    269     if (!m_webView->client())
    270         return;
    271 
    272     // If our default configuration was modified by a script or wasn't
    273     // created by a user gesture, then show as a popup. Else, let this
    274     // new window be opened as a toplevel window.
    275     bool asPopup = !m_toolbarsVisible
    276         || !m_statusbarVisible
    277         || !m_scrollbarsVisible
    278         || !m_menubarVisible
    279         || !m_resizable;
    280 
    281     WebNavigationPolicy policy = WebNavigationPolicyNewForegroundTab;
    282     if (asPopup)
    283         policy = WebNavigationPolicyNewPopup;
    284     if (currentEventShouldCauseBackgroundTab(WebViewImpl::currentInputEvent()))
    285         policy = WebNavigationPolicyNewBackgroundTab;
    286 
    287     m_webView->client()->show(policy);
    288 }
    289 
    290 bool ChromeClientImpl::canRunModal()
    291 {
    292     return !!m_webView->client();
    293 }
    294 
    295 void ChromeClientImpl::runModal()
    296 {
    297     if (m_webView->client())
    298         m_webView->client()->runModal();
    299 }
    300 
    301 void ChromeClientImpl::setToolbarsVisible(bool value)
    302 {
    303     m_toolbarsVisible = value;
    304 }
    305 
    306 bool ChromeClientImpl::toolbarsVisible()
    307 {
    308     return m_toolbarsVisible;
    309 }
    310 
    311 void ChromeClientImpl::setStatusbarVisible(bool value)
    312 {
    313     m_statusbarVisible = value;
    314 }
    315 
    316 bool ChromeClientImpl::statusbarVisible()
    317 {
    318     return m_statusbarVisible;
    319 }
    320 
    321 void ChromeClientImpl::setScrollbarsVisible(bool value)
    322 {
    323     m_scrollbarsVisible = value;
    324     WebFrameImpl* web_frame = static_cast<WebFrameImpl*>(m_webView->mainFrame());
    325     if (web_frame)
    326         web_frame->setAllowsScrolling(value);
    327 }
    328 
    329 bool ChromeClientImpl::scrollbarsVisible()
    330 {
    331     return m_scrollbarsVisible;
    332 }
    333 
    334 void ChromeClientImpl::setMenubarVisible(bool value)
    335 {
    336     m_menubarVisible = value;
    337 }
    338 
    339 bool ChromeClientImpl::menubarVisible()
    340 {
    341     return m_menubarVisible;
    342 }
    343 
    344 void ChromeClientImpl::setResizable(bool value)
    345 {
    346     m_resizable = value;
    347 }
    348 
    349 void ChromeClientImpl::addMessageToConsole(MessageSource source,
    350                                            MessageType type,
    351                                            MessageLevel level,
    352                                            const String& message,
    353                                            unsigned lineNumber,
    354                                            const String& sourceID)
    355 {
    356     if (m_webView->client()) {
    357         m_webView->client()->didAddMessageToConsole(
    358             WebConsoleMessage(static_cast<WebConsoleMessage::Level>(level), message),
    359             sourceID,
    360             lineNumber);
    361     }
    362 }
    363 
    364 bool ChromeClientImpl::canRunBeforeUnloadConfirmPanel()
    365 {
    366     return !!m_webView->client();
    367 }
    368 
    369 bool ChromeClientImpl::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
    370 {
    371     if (m_webView->client()) {
    372         return m_webView->client()->runModalBeforeUnloadDialog(
    373             WebFrameImpl::fromFrame(frame), message);
    374     }
    375     return false;
    376 }
    377 
    378 void ChromeClientImpl::closeWindowSoon()
    379 {
    380     // Make sure this Page can no longer be found by JS.
    381     m_webView->page()->setGroupName(String());
    382 
    383     // Make sure that all loading is stopped.  Ensures that JS stops executing!
    384     m_webView->mainFrame()->stopLoading();
    385 
    386     if (m_webView->client())
    387         m_webView->client()->closeWidgetSoon();
    388 }
    389 
    390 // Although a Frame is passed in, we don't actually use it, since we
    391 // already know our own m_webView.
    392 void ChromeClientImpl::runJavaScriptAlert(Frame* frame, const String& message)
    393 {
    394     if (m_webView->client()) {
    395 #if USE(V8)
    396         // Before showing the JavaScript dialog, we give the proxy implementation
    397         // a chance to process any pending console messages.
    398         V8Proxy::processConsoleMessages();
    399 #endif
    400         m_webView->client()->runModalAlertDialog(
    401             WebFrameImpl::fromFrame(frame), message);
    402     }
    403 }
    404 
    405 // See comments for runJavaScriptAlert().
    406 bool ChromeClientImpl::runJavaScriptConfirm(Frame* frame, const String& message)
    407 {
    408     if (m_webView->client()) {
    409         return m_webView->client()->runModalConfirmDialog(
    410             WebFrameImpl::fromFrame(frame), message);
    411     }
    412     return false;
    413 }
    414 
    415 // See comments for runJavaScriptAlert().
    416 bool ChromeClientImpl::runJavaScriptPrompt(Frame* frame,
    417                                            const String& message,
    418                                            const String& defaultValue,
    419                                            String& result)
    420 {
    421     if (m_webView->client()) {
    422         WebString actualValue;
    423         bool ok = m_webView->client()->runModalPromptDialog(
    424             WebFrameImpl::fromFrame(frame),
    425             message,
    426             defaultValue,
    427             &actualValue);
    428         if (ok)
    429             result = actualValue;
    430         return ok;
    431     }
    432     return false;
    433 }
    434 
    435 void ChromeClientImpl::setStatusbarText(const String& message)
    436 {
    437     if (m_webView->client())
    438         m_webView->client()->setStatusText(message);
    439 }
    440 
    441 bool ChromeClientImpl::shouldInterruptJavaScript()
    442 {
    443     // FIXME: implement me
    444     return false;
    445 }
    446 
    447 bool ChromeClientImpl::tabsToLinks() const
    448 {
    449     // Returns true if anchors should accept keyboard focus with the tab key.
    450     // This method is used in a convoluted fashion by EventHandler::tabsToLinks.
    451     // It's a twisted path (self-evident, but more complicated than seems
    452     // necessary), but the net result is that returning true from here, on a
    453     // platform other than MAC or QT, lets anchors get keyboard focus.
    454     return m_webView->tabsToLinks();
    455 }
    456 
    457 IntRect ChromeClientImpl::windowResizerRect() const
    458 {
    459     IntRect result;
    460     if (m_webView->client())
    461         result = m_webView->client()->windowResizerRect();
    462     return result;
    463 }
    464 
    465 void ChromeClientImpl::repaint(
    466     const IntRect& paintRect, bool contentChanged, bool immediate,
    467     bool repaintContentOnly)
    468 {
    469     // Ignore spurious calls.
    470     if (!contentChanged || paintRect.isEmpty())
    471         return;
    472     if (m_webView->client())
    473         m_webView->client()->didInvalidateRect(paintRect);
    474 }
    475 
    476 void ChromeClientImpl::scroll(
    477     const IntSize& scrollDelta, const IntRect& scrollRect,
    478     const IntRect& clipRect)
    479 {
    480     if (m_webView->client()) {
    481         int dx = scrollDelta.width();
    482         int dy = scrollDelta.height();
    483         m_webView->client()->didScrollRect(dx, dy, clipRect);
    484     }
    485 }
    486 
    487 IntPoint ChromeClientImpl::screenToWindow(const IntPoint&) const
    488 {
    489     notImplemented();
    490     return IntPoint();
    491 }
    492 
    493 IntRect ChromeClientImpl::windowToScreen(const IntRect& rect) const
    494 {
    495     IntRect screenRect(rect);
    496 
    497     if (m_webView->client()) {
    498         WebRect windowRect = m_webView->client()->windowRect();
    499         screenRect.move(windowRect.x, windowRect.y);
    500     }
    501 
    502     return screenRect;
    503 }
    504 
    505 void ChromeClientImpl::contentsSizeChanged(Frame* frame, const IntSize& size) const
    506 {
    507     WebFrameImpl* webframe = WebFrameImpl::fromFrame(frame);
    508     if (webframe->client())
    509         webframe->client()->didChangeContentsSize(webframe, size);
    510 }
    511 
    512 void ChromeClientImpl::scrollbarsModeDidChange() const
    513 {
    514 }
    515 
    516 void ChromeClientImpl::mouseDidMoveOverElement(
    517     const HitTestResult& result, unsigned modifierFlags)
    518 {
    519     if (!m_webView->client())
    520         return;
    521     // Find out if the mouse is over a link, and if so, let our UI know...
    522     if (result.isLiveLink() && !result.absoluteLinkURL().string().isEmpty())
    523         m_webView->client()->setMouseOverURL(result.absoluteLinkURL());
    524     else
    525         m_webView->client()->setMouseOverURL(WebURL());
    526 }
    527 
    528 void ChromeClientImpl::setToolTip(const String& tooltipText, TextDirection dir)
    529 {
    530     if (!m_webView->client())
    531         return;
    532     WebTextDirection textDirection = (dir == RTL) ?
    533         WebTextDirectionRightToLeft :
    534         WebTextDirectionLeftToRight;
    535     m_webView->client()->setToolTipText(
    536         tooltipText, textDirection);
    537 }
    538 
    539 void ChromeClientImpl::print(Frame* frame)
    540 {
    541     if (m_webView->client())
    542         m_webView->client()->printPage(WebFrameImpl::fromFrame(frame));
    543 }
    544 
    545 void ChromeClientImpl::exceededDatabaseQuota(Frame* frame, const String& databaseName)
    546 {
    547     // Chromium users cannot currently change the default quota
    548 }
    549 
    550 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    551 void ChromeClientImpl::reachedMaxAppCacheSize(int64_t spaceNeeded)
    552 {
    553     ASSERT_NOT_REACHED();
    554 }
    555 #endif
    556 
    557 void ChromeClientImpl::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser)
    558 {
    559     WebViewClient* client = m_webView->client();
    560     if (!client)
    561         return;
    562 
    563     WebFileChooserParams params;
    564     params.multiSelect = fileChooser->allowsMultipleFiles();
    565     params.acceptTypes = fileChooser->acceptTypes();
    566     params.selectedFiles = fileChooser->filenames();
    567     if (params.selectedFiles.size() > 0)
    568         params.initialValue = params.selectedFiles[0];
    569     WebFileChooserCompletionImpl* chooserCompletion =
    570         new WebFileChooserCompletionImpl(fileChooser);
    571 
    572     if (client->runFileChooser(params, chooserCompletion))
    573         return;
    574 
    575     // Choosing failed, so do callback with an empty list.
    576     chooserCompletion->didChooseFile(WebVector<WebString>());
    577 }
    578 
    579 void ChromeClientImpl::popupOpened(PopupContainer* popupContainer,
    580                                    const IntRect& bounds,
    581                                    bool activatable,
    582                                    bool handleExternally)
    583 {
    584     if (!m_webView->client())
    585         return;
    586 
    587     WebWidget* webwidget;
    588     if (handleExternally) {
    589         WebPopupMenuInfo popupInfo;
    590         getPopupMenuInfo(popupContainer, &popupInfo);
    591         webwidget = m_webView->client()->createPopupMenu(popupInfo);
    592     } else
    593         webwidget = m_webView->client()->createPopupMenu(activatable);
    594 
    595     static_cast<WebPopupMenuImpl*>(webwidget)->Init(popupContainer, bounds);
    596 }
    597 
    598 void ChromeClientImpl::setCursor(const WebCursorInfo& cursor)
    599 {
    600     if (m_ignoreNextSetCursor) {
    601         m_ignoreNextSetCursor = false;
    602         return;
    603     }
    604 
    605     if (m_webView->client())
    606         m_webView->client()->didChangeCursor(cursor);
    607 }
    608 
    609 void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor)
    610 {
    611     setCursor(cursor);
    612 
    613     // Currently, Widget::setCursor is always called after this function in
    614     // EventHandler.cpp and since we don't want that we set a flag indicating
    615     // that the next SetCursor call is to be ignored.
    616     m_ignoreNextSetCursor = true;
    617 }
    618 
    619 void ChromeClientImpl::formStateDidChange(const Node* node)
    620 {
    621     // The current history item is not updated yet.  That happens lazily when
    622     // WebFrame::currentHistoryItem is requested.
    623     WebFrameImpl* webframe = WebFrameImpl::fromFrame(node->document()->frame());
    624     if (webframe->client())
    625         webframe->client()->didUpdateCurrentHistoryItem(webframe);
    626 }
    627 
    628 void ChromeClientImpl::getPopupMenuInfo(PopupContainer* popupContainer,
    629                                         WebPopupMenuInfo* info)
    630 {
    631     const Vector<PopupItem*>& inputItems = popupContainer->popupData();
    632 
    633     WebVector<WebPopupMenuInfo::Item> outputItems(inputItems.size());
    634 
    635     for (size_t i = 0; i < inputItems.size(); ++i) {
    636         const PopupItem& inputItem = *inputItems[i];
    637         WebPopupMenuInfo::Item& outputItem = outputItems[i];
    638 
    639         outputItem.label = inputItem.label;
    640         outputItem.enabled = inputItem.enabled;
    641 
    642         switch (inputItem.type) {
    643         case PopupItem::TypeOption:
    644             outputItem.type = WebPopupMenuInfo::Item::Option;
    645             break;
    646         case PopupItem::TypeGroup:
    647             outputItem.type = WebPopupMenuInfo::Item::Group;
    648             break;
    649         case PopupItem::TypeSeparator:
    650             outputItem.type = WebPopupMenuInfo::Item::Separator;
    651             break;
    652         default:
    653             ASSERT_NOT_REACHED();
    654         }
    655     }
    656 
    657     info->itemHeight = popupContainer->menuItemHeight();
    658     info->selectedIndex = popupContainer->selectedIndex();
    659     info->items.swap(outputItems);
    660 }
    661 
    662 void ChromeClientImpl::didChangeAccessibilityObjectState(AccessibilityObject* obj)
    663 {
    664     // Alert assistive technology about the accessibility object state change
    665     if (obj)
    666         m_webView->client()->didChangeAccessibilityObjectState(WebAccessibilityObject(obj));
    667 }
    668 
    669 
    670 #if ENABLE(NOTIFICATIONS)
    671 NotificationPresenter* ChromeClientImpl::notificationPresenter() const
    672 {
    673     return m_webView->notificationPresenterImpl();
    674 }
    675 #endif
    676 
    677 } // namespace WebKit
    678