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