Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2010 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 "WebViewImpl.h"
     33 
     34 #include "AutoFillPopupMenuClient.h"
     35 #include "AXObjectCache.h"
     36 #include "BackForwardListChromium.h"
     37 #include "CSSStyleSelector.h"
     38 #include "CSSValueKeywords.h"
     39 #include "Chrome.h"
     40 #include "ColorSpace.h"
     41 #include "CompositionUnderlineVectorBuilder.h"
     42 #include "ContextMenu.h"
     43 #include "ContextMenuController.h"
     44 #include "ContextMenuItem.h"
     45 #include "Cursor.h"
     46 #include "DOMUtilitiesPrivate.h"
     47 #include "DeviceOrientationClientProxy.h"
     48 #include "Document.h"
     49 #include "DocumentLoader.h"
     50 #include "DragController.h"
     51 #include "DragData.h"
     52 #include "DragScrollTimer.h"
     53 #include "Editor.h"
     54 #include "EventHandler.h"
     55 #include "Extensions3D.h"
     56 #include "FocusController.h"
     57 #include "FontDescription.h"
     58 #include "FrameLoader.h"
     59 #include "FrameTree.h"
     60 #include "FrameView.h"
     61 #include "GeolocationClientProxy.h"
     62 #include "GraphicsContext.h"
     63 #include "GraphicsContext3D.h"
     64 #include "GraphicsContext3DInternal.h"
     65 #include "HTMLInputElement.h"
     66 #include "HTMLMediaElement.h"
     67 #include "HTMLNames.h"
     68 #include "HitTestResult.h"
     69 #include "Image.h"
     70 #include "ImageBuffer.h"
     71 #include "InspectorController.h"
     72 #include "KeyboardCodes.h"
     73 #include "KeyboardEvent.h"
     74 #include "MIMETypeRegistry.h"
     75 #include "NodeRenderStyle.h"
     76 #include "Page.h"
     77 #include "PageGroup.h"
     78 #include "PageGroupLoadDeferrer.h"
     79 #include "Pasteboard.h"
     80 #include "PlatformContextSkia.h"
     81 #include "PlatformKeyboardEvent.h"
     82 #include "PlatformMouseEvent.h"
     83 #include "PlatformThemeChromiumGtk.h"
     84 #include "PlatformWheelEvent.h"
     85 #include "PopupMenuChromium.h"
     86 #include "PopupMenuClient.h"
     87 #include "ProgressTracker.h"
     88 #include "RenderView.h"
     89 #include "ResourceHandle.h"
     90 #include "SecurityOrigin.h"
     91 #include "SelectionController.h"
     92 #include "Settings.h"
     93 #include "SpeechInputClientImpl.h"
     94 #include "Timer.h"
     95 #include "TraceEvent.h"
     96 #include "TypingCommand.h"
     97 #include "UserGestureIndicator.h"
     98 #include "Vector.h"
     99 #include "WebAccessibilityObject.h"
    100 #include "WebAutoFillClient.h"
    101 #include "WebDevToolsAgentImpl.h"
    102 #include "WebDevToolsAgentPrivate.h"
    103 #include "WebDragData.h"
    104 #include "WebFrameImpl.h"
    105 #include "WebGraphicsContext3D.h"
    106 #include "WebImage.h"
    107 #include "WebInputElement.h"
    108 #include "WebInputEvent.h"
    109 #include "WebInputEventConversion.h"
    110 #include "WebKit.h"
    111 #include "WebKitClient.h"
    112 #include "WebMediaPlayerAction.h"
    113 #include "WebNode.h"
    114 #include "WebPlugin.h"
    115 #include "WebPluginContainerImpl.h"
    116 #include "WebPoint.h"
    117 #include "WebPopupMenuImpl.h"
    118 #include "WebRect.h"
    119 #include "WebRuntimeFeatures.h"
    120 #include "WebSettingsImpl.h"
    121 #include "WebString.h"
    122 #include "WebVector.h"
    123 #include "WebViewClient.h"
    124 #include "cc/CCHeadsUpDisplay.h"
    125 #include <wtf/ByteArray.h>
    126 #include <wtf/CurrentTime.h>
    127 #include <wtf/RefPtr.h>
    128 
    129 #if USE(CG)
    130 #include <CoreGraphics/CGBitmapContext.h>
    131 #include <CoreGraphics/CGContext.h>
    132 #endif
    133 
    134 #if OS(WINDOWS)
    135 #include "RenderThemeChromiumWin.h"
    136 #else
    137 #if OS(LINUX) || OS(FREEBSD)
    138 #include "RenderThemeChromiumLinux.h"
    139 #endif
    140 #include "RenderTheme.h"
    141 #endif
    142 
    143 // Get rid of WTF's pow define so we can use std::pow.
    144 #undef pow
    145 #include <cmath> // for std::pow
    146 
    147 using namespace WebCore;
    148 
    149 namespace {
    150 
    151 GraphicsContext3D::Attributes getCompositorContextAttributes()
    152 {
    153     // Explicitly disable antialiasing for the compositor. As of the time of
    154     // this writing, the only platform that supported antialiasing for the
    155     // compositor was Mac OS X, because the on-screen OpenGL context creation
    156     // code paths on Windows and Linux didn't yet have multisampling support.
    157     // Mac OS X essentially always behaves as though it's rendering offscreen.
    158     // Multisampling has a heavy cost especially on devices with relatively low
    159     // fill rate like most notebooks, and the Mac implementation would need to
    160     // be optimized to resolve directly into the IOSurface shared between the
    161     // GPU and browser processes. For these reasons and to avoid platform
    162     // disparities we explicitly disable antialiasing.
    163     GraphicsContext3D::Attributes attributes;
    164     attributes.antialias = false;
    165     return attributes;
    166 }
    167 
    168 } // anonymous namespace
    169 
    170 namespace WebKit {
    171 
    172 // Change the text zoom level by kTextSizeMultiplierRatio each time the user
    173 // zooms text in or out (ie., change by 20%).  The min and max values limit
    174 // text zoom to half and 3x the original text size.  These three values match
    175 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm
    176 const double WebView::textSizeMultiplierRatio = 1.2;
    177 const double WebView::minTextSizeMultiplier = 0.5;
    178 const double WebView::maxTextSizeMultiplier = 3.0;
    179 
    180 
    181 // The group name identifies a namespace of pages.  Page group is used on OSX
    182 // for some programs that use HTML views to display things that don't seem like
    183 // web pages to the user (so shouldn't have visited link coloring).  We only use
    184 // one page group.
    185 const char* pageGroupName = "default";
    186 
    187 // Used to defer all page activity in cases where the embedder wishes to run
    188 // a nested event loop. Using a stack enables nesting of message loop invocations.
    189 static Vector<PageGroupLoadDeferrer*> pageGroupLoadDeferrerStack;
    190 
    191 // Ensure that the WebDragOperation enum values stay in sync with the original
    192 // DragOperation constants.
    193 #define COMPILE_ASSERT_MATCHING_ENUM(coreName) \
    194     COMPILE_ASSERT(int(coreName) == int(Web##coreName), dummy##coreName)
    195 COMPILE_ASSERT_MATCHING_ENUM(DragOperationNone);
    196 COMPILE_ASSERT_MATCHING_ENUM(DragOperationCopy);
    197 COMPILE_ASSERT_MATCHING_ENUM(DragOperationLink);
    198 COMPILE_ASSERT_MATCHING_ENUM(DragOperationGeneric);
    199 COMPILE_ASSERT_MATCHING_ENUM(DragOperationPrivate);
    200 COMPILE_ASSERT_MATCHING_ENUM(DragOperationMove);
    201 COMPILE_ASSERT_MATCHING_ENUM(DragOperationDelete);
    202 COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery);
    203 
    204 static const PopupContainerSettings autoFillPopupSettings = {
    205     false, // setTextOnIndexChange
    206     false, // acceptOnAbandon
    207     true, // loopSelectionNavigation
    208     false // restrictWidthOfListBox (For security reasons show the entire entry
    209           // so the user doesn't enter information he did not intend to.)
    210 };
    211 
    212 static bool shouldUseExternalPopupMenus = false;
    213 
    214 // WebView ----------------------------------------------------------------
    215 
    216 WebView* WebView::create(WebViewClient* client)
    217 {
    218     // Keep runtime flag for device motion turned off until it's implemented.
    219     WebRuntimeFeatures::enableDeviceMotion(false);
    220 
    221     // Pass the WebViewImpl's self-reference to the caller.
    222     return adoptRef(new WebViewImpl(client)).leakRef();
    223 }
    224 
    225 void WebView::setUseExternalPopupMenus(bool useExternalPopupMenus)
    226 {
    227     shouldUseExternalPopupMenus = useExternalPopupMenus;
    228 }
    229 
    230 void WebView::updateVisitedLinkState(unsigned long long linkHash)
    231 {
    232     Page::visitedStateChanged(PageGroup::pageGroup(pageGroupName), linkHash);
    233 }
    234 
    235 void WebView::resetVisitedLinkState()
    236 {
    237     Page::allVisitedStateChanged(PageGroup::pageGroup(pageGroupName));
    238 }
    239 
    240 void WebView::willEnterModalLoop()
    241 {
    242     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
    243     ASSERT(pageGroup);
    244 
    245     if (pageGroup->pages().isEmpty())
    246         pageGroupLoadDeferrerStack.append(static_cast<PageGroupLoadDeferrer*>(0));
    247     else {
    248         // Pick any page in the page group since we are deferring all pages.
    249         pageGroupLoadDeferrerStack.append(new PageGroupLoadDeferrer(*pageGroup->pages().begin(), true));
    250     }
    251 }
    252 
    253 void WebView::didExitModalLoop()
    254 {
    255     ASSERT(pageGroupLoadDeferrerStack.size());
    256 
    257     delete pageGroupLoadDeferrerStack.last();
    258     pageGroupLoadDeferrerStack.removeLast();
    259 }
    260 
    261 void WebViewImpl::initializeMainFrame(WebFrameClient* frameClient)
    262 {
    263     // NOTE: The WebFrameImpl takes a reference to itself within InitMainFrame
    264     // and releases that reference once the corresponding Frame is destroyed.
    265     RefPtr<WebFrameImpl> frame = WebFrameImpl::create(frameClient);
    266 
    267     frame->initializeAsMainFrame(this);
    268 
    269     // Restrict the access to the local file system
    270     // (see WebView.mm WebView::_commonInitializationWithFrameName).
    271     SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalOnly);
    272 }
    273 
    274 void WebViewImpl::setDevToolsAgentClient(WebDevToolsAgentClient* devToolsClient)
    275 {
    276     if (devToolsClient)
    277         m_devToolsAgent = new WebDevToolsAgentImpl(this, devToolsClient);
    278     else
    279         m_devToolsAgent.clear();
    280 }
    281 
    282 void WebViewImpl::setAutoFillClient(WebAutoFillClient* autoFillClient)
    283 {
    284     m_autoFillClient = autoFillClient;
    285 }
    286 
    287 void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient)
    288 {
    289     m_spellCheckClient = spellCheckClient;
    290 }
    291 
    292 WebViewImpl::WebViewImpl(WebViewClient* client)
    293     : m_client(client)
    294     , m_autoFillClient(0)
    295     , m_spellCheckClient(0)
    296     , m_chromeClientImpl(this)
    297     , m_contextMenuClientImpl(this)
    298     , m_dragClientImpl(this)
    299     , m_editorClientImpl(this)
    300     , m_inspectorClientImpl(this)
    301     , m_observedNewNavigation(false)
    302 #ifndef NDEBUG
    303     , m_newNavigationLoader(0)
    304 #endif
    305     , m_zoomLevel(0)
    306     , m_minimumZoomLevel(zoomFactorToZoomLevel(minTextSizeMultiplier))
    307     , m_maximumZoomLevel(zoomFactorToZoomLevel(maxTextSizeMultiplier))
    308     , m_contextMenuAllowed(false)
    309     , m_doingDragAndDrop(false)
    310     , m_ignoreInputEvents(false)
    311     , m_suppressNextKeypressEvent(false)
    312     , m_initialNavigationPolicy(WebNavigationPolicyIgnore)
    313     , m_imeAcceptEvents(true)
    314     , m_operationsAllowed(WebDragOperationNone)
    315     , m_dragOperation(WebDragOperationNone)
    316     , m_autoFillPopupShowing(false)
    317     , m_autoFillPopupClient(0)
    318     , m_autoFillPopup(0)
    319     , m_isTransparent(false)
    320     , m_tabsToLinks(false)
    321     , m_dragScrollTimer(new DragScrollTimer())
    322 #if USE(ACCELERATED_COMPOSITING)
    323     , m_layerRenderer(0)
    324     , m_isAcceleratedCompositingActive(false)
    325     , m_compositorCreationFailed(false)
    326     , m_recreatingGraphicsContext(false)
    327 #endif
    328 #if ENABLE(INPUT_SPEECH)
    329     , m_speechInputClient(SpeechInputClientImpl::create(client))
    330 #endif
    331     , m_deviceOrientationClientProxy(new DeviceOrientationClientProxy(client ? client->deviceOrientationClient() : 0))
    332     , m_geolocationClientProxy(new GeolocationClientProxy(client ? client->geolocationClient() : 0))
    333 {
    334     // WebKit/win/WebView.cpp does the same thing, except they call the
    335     // KJS specific wrapper around this method. We need to have threading
    336     // initialized because CollatorICU requires it.
    337     WTF::initializeThreading();
    338     WTF::initializeMainThread();
    339 
    340     // set to impossible point so we always get the first mouse pos
    341     m_lastMousePosition = WebPoint(-1, -1);
    342 
    343     Page::PageClients pageClients;
    344     pageClients.chromeClient = &m_chromeClientImpl;
    345     pageClients.contextMenuClient = &m_contextMenuClientImpl;
    346     pageClients.editorClient = &m_editorClientImpl;
    347     pageClients.dragClient = &m_dragClientImpl;
    348     pageClients.inspectorClient = &m_inspectorClientImpl;
    349 #if ENABLE(INPUT_SPEECH)
    350     pageClients.speechInputClient = m_speechInputClient.get();
    351 #endif
    352     pageClients.deviceOrientationClient = m_deviceOrientationClientProxy.get();
    353     pageClients.geolocationClient = m_geolocationClientProxy.get();
    354     pageClients.backForwardClient = BackForwardListChromium::create(this);
    355 
    356     m_page.set(new Page(pageClients));
    357 
    358     m_geolocationClientProxy->setController(m_page->geolocationController());
    359 
    360     m_page->setGroupName(pageGroupName);
    361 
    362     m_inspectorSettingsMap.set(new SettingsMap);
    363 }
    364 
    365 WebViewImpl::~WebViewImpl()
    366 {
    367     ASSERT(!m_page);
    368 }
    369 
    370 RenderTheme* WebViewImpl::theme() const
    371 {
    372     return m_page.get() ? m_page->theme() : RenderTheme::defaultTheme().get();
    373 }
    374 
    375 WebFrameImpl* WebViewImpl::mainFrameImpl()
    376 {
    377     return m_page.get() ? WebFrameImpl::fromFrame(m_page->mainFrame()) : 0;
    378 }
    379 
    380 bool WebViewImpl::tabKeyCyclesThroughElements() const
    381 {
    382     ASSERT(m_page.get());
    383     return m_page->tabKeyCyclesThroughElements();
    384 }
    385 
    386 void WebViewImpl::setTabKeyCyclesThroughElements(bool value)
    387 {
    388     if (m_page)
    389         m_page->setTabKeyCyclesThroughElements(value);
    390 }
    391 
    392 void WebViewImpl::mouseMove(const WebMouseEvent& event)
    393 {
    394     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    395         return;
    396 
    397     m_lastMousePosition = WebPoint(event.x, event.y);
    398 
    399     // We call mouseMoved here instead of handleMouseMovedEvent because we need
    400     // our ChromeClientImpl to receive changes to the mouse position and
    401     // tooltip text, and mouseMoved handles all of that.
    402     mainFrameImpl()->frame()->eventHandler()->mouseMoved(
    403         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
    404 }
    405 
    406 void WebViewImpl::mouseLeave(const WebMouseEvent& event)
    407 {
    408     // This event gets sent as the main frame is closing.  In that case, just
    409     // ignore it.
    410     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    411         return;
    412 
    413     m_client->setMouseOverURL(WebURL());
    414 
    415     mainFrameImpl()->frame()->eventHandler()->handleMouseMoveEvent(
    416         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
    417 }
    418 
    419 void WebViewImpl::mouseDown(const WebMouseEvent& event)
    420 {
    421     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    422         return;
    423 
    424     // If there is a select popup open, close it as the user is clicking on
    425     // the page (outside of the popup).  We also save it so we can prevent a
    426     // click on the select element from immediately reopening the popup.
    427     RefPtr<WebCore::PopupContainer> selectPopup;
    428     if (event.button == WebMouseEvent::ButtonLeft) {
    429         selectPopup = m_selectPopup;
    430         hideSelectPopup();
    431         ASSERT(!m_selectPopup);
    432     }
    433 
    434     m_lastMouseDownPoint = WebPoint(event.x, event.y);
    435 
    436     RefPtr<Node> clickedNode;
    437     if (event.button == WebMouseEvent::ButtonLeft) {
    438         IntPoint point(event.x, event.y);
    439         point = m_page->mainFrame()->view()->windowToContents(point);
    440         HitTestResult result(m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false));
    441         Node* hitNode = result.innerNonSharedNode();
    442 
    443         // Take capture on a mouse down on a plugin so we can send it mouse events.
    444         if (hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject())
    445             m_mouseCaptureNode = hitNode;
    446 
    447         // If a text field that has focus is clicked again, we should display the
    448         // AutoFill popup.
    449         RefPtr<Node> focusedNode = focusedWebCoreNode();
    450         if (focusedNode.get() && toHTMLInputElement(focusedNode.get())) {
    451             if (hitNode == focusedNode) {
    452                 // Already focused text field was clicked, let's remember this.  If
    453                 // focus has not changed after the mouse event is processed, we'll
    454                 // trigger the autocomplete.
    455                 clickedNode = focusedNode;
    456             }
    457         }
    458     }
    459 
    460     mainFrameImpl()->frame()->loader()->resetMultipleFormSubmissionProtection();
    461 
    462     mainFrameImpl()->frame()->eventHandler()->handleMousePressEvent(
    463         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
    464 
    465     if (clickedNode.get() && clickedNode == focusedWebCoreNode()) {
    466         // Focus has not changed, show the AutoFill popup.
    467         static_cast<EditorClientImpl*>(m_page->editorClient())->
    468             showFormAutofillForNode(clickedNode.get());
    469     }
    470     if (m_selectPopup && m_selectPopup == selectPopup) {
    471         // That click triggered a select popup which is the same as the one that
    472         // was showing before the click.  It means the user clicked the select
    473         // while the popup was showing, and as a result we first closed then
    474         // immediately reopened the select popup.  It needs to be closed.
    475         hideSelectPopup();
    476     }
    477 
    478     // Dispatch the contextmenu event regardless of if the click was swallowed.
    479     // On Windows, we handle it on mouse up, not down.
    480 #if OS(DARWIN)
    481     if (event.button == WebMouseEvent::ButtonRight
    482         || (event.button == WebMouseEvent::ButtonLeft
    483             && event.modifiers & WebMouseEvent::ControlKey))
    484         mouseContextMenu(event);
    485 #elif OS(LINUX) || OS(FREEBSD)
    486     if (event.button == WebMouseEvent::ButtonRight)
    487         mouseContextMenu(event);
    488 #endif
    489 }
    490 
    491 void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
    492 {
    493     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    494         return;
    495 
    496     m_page->contextMenuController()->clearContextMenu();
    497 
    498     PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), event);
    499 
    500     // Find the right target frame. See issue 1186900.
    501     HitTestResult result = hitTestResultForWindowPos(pme.pos());
    502     Frame* targetFrame;
    503     if (result.innerNonSharedNode())
    504         targetFrame = result.innerNonSharedNode()->document()->frame();
    505     else
    506         targetFrame = m_page->focusController()->focusedOrMainFrame();
    507 
    508 #if OS(WINDOWS)
    509     targetFrame->view()->setCursor(pointerCursor());
    510 #endif
    511 
    512     m_contextMenuAllowed = true;
    513     targetFrame->eventHandler()->sendContextMenuEvent(pme);
    514     m_contextMenuAllowed = false;
    515     // Actually showing the context menu is handled by the ContextMenuClient
    516     // implementation...
    517 }
    518 
    519 void WebViewImpl::mouseUp(const WebMouseEvent& event)
    520 {
    521     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    522         return;
    523 
    524 #if OS(LINUX) || OS(FREEBSD)
    525     // If the event was a middle click, attempt to copy text into the focused
    526     // frame. We execute this before we let the page have a go at the event
    527     // because the page may change what is focused during in its event handler.
    528     //
    529     // This code is in the mouse up handler. There is some debate about putting
    530     // this here, as opposed to the mouse down handler.
    531     //   xterm: pastes on up.
    532     //   GTK: pastes on down.
    533     //   Firefox: pastes on up.
    534     //   Midori: couldn't paste at all with 0.1.2
    535     //
    536     // There is something of a webcompat angle to this well, as highlighted by
    537     // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
    538     // down then the text is pasted just before the onclick handler runs and
    539     // clears the text box. So it's important this happens after the
    540     // handleMouseReleaseEvent() earlier in this function
    541     if (event.button == WebMouseEvent::ButtonMiddle) {
    542         Frame* focused = focusedWebCoreFrame();
    543         FrameView* view = m_page->mainFrame()->view();
    544         IntPoint clickPoint(m_lastMouseDownPoint.x, m_lastMouseDownPoint.y);
    545         IntPoint contentPoint = view->windowToContents(clickPoint);
    546         HitTestResult hitTestResult = focused->eventHandler()->hitTestResultAtPoint(contentPoint, false, false, ShouldHitTestScrollbars);
    547         // We don't want to send a paste when middle clicking a scroll bar or a
    548         // link (which will navigate later in the code).  The main scrollbars
    549         // have to be handled separately.
    550         if (!hitTestResult.scrollbar() && !hitTestResult.isLiveLink() && focused && !view->scrollbarAtPoint(clickPoint)) {
    551             Editor* editor = focused->editor();
    552             Pasteboard* pasteboard = Pasteboard::generalPasteboard();
    553             bool oldSelectionMode = pasteboard->isSelectionMode();
    554             pasteboard->setSelectionMode(true);
    555             editor->command(AtomicString("Paste")).execute();
    556             pasteboard->setSelectionMode(oldSelectionMode);
    557         }
    558     }
    559 #endif
    560 
    561     mainFrameImpl()->frame()->eventHandler()->handleMouseReleaseEvent(
    562         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
    563 
    564 #if OS(WINDOWS)
    565     // Dispatch the contextmenu event regardless of if the click was swallowed.
    566     // On Mac/Linux, we handle it on mouse down, not up.
    567     if (event.button == WebMouseEvent::ButtonRight)
    568         mouseContextMenu(event);
    569 #endif
    570 }
    571 
    572 bool WebViewImpl::mouseWheel(const WebMouseWheelEvent& event)
    573 {
    574     PlatformWheelEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
    575     return mainFrameImpl()->frame()->eventHandler()->handleWheelEvent(platformEvent);
    576 }
    577 
    578 bool WebViewImpl::keyEvent(const WebKeyboardEvent& event)
    579 {
    580     ASSERT((event.type == WebInputEvent::RawKeyDown)
    581         || (event.type == WebInputEvent::KeyDown)
    582         || (event.type == WebInputEvent::KeyUp));
    583 
    584     // Please refer to the comments explaining the m_suppressNextKeypressEvent
    585     // member.
    586     // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
    587     // Webkit. A keyDown event is typically associated with a keyPress(char)
    588     // event and a keyUp event. We reset this flag here as this is a new keyDown
    589     // event.
    590     m_suppressNextKeypressEvent = false;
    591 
    592     // Give any select popup a chance at consuming the key event.
    593     if (selectPopupHandleKeyEvent(event))
    594         return true;
    595 
    596     // Give Autocomplete a chance to consume the key events it is interested in.
    597     if (autocompleteHandleKeyEvent(event))
    598         return true;
    599 
    600     Frame* frame = focusedWebCoreFrame();
    601     if (!frame)
    602         return false;
    603 
    604     EventHandler* handler = frame->eventHandler();
    605     if (!handler)
    606         return keyEventDefault(event);
    607 
    608 #if OS(WINDOWS) || OS(LINUX) || OS(FREEBSD)
    609     const WebInputEvent::Type contextMenuTriggeringEventType =
    610 #if OS(WINDOWS)
    611         WebInputEvent::KeyUp;
    612 #elif OS(LINUX) || OS(FREEBSD)
    613         WebInputEvent::RawKeyDown;
    614 #endif
    615 
    616     bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS;
    617     bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10;
    618     if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) {
    619         sendContextMenuEvent(event);
    620         return true;
    621     }
    622 #endif // OS(WINDOWS) || OS(LINUX) || OS(FREEBSD)
    623 
    624     PlatformKeyboardEventBuilder evt(event);
    625 
    626     if (handler->keyEvent(evt)) {
    627         if (WebInputEvent::RawKeyDown == event.type) {
    628             // Suppress the next keypress event unless the focused node is a plug-in node.
    629             // (Flash needs these keypress events to handle non-US keyboards.)
    630             Node* node = frame->document()->focusedNode();
    631             if (!node || !node->renderer() || !node->renderer()->isEmbeddedObject())
    632                 m_suppressNextKeypressEvent = true;
    633         }
    634         return true;
    635     }
    636 
    637     return keyEventDefault(event);
    638 }
    639 
    640 bool WebViewImpl::selectPopupHandleKeyEvent(const WebKeyboardEvent& event)
    641 {
    642     if (!m_selectPopup)
    643         return false;
    644 
    645     return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
    646 }
    647 
    648 bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event)
    649 {
    650     if (!m_autoFillPopupShowing
    651         // Home and End should be left to the text field to process.
    652         || event.windowsKeyCode == VKEY_HOME
    653         || event.windowsKeyCode == VKEY_END)
    654       return false;
    655 
    656     // Pressing delete triggers the removal of the selected suggestion from the DB.
    657     if (event.windowsKeyCode == VKEY_DELETE
    658         && m_autoFillPopup->selectedIndex() != -1) {
    659         Node* node = focusedWebCoreNode();
    660         if (!node || (node->nodeType() != Node::ELEMENT_NODE)) {
    661             ASSERT_NOT_REACHED();
    662             return false;
    663         }
    664         Element* element = static_cast<Element*>(node);
    665         if (!element->hasLocalName(HTMLNames::inputTag)) {
    666             ASSERT_NOT_REACHED();
    667             return false;
    668         }
    669 
    670         int selectedIndex = m_autoFillPopup->selectedIndex();
    671 
    672         if (!m_autoFillPopupClient->canRemoveSuggestionAtIndex(selectedIndex))
    673             return false;
    674 
    675         WebString name = WebInputElement(static_cast<HTMLInputElement*>(element)).nameForAutofill();
    676         WebString value = m_autoFillPopupClient->itemText(selectedIndex);
    677         m_autoFillClient->removeAutocompleteSuggestion(name, value);
    678         // Update the entries in the currently showing popup to reflect the
    679         // deletion.
    680         m_autoFillPopupClient->removeSuggestionAtIndex(selectedIndex);
    681         refreshAutoFillPopup();
    682         return false;
    683     }
    684 
    685     if (!m_autoFillPopup->isInterestedInEventForKey(event.windowsKeyCode))
    686         return false;
    687 
    688     if (m_autoFillPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event))) {
    689         // We need to ignore the next Char event after this otherwise pressing
    690         // enter when selecting an item in the menu will go to the page.
    691         if (WebInputEvent::RawKeyDown == event.type)
    692             m_suppressNextKeypressEvent = true;
    693         return true;
    694     }
    695 
    696     return false;
    697 }
    698 
    699 bool WebViewImpl::charEvent(const WebKeyboardEvent& event)
    700 {
    701     ASSERT(event.type == WebInputEvent::Char);
    702 
    703     // Please refer to the comments explaining the m_suppressNextKeypressEvent
    704     // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
    705     // handled by Webkit. A keyDown event is typically associated with a
    706     // keyPress(char) event and a keyUp event. We reset this flag here as it
    707     // only applies to the current keyPress event.
    708     bool suppress = m_suppressNextKeypressEvent;
    709     m_suppressNextKeypressEvent = false;
    710 
    711     Frame* frame = focusedWebCoreFrame();
    712     if (!frame)
    713         return suppress;
    714 
    715     EventHandler* handler = frame->eventHandler();
    716     if (!handler)
    717         return suppress || keyEventDefault(event);
    718 
    719     PlatformKeyboardEventBuilder evt(event);
    720     if (!evt.isCharacterKey())
    721         return true;
    722 
    723     // Accesskeys are triggered by char events and can't be suppressed.
    724     if (handler->handleAccessKey(evt))
    725         return true;
    726 
    727     // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
    728     // the eventHandler::keyEvent. We mimic this behavior on all platforms since
    729     // for now we are converting other platform's key events to windows key
    730     // events.
    731     if (evt.isSystemKey())
    732         return false;
    733 
    734     if (!suppress && !handler->keyEvent(evt))
    735         return keyEventDefault(event);
    736 
    737     return true;
    738 }
    739 
    740 #if ENABLE(TOUCH_EVENTS)
    741 bool WebViewImpl::touchEvent(const WebTouchEvent& event)
    742 {
    743     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    744         return false;
    745 
    746     PlatformTouchEventBuilder touchEventBuilder(mainFrameImpl()->frameView(), event);
    747     return mainFrameImpl()->frame()->eventHandler()->handleTouchEvent(touchEventBuilder);
    748 }
    749 #endif
    750 
    751 #if OS(WINDOWS) || OS(LINUX) || OS(FREEBSD)
    752 // Mac has no way to open a context menu based on a keyboard event.
    753 bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
    754 {
    755     // The contextMenuController() holds onto the last context menu that was
    756     // popped up on the page until a new one is created. We need to clear
    757     // this menu before propagating the event through the DOM so that we can
    758     // detect if we create a new menu for this event, since we won't create
    759     // a new menu if the DOM swallows the event and the defaultEventHandler does
    760     // not run.
    761     page()->contextMenuController()->clearContextMenu();
    762 
    763     m_contextMenuAllowed = true;
    764     Frame* focusedFrame = page()->focusController()->focusedOrMainFrame();
    765     bool handled = focusedFrame->eventHandler()->sendContextMenuEventForKey();
    766     m_contextMenuAllowed = false;
    767     return handled;
    768 }
    769 #endif
    770 
    771 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
    772 {
    773     Frame* frame = focusedWebCoreFrame();
    774     if (!frame)
    775         return false;
    776 
    777     switch (event.type) {
    778     case WebInputEvent::Char:
    779         if (event.windowsKeyCode == VKEY_SPACE) {
    780             int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
    781             return scrollViewWithKeyboard(keyCode, event.modifiers);
    782         }
    783         break;
    784     case WebInputEvent::RawKeyDown:
    785         if (event.modifiers == WebInputEvent::ControlKey) {
    786             switch (event.windowsKeyCode) {
    787 #if !OS(DARWIN)
    788             case 'A':
    789                 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
    790                 return true;
    791             case VKEY_INSERT:
    792             case 'C':
    793                 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
    794                 return true;
    795 #endif
    796             // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
    797             // key combinations which affect scrolling. Safari is buggy in the
    798             // sense that it scrolls the page for all Ctrl+scrolling key
    799             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
    800             case VKEY_HOME:
    801             case VKEY_END:
    802                 break;
    803             default:
    804                 return false;
    805             }
    806         }
    807         if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
    808             return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
    809         break;
    810     default:
    811         break;
    812     }
    813     return false;
    814 }
    815 
    816 bool WebViewImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
    817 {
    818     ScrollDirection scrollDirection;
    819     ScrollGranularity scrollGranularity;
    820 #if OS(DARWIN)
    821     // Control-Up/Down should be PageUp/Down on Mac.
    822     if (modifiers & WebMouseEvent::ControlKey) {
    823       if (keyCode == VKEY_UP)
    824         keyCode = VKEY_PRIOR;
    825       else if (keyCode == VKEY_DOWN)
    826         keyCode = VKEY_NEXT;
    827     }
    828 #endif
    829     if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
    830         return false;
    831     return propagateScroll(scrollDirection, scrollGranularity);
    832 }
    833 
    834 bool WebViewImpl::mapKeyCodeForScroll(int keyCode,
    835                                       WebCore::ScrollDirection* scrollDirection,
    836                                       WebCore::ScrollGranularity* scrollGranularity)
    837 {
    838     switch (keyCode) {
    839     case VKEY_LEFT:
    840         *scrollDirection = ScrollLeft;
    841         *scrollGranularity = ScrollByLine;
    842         break;
    843     case VKEY_RIGHT:
    844         *scrollDirection = ScrollRight;
    845         *scrollGranularity = ScrollByLine;
    846         break;
    847     case VKEY_UP:
    848         *scrollDirection = ScrollUp;
    849         *scrollGranularity = ScrollByLine;
    850         break;
    851     case VKEY_DOWN:
    852         *scrollDirection = ScrollDown;
    853         *scrollGranularity = ScrollByLine;
    854         break;
    855     case VKEY_HOME:
    856         *scrollDirection = ScrollUp;
    857         *scrollGranularity = ScrollByDocument;
    858         break;
    859     case VKEY_END:
    860         *scrollDirection = ScrollDown;
    861         *scrollGranularity = ScrollByDocument;
    862         break;
    863     case VKEY_PRIOR:  // page up
    864         *scrollDirection = ScrollUp;
    865         *scrollGranularity = ScrollByPage;
    866         break;
    867     case VKEY_NEXT:  // page down
    868         *scrollDirection = ScrollDown;
    869         *scrollGranularity = ScrollByPage;
    870         break;
    871     default:
    872         return false;
    873     }
    874 
    875     return true;
    876 }
    877 
    878 void WebViewImpl::hideSelectPopup()
    879 {
    880     if (m_selectPopup.get())
    881         m_selectPopup->hidePopup();
    882 }
    883 
    884 bool WebViewImpl::propagateScroll(ScrollDirection scrollDirection,
    885                                   ScrollGranularity scrollGranularity)
    886 {
    887     Frame* frame = focusedWebCoreFrame();
    888     if (!frame)
    889         return false;
    890 
    891     bool scrollHandled = frame->eventHandler()->scrollOverflow(scrollDirection, scrollGranularity);
    892     Frame* currentFrame = frame;
    893     while (!scrollHandled && currentFrame) {
    894         scrollHandled = currentFrame->view()->scroll(scrollDirection, scrollGranularity);
    895         currentFrame = currentFrame->tree()->parent();
    896     }
    897     return scrollHandled;
    898 }
    899 
    900 void  WebViewImpl::popupOpened(WebCore::PopupContainer* popupContainer)
    901 {
    902     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
    903         ASSERT(!m_selectPopup);
    904         m_selectPopup = popupContainer;
    905     }
    906 }
    907 
    908 void  WebViewImpl::popupClosed(WebCore::PopupContainer* popupContainer)
    909 {
    910     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
    911         ASSERT(m_selectPopup.get());
    912         m_selectPopup = 0;
    913     }
    914 }
    915 
    916 void WebViewImpl::hideAutoFillPopup()
    917 {
    918     if (m_autoFillPopupShowing) {
    919         m_autoFillPopup->hidePopup();
    920         m_autoFillPopupShowing = false;
    921     }
    922 }
    923 
    924 Frame* WebViewImpl::focusedWebCoreFrame() const
    925 {
    926     return m_page.get() ? m_page->focusController()->focusedOrMainFrame() : 0;
    927 }
    928 
    929 WebViewImpl* WebViewImpl::fromPage(Page* page)
    930 {
    931     if (!page)
    932         return 0;
    933 
    934     ChromeClientImpl* chromeClient = static_cast<ChromeClientImpl*>(page->chrome()->client());
    935     return static_cast<WebViewImpl*>(chromeClient->webView());
    936 }
    937 
    938 // WebWidget ------------------------------------------------------------------
    939 
    940 void WebViewImpl::close()
    941 {
    942     RefPtr<WebFrameImpl> mainFrameImpl;
    943 
    944     if (m_page.get()) {
    945         // Initiate shutdown for the entire frameset.  This will cause a lot of
    946         // notifications to be sent.
    947         if (m_page->mainFrame()) {
    948             mainFrameImpl = WebFrameImpl::fromFrame(m_page->mainFrame());
    949             m_page->mainFrame()->loader()->frameDetached();
    950         }
    951         m_page.clear();
    952     }
    953 
    954     // Should happen after m_page.clear().
    955     if (m_devToolsAgent.get())
    956         m_devToolsAgent.clear();
    957 
    958     // Reset the delegate to prevent notifications being sent as we're being
    959     // deleted.
    960     m_client = 0;
    961 
    962     deref();  // Balances ref() acquired in WebView::create
    963 }
    964 
    965 void WebViewImpl::resize(const WebSize& newSize)
    966 {
    967     if (m_size == newSize)
    968         return;
    969     m_size = newSize;
    970 
    971     if (mainFrameImpl()->frameView()) {
    972         mainFrameImpl()->frameView()->resize(m_size.width, m_size.height);
    973         mainFrameImpl()->frame()->eventHandler()->sendResizeEvent();
    974     }
    975 
    976     if (m_client) {
    977         if (isAcceleratedCompositingActive()) {
    978 #if USE(ACCELERATED_COMPOSITING)
    979             updateLayerRendererViewport();
    980 #endif
    981         } else {
    982             WebRect damagedRect(0, 0, m_size.width, m_size.height);
    983             m_client->didInvalidateRect(damagedRect);
    984         }
    985     }
    986 
    987 #if USE(ACCELERATED_COMPOSITING)
    988     if (m_layerRenderer && isAcceleratedCompositingActive()) {
    989         m_layerRenderer->resizeOnscreenContent(IntSize(std::max(1, m_size.width),
    990                                                        std::max(1, m_size.height)));
    991     }
    992 #endif
    993 }
    994 
    995 void WebViewImpl::animate()
    996 {
    997 #if ENABLE(REQUEST_ANIMATION_FRAME)
    998     WebFrameImpl* webframe = mainFrameImpl();
    999     if (webframe) {
   1000         FrameView* view = webframe->frameView();
   1001         if (view)
   1002             view->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(currentTime()));
   1003     }
   1004 #endif
   1005 }
   1006 
   1007 void WebViewImpl::layout()
   1008 {
   1009 
   1010     WebFrameImpl* webframe = mainFrameImpl();
   1011     if (webframe) {
   1012         // In order for our child HWNDs (NativeWindowWidgets) to update properly,
   1013         // they need to be told that we are updating the screen.  The problem is
   1014         // that the native widgets need to recalculate their clip region and not
   1015         // overlap any of our non-native widgets.  To force the resizing, call
   1016         // setFrameRect().  This will be a quick operation for most frames, but
   1017         // the NativeWindowWidgets will update a proper clipping region.
   1018         FrameView* view = webframe->frameView();
   1019         if (view)
   1020             view->setFrameRect(view->frameRect());
   1021 
   1022         // setFrameRect may have the side-effect of causing existing page
   1023         // layout to be invalidated, so layout needs to be called last.
   1024 
   1025         webframe->layout();
   1026     }
   1027 }
   1028 
   1029 #if USE(ACCELERATED_COMPOSITING)
   1030 void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect)
   1031 {
   1032 #if USE(SKIA)
   1033     PlatformContextSkia context(canvas);
   1034 
   1035     // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
   1036     GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
   1037     int bitmapHeight = canvas->getDevice()->accessBitmap(false).height();
   1038 #elif USE(CG)
   1039     GraphicsContext gc(canvas);
   1040     int bitmapHeight = CGBitmapContextGetHeight(reinterpret_cast<CGContextRef>(canvas));
   1041 #else
   1042     notImplemented();
   1043 #endif
   1044     // Compute rect to sample from inverted GPU buffer.
   1045     IntRect invertRect(rect.x(), bitmapHeight - rect.maxY(), rect.width(), rect.height());
   1046 
   1047     OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(rect.size()));
   1048     RefPtr<ByteArray> pixelArray(ByteArray::create(rect.width() * rect.height() * 4));
   1049     if (imageBuffer.get() && pixelArray.get()) {
   1050         m_layerRenderer->getFramebufferPixels(pixelArray->data(), invertRect);
   1051         imageBuffer->putPremultipliedImageData(pixelArray.get(), rect.size(), IntRect(IntPoint(), rect.size()), IntPoint());
   1052         gc.save();
   1053         gc.translate(IntSize(0, bitmapHeight));
   1054         gc.scale(FloatSize(1.0f, -1.0f));
   1055         // Use invertRect in next line, so that transform above inverts it back to
   1056         // desired destination rect.
   1057         gc.drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, invertRect.location());
   1058         gc.restore();
   1059     }
   1060 }
   1061 #endif
   1062 
   1063 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
   1064 {
   1065     if (isAcceleratedCompositingActive()) {
   1066 #if USE(ACCELERATED_COMPOSITING)
   1067         doComposite();
   1068 
   1069         // If a canvas was passed in, we use it to grab a copy of the
   1070         // freshly-rendered pixels.
   1071         if (canvas) {
   1072             // Clip rect to the confines of the rootLayerTexture.
   1073             IntRect resizeRect(rect);
   1074             resizeRect.intersect(IntRect(IntPoint(), m_layerRenderer->viewportSize()));
   1075             doPixelReadbackToCanvas(canvas, resizeRect);
   1076         }
   1077 #endif
   1078     } else {
   1079         WebFrameImpl* webframe = mainFrameImpl();
   1080         if (webframe)
   1081             webframe->paint(canvas, rect);
   1082     }
   1083 }
   1084 
   1085 void WebViewImpl::themeChanged()
   1086 {
   1087     if (!page())
   1088         return;
   1089     FrameView* view = page()->mainFrame()->view();
   1090 
   1091     WebRect damagedRect(0, 0, m_size.width, m_size.height);
   1092     view->invalidateRect(damagedRect);
   1093 }
   1094 
   1095 void WebViewImpl::composite(bool finish)
   1096 {
   1097 #if USE(ACCELERATED_COMPOSITING)
   1098     TRACE_EVENT("WebViewImpl::composite", this, 0);
   1099     if (m_recreatingGraphicsContext) {
   1100         // reallocateRenderer will request a repaint whether or not it succeeded
   1101         // in creating a new context.
   1102         reallocateRenderer();
   1103         m_recreatingGraphicsContext = false;
   1104         return;
   1105     }
   1106     doComposite();
   1107 
   1108     // Finish if requested.
   1109     if (finish)
   1110         m_layerRenderer->finish();
   1111 
   1112     // Put result onscreen.
   1113     m_layerRenderer->present();
   1114 
   1115     GraphicsContext3D* context = m_layerRenderer->context();
   1116     if (context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR) {
   1117         // Trying to recover the context right here will not work if GPU process
   1118         // died. This is because GpuChannelHost::OnErrorMessage will only be
   1119         // called at the next iteration of the message loop, reverting our
   1120         // recovery attempts here. Instead, we detach the root layer from the
   1121         // renderer, recreate the renderer at the next message loop iteration
   1122         // and request a repaint yet again.
   1123         m_recreatingGraphicsContext = true;
   1124         setRootLayerNeedsDisplay();
   1125     }
   1126 #endif
   1127 }
   1128 
   1129 const WebInputEvent* WebViewImpl::m_currentInputEvent = 0;
   1130 
   1131 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
   1132 {
   1133     UserGestureIndicator gestureIndicator(WebInputEvent::isUserGestureEventType(inputEvent.type) ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
   1134 
   1135     // If we've started a drag and drop operation, ignore input events until
   1136     // we're done.
   1137     if (m_doingDragAndDrop)
   1138         return true;
   1139 
   1140     if (m_ignoreInputEvents)
   1141         return true;
   1142 
   1143     m_currentInputEvent = &inputEvent;
   1144 
   1145     if (m_mouseCaptureNode.get() && WebInputEvent::isMouseEventType(inputEvent.type)) {
   1146         // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
   1147         RefPtr<Node> node = m_mouseCaptureNode;
   1148 
   1149         // Not all platforms call mouseCaptureLost() directly.
   1150         if (inputEvent.type == WebInputEvent::MouseUp)
   1151             mouseCaptureLost();
   1152 
   1153         AtomicString eventType;
   1154         switch (inputEvent.type) {
   1155         case WebInputEvent::MouseMove:
   1156             eventType = eventNames().mousemoveEvent;
   1157             break;
   1158         case WebInputEvent::MouseLeave:
   1159             eventType = eventNames().mouseoutEvent;
   1160             break;
   1161         case WebInputEvent::MouseDown:
   1162             eventType = eventNames().mousedownEvent;
   1163             break;
   1164         case WebInputEvent::MouseUp:
   1165             eventType = eventNames().mouseupEvent;
   1166             break;
   1167         default:
   1168             ASSERT_NOT_REACHED();
   1169         }
   1170 
   1171         node->dispatchMouseEvent(
   1172               PlatformMouseEventBuilder(mainFrameImpl()->frameView(), *static_cast<const WebMouseEvent*>(&inputEvent)),
   1173               eventType, static_cast<const WebMouseEvent*>(&inputEvent)->clickCount);
   1174         m_currentInputEvent = 0;
   1175         return true;
   1176     }
   1177 
   1178     bool handled = true;
   1179 
   1180     // FIXME: WebKit seems to always return false on mouse events processing
   1181     // methods. For now we'll assume it has processed them (as we are only
   1182     // interested in whether keyboard events are processed).
   1183     switch (inputEvent.type) {
   1184     case WebInputEvent::MouseMove:
   1185         mouseMove(*static_cast<const WebMouseEvent*>(&inputEvent));
   1186         break;
   1187 
   1188     case WebInputEvent::MouseLeave:
   1189         mouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent));
   1190         break;
   1191 
   1192     case WebInputEvent::MouseWheel:
   1193         handled = mouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent));
   1194         break;
   1195 
   1196     case WebInputEvent::MouseDown:
   1197         mouseDown(*static_cast<const WebMouseEvent*>(&inputEvent));
   1198         break;
   1199 
   1200     case WebInputEvent::MouseUp:
   1201         mouseUp(*static_cast<const WebMouseEvent*>(&inputEvent));
   1202         break;
   1203 
   1204     case WebInputEvent::RawKeyDown:
   1205     case WebInputEvent::KeyDown:
   1206     case WebInputEvent::KeyUp:
   1207         handled = keyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
   1208         break;
   1209 
   1210     case WebInputEvent::Char:
   1211         handled = charEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
   1212         break;
   1213 
   1214 #if ENABLE(TOUCH_EVENTS)
   1215     case WebInputEvent::TouchStart:
   1216     case WebInputEvent::TouchMove:
   1217     case WebInputEvent::TouchEnd:
   1218     case WebInputEvent::TouchCancel:
   1219         handled = touchEvent(*static_cast<const WebTouchEvent*>(&inputEvent));
   1220         break;
   1221 #endif
   1222 
   1223     default:
   1224         handled = false;
   1225     }
   1226 
   1227     m_currentInputEvent = 0;
   1228 
   1229     return handled;
   1230 }
   1231 
   1232 void WebViewImpl::mouseCaptureLost()
   1233 {
   1234     m_mouseCaptureNode = 0;
   1235 }
   1236 
   1237 void WebViewImpl::setFocus(bool enable)
   1238 {
   1239     m_page->focusController()->setFocused(enable);
   1240     if (enable) {
   1241         // Note that we don't call setActive() when disabled as this cause extra
   1242         // focus/blur events to be dispatched.
   1243         m_page->focusController()->setActive(true);
   1244         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
   1245         if (focusedFrame) {
   1246             Node* focusedNode = focusedFrame->document()->focusedNode();
   1247             if (focusedNode && focusedNode->isElementNode()
   1248                 && focusedFrame->selection()->selection().isNone()) {
   1249                 // If the selection was cleared while the WebView was not
   1250                 // focused, then the focus element shows with a focus ring but
   1251                 // no caret and does respond to keyboard inputs.
   1252                 Element* element = static_cast<Element*>(focusedNode);
   1253                 if (element->isTextFormControl())
   1254                     element->updateFocusAppearance(true);
   1255                 else if (focusedNode->isContentEditable()) {
   1256                     // updateFocusAppearance() selects all the text of
   1257                     // contentseditable DIVs. So we set the selection explicitly
   1258                     // instead. Note that this has the side effect of moving the
   1259                     // caret back to the beginning of the text.
   1260                     Position position(focusedNode, 0,
   1261                                       Position::PositionIsOffsetInAnchor);
   1262                     focusedFrame->selection()->setSelection(
   1263                         VisibleSelection(position, SEL_DEFAULT_AFFINITY));
   1264                 }
   1265             }
   1266         }
   1267         m_imeAcceptEvents = true;
   1268     } else {
   1269         hideAutoFillPopup();
   1270         hideSelectPopup();
   1271 
   1272         // Clear focus on the currently focused frame if any.
   1273         if (!m_page.get())
   1274             return;
   1275 
   1276         Frame* frame = m_page->mainFrame();
   1277         if (!frame)
   1278             return;
   1279 
   1280         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
   1281         if (focusedFrame.get()) {
   1282             // Finish an ongoing composition to delete the composition node.
   1283             Editor* editor = focusedFrame->editor();
   1284             if (editor && editor->hasComposition())
   1285                 editor->confirmComposition();
   1286             m_imeAcceptEvents = false;
   1287         }
   1288     }
   1289 }
   1290 
   1291 bool WebViewImpl::setComposition(
   1292     const WebString& text,
   1293     const WebVector<WebCompositionUnderline>& underlines,
   1294     int selectionStart,
   1295     int selectionEnd)
   1296 {
   1297     Frame* focused = focusedWebCoreFrame();
   1298     if (!focused || !m_imeAcceptEvents)
   1299         return false;
   1300     Editor* editor = focused->editor();
   1301     if (!editor)
   1302         return false;
   1303 
   1304     // The input focus has been moved to another WebWidget object.
   1305     // We should use this |editor| object only to complete the ongoing
   1306     // composition.
   1307     if (!editor->canEdit() && !editor->hasComposition())
   1308         return false;
   1309 
   1310     // We should verify the parent node of this IME composition node are
   1311     // editable because JavaScript may delete a parent node of the composition
   1312     // node. In this case, WebKit crashes while deleting texts from the parent
   1313     // node, which doesn't exist any longer.
   1314     PassRefPtr<Range> range = editor->compositionRange();
   1315     if (range) {
   1316         const Node* node = range->startContainer();
   1317         if (!node || !node->isContentEditable())
   1318             return false;
   1319     }
   1320 
   1321     // If we're not going to fire a keypress event, then the keydown event was
   1322     // canceled.  In that case, cancel any existing composition.
   1323     if (text.isEmpty() || m_suppressNextKeypressEvent) {
   1324         // A browser process sent an IPC message which does not contain a valid
   1325         // string, which means an ongoing composition has been canceled.
   1326         // If the ongoing composition has been canceled, replace the ongoing
   1327         // composition string with an empty string and complete it.
   1328         String emptyString;
   1329         Vector<CompositionUnderline> emptyUnderlines;
   1330         editor->setComposition(emptyString, emptyUnderlines, 0, 0);
   1331         return text.isEmpty();
   1332     }
   1333 
   1334     // When the range of composition underlines overlap with the range between
   1335     // selectionStart and selectionEnd, WebKit somehow won't paint the selection
   1336     // at all (see InlineTextBox::paint() function in InlineTextBox.cpp).
   1337     // But the selection range actually takes effect.
   1338     editor->setComposition(String(text),
   1339                            CompositionUnderlineVectorBuilder(underlines),
   1340                            selectionStart, selectionEnd);
   1341 
   1342     return editor->hasComposition();
   1343 }
   1344 
   1345 bool WebViewImpl::confirmComposition()
   1346 {
   1347     return confirmComposition(WebString());
   1348 }
   1349 
   1350 bool WebViewImpl::confirmComposition(const WebString& text)
   1351 {
   1352     Frame* focused = focusedWebCoreFrame();
   1353     if (!focused || !m_imeAcceptEvents)
   1354         return false;
   1355     Editor* editor = focused->editor();
   1356     if (!editor || (!editor->hasComposition() && !text.length()))
   1357         return false;
   1358 
   1359     // We should verify the parent node of this IME composition node are
   1360     // editable because JavaScript may delete a parent node of the composition
   1361     // node. In this case, WebKit crashes while deleting texts from the parent
   1362     // node, which doesn't exist any longer.
   1363     PassRefPtr<Range> range = editor->compositionRange();
   1364     if (range) {
   1365         const Node* node = range->startContainer();
   1366         if (!node || !node->isContentEditable())
   1367             return false;
   1368     }
   1369 
   1370     if (editor->hasComposition()) {
   1371         if (text.length())
   1372             editor->confirmComposition(String(text));
   1373         else
   1374             editor->confirmComposition();
   1375     } else
   1376         editor->insertText(String(text), 0);
   1377 
   1378     return true;
   1379 }
   1380 
   1381 WebTextInputType WebViewImpl::textInputType()
   1382 {
   1383     WebTextInputType type = WebTextInputTypeNone;
   1384     const Frame* focused = focusedWebCoreFrame();
   1385     if (!focused)
   1386         return type;
   1387 
   1388     const Editor* editor = focused->editor();
   1389     if (!editor || !editor->canEdit())
   1390         return type;
   1391 
   1392     SelectionController* controller = focused->selection();
   1393     if (!controller)
   1394         return type;
   1395 
   1396     const Node* node = controller->start().deprecatedNode();
   1397     if (!node)
   1398         return type;
   1399 
   1400     // FIXME: Support more text input types when necessary, eg. Number,
   1401     // Date, Email, URL, etc.
   1402     if (controller->isInPasswordField())
   1403         type = WebTextInputTypePassword;
   1404     else if (node->shouldUseInputMethod())
   1405         type = WebTextInputTypeText;
   1406 
   1407     return type;
   1408 }
   1409 
   1410 WebRect WebViewImpl::caretOrSelectionBounds()
   1411 {
   1412     WebRect rect;
   1413     const Frame* focused = focusedWebCoreFrame();
   1414     if (!focused)
   1415         return rect;
   1416 
   1417     SelectionController* controller = focused->selection();
   1418     if (!controller)
   1419         return rect;
   1420 
   1421     const FrameView* view = focused->view();
   1422     if (!view)
   1423         return rect;
   1424 
   1425     const Node* node = controller->base().containerNode();
   1426     if (!node || !node->renderer())
   1427         return rect;
   1428 
   1429     if (controller->isCaret())
   1430         rect = view->contentsToWindow(controller->absoluteCaretBounds());
   1431     else if (controller->isRange()) {
   1432         node = controller->extent().containerNode();
   1433         RefPtr<Range> range = controller->toNormalizedRange();
   1434         if (!node || !node->renderer() || !range)
   1435             return rect;
   1436         rect = view->contentsToWindow(focused->editor()->firstRectForRange(range.get()));
   1437     }
   1438     return rect;
   1439 }
   1440 
   1441 bool WebViewImpl::selectionRange(WebPoint& start, WebPoint& end) const
   1442 {
   1443     const Frame* frame = focusedWebCoreFrame();
   1444     if (!frame)
   1445         return false;
   1446     RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
   1447     RefPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
   1448                                       selectedRange->startContainer(),
   1449                                       selectedRange->startOffset(),
   1450                                       selectedRange->startContainer(),
   1451                                       selectedRange->startOffset()));
   1452 
   1453     IntRect rect = frame->editor()->firstRectForRange(range.get());
   1454     start.x = rect.x();
   1455     start.y = rect.y() + rect.height() - 1;
   1456 
   1457     range = Range::create(selectedRange->endContainer()->document(),
   1458                           selectedRange->endContainer(),
   1459                           selectedRange->endOffset(),
   1460                           selectedRange->endContainer(),
   1461                           selectedRange->endOffset());
   1462 
   1463     rect = frame->editor()->firstRectForRange(range.get());
   1464     end.x = rect.x() + rect.width() - 1;
   1465     end.y = rect.y() + rect.height() - 1;
   1466 
   1467     start = frame->view()->contentsToWindow(start);
   1468     end = frame->view()->contentsToWindow(end);
   1469     return true;
   1470 }
   1471 
   1472 void WebViewImpl::setTextDirection(WebTextDirection direction)
   1473 {
   1474     // The Editor::setBaseWritingDirection() function checks if we can change
   1475     // the text direction of the selected node and updates its DOM "dir"
   1476     // attribute and its CSS "direction" property.
   1477     // So, we just call the function as Safari does.
   1478     const Frame* focused = focusedWebCoreFrame();
   1479     if (!focused)
   1480         return;
   1481 
   1482     Editor* editor = focused->editor();
   1483     if (!editor || !editor->canEdit())
   1484         return;
   1485 
   1486     switch (direction) {
   1487     case WebTextDirectionDefault:
   1488         editor->setBaseWritingDirection(NaturalWritingDirection);
   1489         break;
   1490 
   1491     case WebTextDirectionLeftToRight:
   1492         editor->setBaseWritingDirection(LeftToRightWritingDirection);
   1493         break;
   1494 
   1495     case WebTextDirectionRightToLeft:
   1496         editor->setBaseWritingDirection(RightToLeftWritingDirection);
   1497         break;
   1498 
   1499     default:
   1500         notImplemented();
   1501         break;
   1502     }
   1503 }
   1504 
   1505 bool WebViewImpl::isAcceleratedCompositingActive() const
   1506 {
   1507 #if USE(ACCELERATED_COMPOSITING)
   1508     return m_isAcceleratedCompositingActive;
   1509 #else
   1510     return false;
   1511 #endif
   1512 }
   1513 
   1514 // WebView --------------------------------------------------------------------
   1515 
   1516 WebSettings* WebViewImpl::settings()
   1517 {
   1518     if (!m_webSettings.get())
   1519         m_webSettings.set(new WebSettingsImpl(m_page->settings()));
   1520     ASSERT(m_webSettings.get());
   1521     return m_webSettings.get();
   1522 }
   1523 
   1524 WebString WebViewImpl::pageEncoding() const
   1525 {
   1526     if (!m_page.get())
   1527         return WebString();
   1528 
   1529     return m_page->mainFrame()->document()->loader()->writer()->encoding();
   1530 }
   1531 
   1532 void WebViewImpl::setPageEncoding(const WebString& encodingName)
   1533 {
   1534     if (!m_page.get())
   1535         return;
   1536 
   1537     // Only change override encoding, don't change default encoding.
   1538     // Note that the new encoding must be 0 if it isn't supposed to be set.
   1539     String newEncodingName;
   1540     if (!encodingName.isEmpty())
   1541         newEncodingName = encodingName;
   1542     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(newEncodingName);
   1543 }
   1544 
   1545 bool WebViewImpl::dispatchBeforeUnloadEvent()
   1546 {
   1547     // FIXME: This should really cause a recursive depth-first walk of all
   1548     // frames in the tree, calling each frame's onbeforeunload.  At the moment,
   1549     // we're consistent with Safari 3.1, not IE/FF.
   1550     Frame* frame = m_page->mainFrame();
   1551     if (!frame)
   1552         return true;
   1553 
   1554     return frame->loader()->shouldClose();
   1555 }
   1556 
   1557 void WebViewImpl::dispatchUnloadEvent()
   1558 {
   1559     // Run unload handlers.
   1560     m_page->mainFrame()->loader()->closeURL();
   1561 }
   1562 
   1563 WebFrame* WebViewImpl::mainFrame()
   1564 {
   1565     return mainFrameImpl();
   1566 }
   1567 
   1568 WebFrame* WebViewImpl::findFrameByName(
   1569     const WebString& name, WebFrame* relativeToFrame)
   1570 {
   1571     if (!relativeToFrame)
   1572         relativeToFrame = mainFrame();
   1573     Frame* frame = static_cast<WebFrameImpl*>(relativeToFrame)->frame();
   1574     frame = frame->tree()->find(name);
   1575     return WebFrameImpl::fromFrame(frame);
   1576 }
   1577 
   1578 WebFrame* WebViewImpl::focusedFrame()
   1579 {
   1580     return WebFrameImpl::fromFrame(focusedWebCoreFrame());
   1581 }
   1582 
   1583 void WebViewImpl::setFocusedFrame(WebFrame* frame)
   1584 {
   1585     if (!frame) {
   1586         // Clears the focused frame if any.
   1587         Frame* frame = focusedWebCoreFrame();
   1588         if (frame)
   1589             frame->selection()->setFocused(false);
   1590         return;
   1591     }
   1592     WebFrameImpl* frameImpl = static_cast<WebFrameImpl*>(frame);
   1593     Frame* webcoreFrame = frameImpl->frame();
   1594     webcoreFrame->page()->focusController()->setFocusedFrame(webcoreFrame);
   1595 }
   1596 
   1597 void WebViewImpl::setInitialFocus(bool reverse)
   1598 {
   1599     if (!m_page.get())
   1600         return;
   1601 
   1602     // Since we don't have a keyboard event, we'll create one.
   1603     WebKeyboardEvent keyboardEvent;
   1604     keyboardEvent.type = WebInputEvent::RawKeyDown;
   1605     if (reverse)
   1606         keyboardEvent.modifiers = WebInputEvent::ShiftKey;
   1607 
   1608     // VK_TAB which is only defined on Windows.
   1609     keyboardEvent.windowsKeyCode = 0x09;
   1610     PlatformKeyboardEventBuilder platformEvent(keyboardEvent);
   1611     RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
   1612 
   1613     Frame* frame = page()->focusController()->focusedOrMainFrame();
   1614     if (Document* document = frame->document())
   1615         document->setFocusedNode(0);
   1616     page()->focusController()->setInitialFocus(
   1617         reverse ? FocusDirectionBackward : FocusDirectionForward,
   1618         webkitEvent.get());
   1619 }
   1620 
   1621 void WebViewImpl::clearFocusedNode()
   1622 {
   1623     if (!m_page.get())
   1624         return;
   1625 
   1626     RefPtr<Frame> frame = m_page->mainFrame();
   1627     if (!frame.get())
   1628         return;
   1629 
   1630     RefPtr<Document> document = frame->document();
   1631     if (!document.get())
   1632         return;
   1633 
   1634     RefPtr<Node> oldFocusedNode = document->focusedNode();
   1635 
   1636     // Clear the focused node.
   1637     document->setFocusedNode(0);
   1638 
   1639     if (!oldFocusedNode.get())
   1640         return;
   1641 
   1642     // If a text field has focus, we need to make sure the selection controller
   1643     // knows to remove selection from it. Otherwise, the text field is still
   1644     // processing keyboard events even though focus has been moved to the page and
   1645     // keystrokes get eaten as a result.
   1646     if (oldFocusedNode->hasTagName(HTMLNames::textareaTag)
   1647         || (oldFocusedNode->hasTagName(HTMLNames::inputTag)
   1648             && static_cast<HTMLInputElement*>(oldFocusedNode.get())->isTextField())) {
   1649         // Clear the selection.
   1650         SelectionController* selection = frame->selection();
   1651         selection->clear();
   1652     }
   1653 }
   1654 
   1655 void WebViewImpl::scrollFocusedNodeIntoView()
   1656 {
   1657     Node* focusedNode = focusedWebCoreNode();
   1658     if (focusedNode && focusedNode->isElementNode()) {
   1659         Element* elementNode = static_cast<Element*>(focusedNode);
   1660         elementNode->scrollIntoViewIfNeeded(true);
   1661     }
   1662 }
   1663 
   1664 double WebViewImpl::zoomLevel()
   1665 {
   1666     return m_zoomLevel;
   1667 }
   1668 
   1669 double WebViewImpl::setZoomLevel(bool textOnly, double zoomLevel)
   1670 {
   1671     if (zoomLevel < m_minimumZoomLevel)
   1672         m_zoomLevel = m_minimumZoomLevel;
   1673     else if (zoomLevel > m_maximumZoomLevel)
   1674         m_zoomLevel = m_maximumZoomLevel;
   1675     else
   1676         m_zoomLevel = zoomLevel;
   1677 
   1678     Frame* frame = mainFrameImpl()->frame();
   1679     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
   1680     if (pluginContainer)
   1681         pluginContainer->plugin()->setZoomLevel(m_zoomLevel, textOnly);
   1682     else {
   1683         float zoomFactor = static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel));
   1684         if (textOnly)
   1685             frame->setPageAndTextZoomFactors(1, zoomFactor);
   1686         else
   1687             frame->setPageAndTextZoomFactors(zoomFactor, 1);
   1688     }
   1689     return m_zoomLevel;
   1690 }
   1691 
   1692 void WebViewImpl::zoomLimitsChanged(double minimumZoomLevel,
   1693                                     double maximumZoomLevel)
   1694 {
   1695     m_minimumZoomLevel = minimumZoomLevel;
   1696     m_maximumZoomLevel = maximumZoomLevel;
   1697     m_client->zoomLimitsChanged(m_minimumZoomLevel, m_maximumZoomLevel);
   1698 }
   1699 
   1700 void WebViewImpl::fullFramePluginZoomLevelChanged(double zoomLevel)
   1701 {
   1702     if (zoomLevel == m_zoomLevel)
   1703         return;
   1704 
   1705     m_zoomLevel = std::max(std::min(zoomLevel, m_maximumZoomLevel), m_minimumZoomLevel);
   1706     m_client->zoomLevelChanged();
   1707 }
   1708 
   1709 double WebView::zoomLevelToZoomFactor(double zoomLevel)
   1710 {
   1711     return std::pow(textSizeMultiplierRatio, zoomLevel);
   1712 }
   1713 
   1714 double WebView::zoomFactorToZoomLevel(double factor)
   1715 {
   1716     // Since factor = 1.2^level, level = log(factor) / log(1.2)
   1717     return log(factor) / log(textSizeMultiplierRatio);
   1718 }
   1719 
   1720 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
   1721                                            const WebPoint& location)
   1722 {
   1723     HitTestResult result =
   1724         hitTestResultForWindowPos(location);
   1725     RefPtr<Node> node = result.innerNonSharedNode();
   1726     if (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))
   1727       return;
   1728 
   1729     RefPtr<HTMLMediaElement> mediaElement =
   1730         static_pointer_cast<HTMLMediaElement>(node);
   1731     switch (action.type) {
   1732     case WebMediaPlayerAction::Play:
   1733         if (action.enable)
   1734             mediaElement->play(mediaElement->processingUserGesture());
   1735         else
   1736             mediaElement->pause(mediaElement->processingUserGesture());
   1737         break;
   1738     case WebMediaPlayerAction::Mute:
   1739         mediaElement->setMuted(action.enable);
   1740         break;
   1741     case WebMediaPlayerAction::Loop:
   1742         mediaElement->setLoop(action.enable);
   1743         break;
   1744     case WebMediaPlayerAction::Controls:
   1745         mediaElement->setControls(action.enable);
   1746         break;
   1747     default:
   1748         ASSERT_NOT_REACHED();
   1749     }
   1750 }
   1751 
   1752 void WebViewImpl::copyImageAt(const WebPoint& point)
   1753 {
   1754     if (!m_page.get())
   1755         return;
   1756 
   1757     HitTestResult result = hitTestResultForWindowPos(point);
   1758 
   1759     if (result.absoluteImageURL().isEmpty()) {
   1760         // There isn't actually an image at these coordinates.  Might be because
   1761         // the window scrolled while the context menu was open or because the page
   1762         // changed itself between when we thought there was an image here and when
   1763         // we actually tried to retreive the image.
   1764         //
   1765         // FIXME: implement a cache of the most recent HitTestResult to avoid having
   1766         //        to do two hit tests.
   1767         return;
   1768     }
   1769 
   1770     m_page->mainFrame()->editor()->copyImage(result);
   1771 }
   1772 
   1773 void WebViewImpl::dragSourceEndedAt(
   1774     const WebPoint& clientPoint,
   1775     const WebPoint& screenPoint,
   1776     WebDragOperation operation)
   1777 {
   1778     PlatformMouseEvent pme(clientPoint,
   1779                            screenPoint,
   1780                            LeftButton, MouseEventMoved, 0, false, false, false,
   1781                            false, 0);
   1782     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(pme,
   1783         static_cast<DragOperation>(operation));
   1784     m_dragScrollTimer->stop();
   1785 }
   1786 
   1787 void WebViewImpl::dragSourceMovedTo(
   1788     const WebPoint& clientPoint,
   1789     const WebPoint& screenPoint,
   1790     WebDragOperation operation)
   1791 {
   1792     m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
   1793 }
   1794 
   1795 void WebViewImpl::dragSourceSystemDragEnded()
   1796 {
   1797     // It's possible for us to get this callback while not doing a drag if
   1798     // it's from a previous page that got unloaded.
   1799     if (m_doingDragAndDrop) {
   1800         m_page->dragController()->dragEnded();
   1801         m_doingDragAndDrop = false;
   1802     }
   1803 }
   1804 
   1805 WebDragOperation WebViewImpl::dragTargetDragEnter(
   1806     const WebDragData& webDragData,
   1807     const WebPoint& clientPoint,
   1808     const WebPoint& screenPoint,
   1809     WebDragOperationsMask operationsAllowed)
   1810 {
   1811     ASSERT(!m_currentDragData.get());
   1812 
   1813     m_currentDragData = webDragData;
   1814     m_operationsAllowed = operationsAllowed;
   1815 
   1816     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragEnter);
   1817 }
   1818 
   1819 WebDragOperation WebViewImpl::dragTargetDragOver(
   1820     const WebPoint& clientPoint,
   1821     const WebPoint& screenPoint,
   1822     WebDragOperationsMask operationsAllowed)
   1823 {
   1824     m_operationsAllowed = operationsAllowed;
   1825 
   1826     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragOver);
   1827 }
   1828 
   1829 void WebViewImpl::dragTargetDragLeave()
   1830 {
   1831     ASSERT(m_currentDragData.get());
   1832 
   1833     DragData dragData(
   1834         m_currentDragData.get(),
   1835         IntPoint(),
   1836         IntPoint(),
   1837         static_cast<DragOperation>(m_operationsAllowed));
   1838 
   1839     m_page->dragController()->dragExited(&dragData);
   1840 
   1841     // FIXME: why is the drag scroll timer not stopped here?
   1842 
   1843     m_dragOperation = WebDragOperationNone;
   1844     m_currentDragData = 0;
   1845 }
   1846 
   1847 void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
   1848                                  const WebPoint& screenPoint)
   1849 {
   1850     ASSERT(m_currentDragData.get());
   1851 
   1852     // If this webview transitions from the "drop accepting" state to the "not
   1853     // accepting" state, then our IPC message reply indicating that may be in-
   1854     // flight, or else delayed by javascript processing in this webview.  If a
   1855     // drop happens before our IPC reply has reached the browser process, then
   1856     // the browser forwards the drop to this webview.  So only allow a drop to
   1857     // proceed if our webview m_dragOperation state is not DragOperationNone.
   1858 
   1859     if (m_dragOperation == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop.
   1860         dragTargetDragLeave();
   1861         return;
   1862     }
   1863 
   1864     DragData dragData(
   1865         m_currentDragData.get(),
   1866         clientPoint,
   1867         screenPoint,
   1868         static_cast<DragOperation>(m_operationsAllowed));
   1869 
   1870     m_page->dragController()->performDrag(&dragData);
   1871 
   1872     m_dragOperation = WebDragOperationNone;
   1873     m_currentDragData = 0;
   1874 
   1875     m_dragScrollTimer->stop();
   1876 }
   1877 
   1878 WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPoint, const WebPoint& screenPoint, DragAction dragAction)
   1879 {
   1880     ASSERT(m_currentDragData.get());
   1881 
   1882     DragData dragData(
   1883         m_currentDragData.get(),
   1884         clientPoint,
   1885         screenPoint,
   1886         static_cast<DragOperation>(m_operationsAllowed));
   1887 
   1888     DragOperation dropEffect;
   1889     if (dragAction == DragEnter)
   1890         dropEffect = m_page->dragController()->dragEntered(&dragData);
   1891     else
   1892         dropEffect = m_page->dragController()->dragUpdated(&dragData);
   1893 
   1894     // Mask the drop effect operation against the drag source's allowed operations.
   1895     if (!(dropEffect & dragData.draggingSourceOperationMask()))
   1896         dropEffect = DragOperationNone;
   1897 
   1898      m_dragOperation = static_cast<WebDragOperation>(dropEffect);
   1899 
   1900     if (dragAction == DragOver)
   1901         m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
   1902     else
   1903         m_dragScrollTimer->stop();
   1904 
   1905     return m_dragOperation;
   1906 }
   1907 
   1908 unsigned long WebViewImpl::createUniqueIdentifierForRequest()
   1909 {
   1910     if (m_page)
   1911         return m_page->progress()->createUniqueIdentifier();
   1912     return 0;
   1913 }
   1914 
   1915 void WebViewImpl::inspectElementAt(const WebPoint& point)
   1916 {
   1917     if (!m_page.get())
   1918         return;
   1919 
   1920     if (point.x == -1 || point.y == -1)
   1921         m_page->inspectorController()->inspect(0);
   1922     else {
   1923         HitTestResult result = hitTestResultForWindowPos(point);
   1924 
   1925         if (!result.innerNonSharedNode())
   1926             return;
   1927 
   1928         m_page->inspectorController()->inspect(result.innerNonSharedNode());
   1929     }
   1930 }
   1931 
   1932 WebString WebViewImpl::inspectorSettings() const
   1933 {
   1934     return m_inspectorSettings;
   1935 }
   1936 
   1937 void WebViewImpl::setInspectorSettings(const WebString& settings)
   1938 {
   1939     m_inspectorSettings = settings;
   1940 }
   1941 
   1942 bool WebViewImpl::inspectorSetting(const WebString& key, WebString* value) const
   1943 {
   1944     if (!m_inspectorSettingsMap->contains(key))
   1945         return false;
   1946     *value = m_inspectorSettingsMap->get(key);
   1947     return true;
   1948 }
   1949 
   1950 void WebViewImpl::setInspectorSetting(const WebString& key,
   1951                                       const WebString& value)
   1952 {
   1953     m_inspectorSettingsMap->set(key, value);
   1954     client()->didUpdateInspectorSetting(key, value);
   1955 }
   1956 
   1957 WebDevToolsAgent* WebViewImpl::devToolsAgent()
   1958 {
   1959     return m_devToolsAgent.get();
   1960 }
   1961 
   1962 WebAccessibilityObject WebViewImpl::accessibilityObject()
   1963 {
   1964     if (!mainFrameImpl())
   1965         return WebAccessibilityObject();
   1966 
   1967     Document* document = mainFrameImpl()->frame()->document();
   1968     return WebAccessibilityObject(
   1969         document->axObjectCache()->getOrCreate(document->renderer()));
   1970 }
   1971 
   1972 void WebViewImpl::applyAutoFillSuggestions(
   1973     const WebNode& node,
   1974     const WebVector<WebString>& names,
   1975     const WebVector<WebString>& labels,
   1976     const WebVector<WebString>& icons,
   1977     const WebVector<int>& uniqueIDs,
   1978     int separatorIndex)
   1979 {
   1980     ASSERT(names.size() == labels.size());
   1981     ASSERT(names.size() == uniqueIDs.size());
   1982     ASSERT(separatorIndex < static_cast<int>(names.size()));
   1983 
   1984     if (names.isEmpty()) {
   1985         hideAutoFillPopup();
   1986         return;
   1987     }
   1988 
   1989     RefPtr<Node> focusedNode = focusedWebCoreNode();
   1990     // If the node for which we queried the AutoFill suggestions is not the
   1991     // focused node, then we have nothing to do.  FIXME: also check the
   1992     // caret is at the end and that the text has not changed.
   1993     if (!focusedNode || focusedNode != PassRefPtr<Node>(node)) {
   1994         hideAutoFillPopup();
   1995         return;
   1996     }
   1997 
   1998     HTMLInputElement* inputElem =
   1999         static_cast<HTMLInputElement*>(focusedNode.get());
   2000 
   2001     // The first time the AutoFill popup is shown we'll create the client and
   2002     // the popup.
   2003     if (!m_autoFillPopupClient.get())
   2004         m_autoFillPopupClient.set(new AutoFillPopupMenuClient);
   2005 
   2006     m_autoFillPopupClient->initialize(
   2007         inputElem, names, labels, icons, uniqueIDs, separatorIndex);
   2008 
   2009     if (!m_autoFillPopup.get()) {
   2010         m_autoFillPopup = PopupContainer::create(m_autoFillPopupClient.get(),
   2011                                                  PopupContainer::Suggestion,
   2012                                                  autoFillPopupSettings);
   2013     }
   2014 
   2015     if (m_autoFillPopupShowing) {
   2016         refreshAutoFillPopup();
   2017     } else {
   2018         m_autoFillPopup->showInRect(focusedNode->getRect(), focusedNode->ownerDocument()->view(), 0);
   2019         m_autoFillPopupShowing = true;
   2020     }
   2021 }
   2022 
   2023 void WebViewImpl::hidePopups()
   2024 {
   2025     hideSelectPopup();
   2026     hideAutoFillPopup();
   2027 }
   2028 
   2029 void WebViewImpl::performCustomContextMenuAction(unsigned action)
   2030 {
   2031     if (!m_page)
   2032         return;
   2033     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
   2034     if (!menu)
   2035         return;
   2036     ContextMenuItem* item = menu->itemWithAction(static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + action));
   2037     if (item)
   2038         m_page->contextMenuController()->contextMenuItemSelected(item);
   2039     m_page->contextMenuController()->clearContextMenu();
   2040 }
   2041 
   2042 // WebView --------------------------------------------------------------------
   2043 
   2044 void WebViewImpl::setIsTransparent(bool isTransparent)
   2045 {
   2046     // Set any existing frames to be transparent.
   2047     Frame* frame = m_page->mainFrame();
   2048     while (frame) {
   2049         frame->view()->setTransparent(isTransparent);
   2050         frame = frame->tree()->traverseNext();
   2051     }
   2052 
   2053     // Future frames check this to know whether to be transparent.
   2054     m_isTransparent = isTransparent;
   2055 }
   2056 
   2057 bool WebViewImpl::isTransparent() const
   2058 {
   2059     return m_isTransparent;
   2060 }
   2061 
   2062 void WebViewImpl::setIsActive(bool active)
   2063 {
   2064     if (page() && page()->focusController())
   2065         page()->focusController()->setActive(active);
   2066 }
   2067 
   2068 bool WebViewImpl::isActive() const
   2069 {
   2070     return (page() && page()->focusController()) ? page()->focusController()->isActive() : false;
   2071 }
   2072 
   2073 void WebViewImpl::setDomainRelaxationForbidden(bool forbidden, const WebString& scheme)
   2074 {
   2075     SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme));
   2076 }
   2077 
   2078 void WebViewImpl::setScrollbarColors(unsigned inactiveColor,
   2079                                      unsigned activeColor,
   2080                                      unsigned trackColor) {
   2081 #if OS(LINUX) || OS(FREEBSD)
   2082     PlatformThemeChromiumGtk::setScrollbarColors(inactiveColor,
   2083                                                  activeColor,
   2084                                                  trackColor);
   2085 #endif
   2086 }
   2087 
   2088 void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor,
   2089                                      unsigned activeForegroundColor,
   2090                                      unsigned inactiveBackgroundColor,
   2091                                      unsigned inactiveForegroundColor) {
   2092 #if OS(LINUX) || OS(FREEBSD)
   2093     RenderThemeChromiumLinux::setSelectionColors(activeBackgroundColor,
   2094                                                  activeForegroundColor,
   2095                                                  inactiveBackgroundColor,
   2096                                                  inactiveForegroundColor);
   2097     theme()->platformColorsDidChange();
   2098 #endif
   2099 }
   2100 
   2101 void WebView::addUserScript(const WebString& sourceCode,
   2102                             const WebVector<WebString>& patternsIn,
   2103                             WebView::UserScriptInjectAt injectAt,
   2104                             WebView::UserContentInjectIn injectIn)
   2105 {
   2106     OwnPtr<Vector<String> > patterns(new Vector<String>);
   2107     for (size_t i = 0; i < patternsIn.size(); ++i)
   2108         patterns->append(patternsIn[i]);
   2109 
   2110     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
   2111     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::create());
   2112     pageGroup->addUserScriptToWorld(world.get(), sourceCode, WebURL(), patterns.release(), 0,
   2113                                     static_cast<UserScriptInjectionTime>(injectAt),
   2114                                     static_cast<UserContentInjectedFrames>(injectIn));
   2115 }
   2116 
   2117 void WebView::addUserStyleSheet(const WebString& sourceCode,
   2118                                 const WebVector<WebString>& patternsIn,
   2119                                 WebView::UserContentInjectIn injectIn,
   2120                                 WebView::UserStyleInjectionTime injectionTime)
   2121 {
   2122     OwnPtr<Vector<String> > patterns(new Vector<String>);
   2123     for (size_t i = 0; i < patternsIn.size(); ++i)
   2124         patterns->append(patternsIn[i]);
   2125 
   2126     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
   2127     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::create());
   2128 
   2129     // FIXME: Current callers always want the level to be "author". It probably makes sense to let
   2130     // callers specify this though, since in other cases the caller will probably want "user" level.
   2131     //
   2132     // FIXME: It would be nice to populate the URL correctly, instead of passing an empty URL.
   2133     pageGroup->addUserStyleSheetToWorld(world.get(), sourceCode, WebURL(), patterns.release(), 0,
   2134                                         static_cast<UserContentInjectedFrames>(injectIn),
   2135                                         UserStyleAuthorLevel,
   2136                                         static_cast<WebCore::UserStyleInjectionTime>(injectionTime));
   2137 }
   2138 
   2139 void WebView::removeAllUserContent()
   2140 {
   2141     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
   2142     pageGroup->removeAllUserContent();
   2143 }
   2144 
   2145 void WebViewImpl::didCommitLoad(bool* isNewNavigation)
   2146 {
   2147     if (isNewNavigation)
   2148         *isNewNavigation = m_observedNewNavigation;
   2149 
   2150 #ifndef NDEBUG
   2151     ASSERT(!m_observedNewNavigation
   2152         || m_page->mainFrame()->loader()->documentLoader() == m_newNavigationLoader);
   2153     m_newNavigationLoader = 0;
   2154 #endif
   2155     m_observedNewNavigation = false;
   2156 }
   2157 
   2158 bool WebViewImpl::useExternalPopupMenus()
   2159 {
   2160     return shouldUseExternalPopupMenus;
   2161 }
   2162 
   2163 bool WebViewImpl::navigationPolicyFromMouseEvent(unsigned short button,
   2164                                                  bool ctrl, bool shift,
   2165                                                  bool alt, bool meta,
   2166                                                  WebNavigationPolicy* policy)
   2167 {
   2168 #if OS(WINDOWS) || OS(LINUX) || OS(FREEBSD) || OS(SOLARIS)
   2169     const bool newTabModifier = (button == 1) || ctrl;
   2170 #elif OS(DARWIN)
   2171     const bool newTabModifier = (button == 1) || meta;
   2172 #endif
   2173     if (!newTabModifier && !shift && !alt)
   2174       return false;
   2175 
   2176     ASSERT(policy);
   2177     if (newTabModifier) {
   2178         if (shift)
   2179           *policy = WebNavigationPolicyNewForegroundTab;
   2180         else
   2181           *policy = WebNavigationPolicyNewBackgroundTab;
   2182     } else {
   2183         if (shift)
   2184           *policy = WebNavigationPolicyNewWindow;
   2185         else
   2186           *policy = WebNavigationPolicyDownload;
   2187     }
   2188     return true;
   2189 }
   2190 
   2191 void WebViewImpl::startDragging(const WebDragData& dragData,
   2192                                 WebDragOperationsMask mask,
   2193                                 const WebImage& dragImage,
   2194                                 const WebPoint& dragImageOffset)
   2195 {
   2196     if (!m_client)
   2197         return;
   2198     ASSERT(!m_doingDragAndDrop);
   2199     m_doingDragAndDrop = true;
   2200     m_client->startDragging(dragData, mask, dragImage, dragImageOffset);
   2201 }
   2202 
   2203 void WebViewImpl::observeNewNavigation()
   2204 {
   2205     m_observedNewNavigation = true;
   2206 #ifndef NDEBUG
   2207     m_newNavigationLoader = m_page->mainFrame()->loader()->documentLoader();
   2208 #endif
   2209 }
   2210 
   2211 void WebViewImpl::setIgnoreInputEvents(bool newValue)
   2212 {
   2213     ASSERT(m_ignoreInputEvents != newValue);
   2214     m_ignoreInputEvents = newValue;
   2215 }
   2216 
   2217 #if ENABLE(NOTIFICATIONS)
   2218 NotificationPresenterImpl* WebViewImpl::notificationPresenterImpl()
   2219 {
   2220     if (!m_notificationPresenter.isInitialized() && m_client)
   2221         m_notificationPresenter.initialize(m_client->notificationPresenter());
   2222     return &m_notificationPresenter;
   2223 }
   2224 #endif
   2225 
   2226 void WebViewImpl::refreshAutoFillPopup()
   2227 {
   2228     ASSERT(m_autoFillPopupShowing);
   2229 
   2230     // Hide the popup if it has become empty.
   2231     if (!m_autoFillPopupClient->listSize()) {
   2232         hideAutoFillPopup();
   2233         return;
   2234     }
   2235 
   2236     IntRect oldBounds = m_autoFillPopup->frameRect();
   2237     m_autoFillPopup->refresh(focusedWebCoreNode()->getRect());
   2238     IntRect newBounds = m_autoFillPopup->frameRect();
   2239     // Let's resize the backing window if necessary.
   2240     if (oldBounds != newBounds) {
   2241         WebPopupMenuImpl* popupMenu =
   2242             static_cast<WebPopupMenuImpl*>(m_autoFillPopup->client());
   2243         if (popupMenu)
   2244             popupMenu->client()->setWindowRect(newBounds);
   2245     }
   2246 }
   2247 
   2248 Node* WebViewImpl::focusedWebCoreNode()
   2249 {
   2250     Frame* frame = m_page->focusController()->focusedFrame();
   2251     if (!frame)
   2252         return 0;
   2253 
   2254     Document* document = frame->document();
   2255     if (!document)
   2256         return 0;
   2257 
   2258     return document->focusedNode();
   2259 }
   2260 
   2261 HitTestResult WebViewImpl::hitTestResultForWindowPos(const IntPoint& pos)
   2262 {
   2263     IntPoint docPoint(m_page->mainFrame()->view()->windowToContents(pos));
   2264     return m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(docPoint, false);
   2265 }
   2266 
   2267 void WebViewImpl::setTabsToLinks(bool enable)
   2268 {
   2269     m_tabsToLinks = enable;
   2270 }
   2271 
   2272 bool WebViewImpl::tabsToLinks() const
   2273 {
   2274     return m_tabsToLinks;
   2275 }
   2276 
   2277 #if USE(ACCELERATED_COMPOSITING)
   2278 bool WebViewImpl::allowsAcceleratedCompositing()
   2279 {
   2280     return !m_compositorCreationFailed;
   2281 }
   2282 
   2283 bool WebViewImpl::pageHasRTLStyle() const
   2284 {
   2285     if (!page())
   2286         return false;
   2287     Document* document = page()->mainFrame()->document();
   2288     if (!document)
   2289         return false;
   2290     RenderView* renderView = document->renderView();
   2291     if (!renderView)
   2292         return false;
   2293     RenderStyle* style = renderView->style();
   2294     if (!style)
   2295         return false;
   2296     return (style->direction() == RTL);
   2297 }
   2298 
   2299 void WebViewImpl::setRootGraphicsLayer(WebCore::PlatformLayer* layer)
   2300 {
   2301     setIsAcceleratedCompositingActive(layer);
   2302     if (m_layerRenderer)
   2303         m_layerRenderer->setRootLayer(layer);
   2304 
   2305     IntRect damagedRect(0, 0, m_size.width, m_size.height);
   2306     if (m_isAcceleratedCompositingActive)
   2307         invalidateRootLayerRect(damagedRect);
   2308     else
   2309         m_client->didInvalidateRect(damagedRect);
   2310 }
   2311 
   2312 void WebViewImpl::setRootLayerNeedsDisplay()
   2313 {
   2314     m_client->scheduleComposite();
   2315 }
   2316 
   2317 
   2318 void WebViewImpl::scrollRootLayerRect(const IntSize& scrollDelta, const IntRect& clipRect)
   2319 {
   2320     updateLayerRendererViewport();
   2321     setRootLayerNeedsDisplay();
   2322 }
   2323 
   2324 void WebViewImpl::invalidateRootLayerRect(const IntRect& rect)
   2325 {
   2326     ASSERT(m_layerRenderer);
   2327 
   2328     if (!page())
   2329         return;
   2330 
   2331     FrameView* view = page()->mainFrame()->view();
   2332     IntRect dirtyRect = view->windowToContents(rect);
   2333     updateLayerRendererViewport();
   2334     m_layerRenderer->invalidateRootLayerRect(dirtyRect);
   2335     setRootLayerNeedsDisplay();
   2336 }
   2337 
   2338 class WebViewImplContentPainter : public TilePaintInterface {
   2339     WTF_MAKE_NONCOPYABLE(WebViewImplContentPainter);
   2340 public:
   2341     static PassOwnPtr<WebViewImplContentPainter*> create(WebViewImpl* webViewImpl)
   2342     {
   2343         return adoptPtr(new WebViewImplContentPainter(webViewImpl));
   2344     }
   2345 
   2346     virtual void paint(GraphicsContext& context, const IntRect& contentRect)
   2347     {
   2348         Page* page = m_webViewImpl->page();
   2349         if (!page)
   2350             return;
   2351         FrameView* view = page->mainFrame()->view();
   2352         view->paintContents(&context, contentRect);
   2353     }
   2354 
   2355 private:
   2356     explicit WebViewImplContentPainter(WebViewImpl* webViewImpl)
   2357         : m_webViewImpl(webViewImpl)
   2358     {
   2359     }
   2360 
   2361     WebViewImpl* m_webViewImpl;
   2362 };
   2363 
   2364 void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
   2365 {
   2366     PlatformBridge::histogramEnumeration("GPU.setIsAcceleratedCompositingActive", active * 2 + m_isAcceleratedCompositingActive, 4);
   2367 
   2368     if (m_isAcceleratedCompositingActive == active)
   2369         return;
   2370 
   2371     if (!active) {
   2372         m_isAcceleratedCompositingActive = false;
   2373         // We need to finish all GL rendering before sending
   2374         // didActivateAcceleratedCompositing(false) to prevent
   2375         // flickering when compositing turns off.
   2376         if (m_layerRenderer)
   2377             m_layerRenderer->finish();
   2378         m_client->didActivateAcceleratedCompositing(false);
   2379     } else if (m_layerRenderer) {
   2380         m_isAcceleratedCompositingActive = true;
   2381         m_layerRenderer->resizeOnscreenContent(WebCore::IntSize(std::max(1, m_size.width),
   2382                                                                 std::max(1, m_size.height)));
   2383 
   2384         m_client->didActivateAcceleratedCompositing(true);
   2385     } else {
   2386         RefPtr<GraphicsContext3D> context = m_temporaryOnscreenGraphicsContext3D.release();
   2387         if (!context) {
   2388             context = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
   2389             if (context)
   2390                 context->reshape(std::max(1, m_size.width), std::max(1, m_size.height));
   2391         }
   2392 
   2393 
   2394         m_layerRenderer = LayerRendererChromium::create(context.release(), WebViewImplContentPainter::create(this));
   2395         if (m_layerRenderer) {
   2396             m_client->didActivateAcceleratedCompositing(true);
   2397             m_isAcceleratedCompositingActive = true;
   2398             m_compositorCreationFailed = false;
   2399         } else {
   2400             m_isAcceleratedCompositingActive = false;
   2401             m_client->didActivateAcceleratedCompositing(false);
   2402             m_compositorCreationFailed = true;
   2403         }
   2404     }
   2405     if (page())
   2406         page()->mainFrame()->view()->setClipsRepaints(!m_isAcceleratedCompositingActive);
   2407 }
   2408 
   2409 void WebViewImpl::doComposite()
   2410 {
   2411     ASSERT(m_layerRenderer);
   2412     if (!m_layerRenderer) {
   2413         setIsAcceleratedCompositingActive(false);
   2414         return;
   2415     }
   2416 
   2417     ASSERT(isAcceleratedCompositingActive());
   2418     if (!page())
   2419         return;
   2420 
   2421     m_layerRenderer->setCompositeOffscreen(settings()->compositeToTextureEnabled());
   2422 
   2423     CCHeadsUpDisplay* hud = m_layerRenderer->headsUpDisplay();
   2424     hud->setShowFPSCounter(settings()->showFPSCounter());
   2425     hud->setShowPlatformLayerTree(settings()->showPlatformLayerTree());
   2426 
   2427     m_layerRenderer->updateAndDrawLayers();
   2428 }
   2429 
   2430 void WebViewImpl::reallocateRenderer()
   2431 {
   2432     RefPtr<GraphicsContext3D> newContext = m_temporaryOnscreenGraphicsContext3D.get();
   2433     WebGraphicsContext3D* webContext = GraphicsContext3DInternal::extractWebGraphicsContext3D(newContext.get());
   2434     if (!newContext || !webContext || webContext->isContextLost())
   2435         newContext = GraphicsContext3D::create(
   2436             getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
   2437     // GraphicsContext3D::create might fail and return 0, in that case LayerRendererChromium::create will also return 0.
   2438     RefPtr<LayerRendererChromium> layerRenderer = LayerRendererChromium::create(newContext, WebViewImplContentPainter::create(this));
   2439 
   2440     // Reattach the root layer.  Child layers will get reattached as a side effect of updateLayersRecursive.
   2441     if (layerRenderer) {
   2442         m_layerRenderer->transferRootLayer(layerRenderer.get());
   2443         m_layerRenderer = layerRenderer;
   2444         // FIXME: In MacOS newContext->reshape method needs to be called to
   2445         // allocate IOSurfaces. All calls to create a context followed by
   2446         // reshape should really be extracted into one function; it is not
   2447         // immediately obvious that GraphicsContext3D object will not
   2448         // function properly until its reshape method is called.
   2449         newContext->reshape(std::max(1, m_size.width), std::max(1, m_size.height));
   2450         setRootGraphicsLayer(m_layerRenderer->rootLayer());
   2451         // Forces ViewHostMsg_DidActivateAcceleratedCompositing to be sent so
   2452         // that the browser process can reacquire surfaces.
   2453         m_client->didActivateAcceleratedCompositing(true);
   2454     } else
   2455         setRootGraphicsLayer(0);
   2456 }
   2457 #endif
   2458 
   2459 void WebViewImpl::updateLayerRendererViewport()
   2460 {
   2461     ASSERT(m_layerRenderer);
   2462 
   2463     if (!page())
   2464         return;
   2465 
   2466     FrameView* view = page()->mainFrame()->view();
   2467     IntRect contentRect = view->visibleContentRect(false);
   2468     IntRect visibleRect = view->visibleContentRect(true);
   2469     IntPoint scroll(view->scrollX(), view->scrollY());
   2470 
   2471     m_layerRenderer->setViewport(visibleRect, contentRect, scroll);
   2472 }
   2473 
   2474 WebGraphicsContext3D* WebViewImpl::graphicsContext3D()
   2475 {
   2476 #if USE(ACCELERATED_COMPOSITING)
   2477     if (m_page->settings()->acceleratedCompositingEnabled() && allowsAcceleratedCompositing()) {
   2478         if (m_layerRenderer) {
   2479             WebGraphicsContext3D* webContext = GraphicsContext3DInternal::extractWebGraphicsContext3D(m_layerRenderer->context());
   2480             if (webContext && !webContext->isContextLost())
   2481                 return webContext;
   2482         }
   2483         if (m_temporaryOnscreenGraphicsContext3D) {
   2484             WebGraphicsContext3D* webContext = GraphicsContext3DInternal::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get());
   2485             if (webContext && !webContext->isContextLost())
   2486                 return webContext;
   2487         }
   2488         m_temporaryOnscreenGraphicsContext3D = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
   2489         if (m_temporaryOnscreenGraphicsContext3D)
   2490             m_temporaryOnscreenGraphicsContext3D->reshape(std::max(1, m_size.width), std::max(1, m_size.height));
   2491         return GraphicsContext3DInternal::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get());
   2492     }
   2493 #endif
   2494     return 0;
   2495 }
   2496 
   2497 } // namespace WebKit
   2498