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