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