f47f9dcb8a430e9bbd4fcb408535e9335f10c201
[WebKit-https.git] / Source / WebKit / chromium / src / WebViewImpl.cpp
1 /*
2  * Copyright (C) 2011, 2012 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 "AXObjectCache.h"
35 #include "ActivePlatformGestureAnimation.h"
36 #include "AutofillPopupMenuClient.h"
37 #include "BackForwardListChromium.h"
38 #include "BatteryClientImpl.h"
39 #include "BatteryController.h"
40 #include "CSSValueKeywords.h"
41 #include "Chrome.h"
42 #include "Color.h"
43 #include "ColorSpace.h"
44 #include "CompositionUnderlineVectorBuilder.h"
45 #include "CompositorHUDFontAtlas.h"
46 #include "ContextFeaturesClientImpl.h"
47 #include "ContextMenu.h"
48 #include "ContextMenuController.h"
49 #include "ContextMenuItem.h"
50 #include "Cursor.h"
51 #include "DOMUtilitiesPrivate.h"
52 #include "DeviceOrientationClientProxy.h"
53 #include "Document.h"
54 #include "DocumentLoader.h"
55 #include "DragController.h"
56 #include "DragData.h"
57 #include "DragScrollTimer.h"
58 #include "DragSession.h"
59 #include "Editor.h"
60 #include "EventHandler.h"
61 #include "Extensions3D.h"
62 #include "FocusController.h"
63 #include "FontDescription.h"
64 #include "Frame.h"
65 #include "FrameLoader.h"
66 #include "FrameSelection.h"
67 #include "FrameTree.h"
68 #include "FrameView.h"
69 #include "GeolocationClientProxy.h"
70 #include "GeolocationController.h"
71 #include "GraphicsContext.h"
72 #include "GraphicsContext3D.h"
73 #include "GraphicsContext3DPrivate.h"
74 #include "HTMLInputElement.h"
75 #include "HTMLMediaElement.h"
76 #include "HTMLNames.h"
77 #include "HTMLTextAreaElement.h"
78 #include "HitTestResult.h"
79 #include "Image.h"
80 #include "ImageBuffer.h"
81 #include "InspectorController.h"
82 #include "InspectorInstrumentation.h"
83 #include "KeyboardCodes.h"
84 #include "KeyboardEvent.h"
85 #include "LayerPainterChromium.h"
86 #include "LinkHighlight.h"
87 #include "MIMETypeRegistry.h"
88 #include "NodeRenderStyle.h"
89 #include "NonCompositedContentHost.h"
90 #include "Page.h"
91 #include "PageGroup.h"
92 #include "PageGroupLoadDeferrer.h"
93 #include "PagePopupClient.h"
94 #include "PageWidgetDelegate.h"
95 #include "Pasteboard.h"
96 #include "PlatformContextSkia.h"
97 #include "PlatformKeyboardEvent.h"
98 #include "PlatformMouseEvent.h"
99 #include "PlatformThemeChromiumLinux.h"
100 #include "PlatformWheelEvent.h"
101 #include "PointerLockController.h"
102 #include "PopupContainer.h"
103 #include "PopupMenuClient.h"
104 #include "PrerendererClientImpl.h"
105 #include "ProgressTracker.h"
106 #include "RenderLayerCompositor.h"
107 #include "RenderView.h"
108 #include "RenderWidget.h"
109 #include "ResourceHandle.h"
110 #include "SchemeRegistry.h"
111 #include "SecurityOrigin.h"
112 #include "SecurityPolicy.h"
113 #include "Settings.h"
114 #include "SharedGraphicsContext3D.h"
115 #include "SpeechInputClientImpl.h"
116 #include "SpeechRecognitionClientProxy.h"
117 #include "StyleResolver.h"
118 #include "Text.h"
119 #include "TextFieldDecoratorImpl.h"
120 #include "TextIterator.h"
121 #include "Timer.h"
122 #include "TraceEvent.h"
123 #include "UserGestureIndicator.h"
124 #include "WebAccessibilityObject.h"
125 #include "WebActiveWheelFlingParameters.h"
126 #include "WebAutofillClient.h"
127 #include "WebDevToolsAgentImpl.h"
128 #include "WebDevToolsAgentPrivate.h"
129 #include "WebFrameImpl.h"
130 #include "WebHelperPluginImpl.h"
131 #include "WebHitTestResult.h"
132 #include "WebInputElement.h"
133 #include "WebInputEvent.h"
134 #include "WebInputEventConversion.h"
135 #include "WebMediaPlayerAction.h"
136 #include "WebNode.h"
137 #include "WebPagePopupImpl.h"
138 #include "WebPlugin.h"
139 #include "WebPluginAction.h"
140 #include "WebPluginContainerImpl.h"
141 #include "WebPopupMenuImpl.h"
142 #include "WebRange.h"
143 #include "WebRuntimeFeatures.h"
144 #include "WebSettingsImpl.h"
145 #include "WebTextInputInfo.h"
146 #include "WebViewClient.h"
147 #include "WheelEvent.h"
148 #include "painting/GraphicsContextBuilder.h"
149 #include <public/Platform.h>
150 #include <public/WebCompositorOutputSurface.h>
151 #include <public/WebCompositorSupport.h>
152 #include <public/WebDragData.h>
153 #include <public/WebFloatPoint.h>
154 #include <public/WebGraphicsContext3D.h>
155 #include <public/WebImage.h>
156 #include <public/WebLayer.h>
157 #include <public/WebLayerTreeView.h>
158 #include <public/WebPoint.h>
159 #include <public/WebRect.h>
160 #include <public/WebString.h>
161 #include <public/WebVector.h>
162 #include <wtf/CurrentTime.h>
163 #include <wtf/MainThread.h>
164 #include <wtf/RefPtr.h>
165 #include <wtf/TemporaryChange.h>
166 #include <wtf/Uint8ClampedArray.h>
167
168 #if ENABLE(GESTURE_EVENTS)
169 #include "PlatformGestureCurveFactory.h"
170 #include "PlatformGestureEvent.h"
171 #include "TouchDisambiguation.h"
172 #endif
173
174 #if OS(WINDOWS)
175 #include "RenderThemeChromiumWin.h"
176 #else
177 #if OS(UNIX) && !OS(DARWIN)
178 #include "RenderThemeChromiumLinux.h"
179 #endif
180 #include "RenderTheme.h"
181 #endif
182
183 // Get rid of WTF's pow define so we can use std::pow.
184 #undef pow
185 #include <cmath> // for std::pow
186
187 using namespace WebCore;
188 using namespace std;
189
190 // The following constants control parameters for automated scaling of webpages
191 // (such as due to a double tap gesture or find in page etc.). These are
192 // experimentally determined.
193 static const int touchPointPadding = 32;
194 static const float minScaleDifference = 0.01f;
195 static const float doubleTapZoomContentDefaultMargin = 5;
196 static const float doubleTapZoomContentMinimumMargin = 2;
197 static const double doubleTapZoomAnimationDurationInSeconds = 0.25;
198
199 // Constants for zooming in on a focused text field.
200 static const double scrollAndScaleAnimationDurationInSeconds = 0.2;
201
202 namespace WebKit {
203
204 // Change the text zoom level by kTextSizeMultiplierRatio each time the user
205 // zooms text in or out (ie., change by 20%).  The min and max values limit
206 // text zoom to half and 3x the original text size.  These three values match
207 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm
208 const double WebView::textSizeMultiplierRatio = 1.2;
209 const double WebView::minTextSizeMultiplier = 0.5;
210 const double WebView::maxTextSizeMultiplier = 3.0;
211 const float WebView::minPageScaleFactor = 0.25;
212 const float WebView::maxPageScaleFactor = 4.0;
213
214
215 // The group name identifies a namespace of pages. Page group is used on PLATFORM(MAC)
216 // for some programs that use HTML views to display things that don't seem like
217 // web pages to the user (so shouldn't have visited link coloring).  We only use
218 // one page group.
219 const char* pageGroupName = "default";
220
221 // Used to defer all page activity in cases where the embedder wishes to run
222 // a nested event loop. Using a stack enables nesting of message loop invocations.
223 static Vector<PageGroupLoadDeferrer*>& pageGroupLoadDeferrerStack()
224 {
225     DEFINE_STATIC_LOCAL(Vector<PageGroupLoadDeferrer*>, deferrerStack, ());
226     return deferrerStack;
227 }
228
229 // Ensure that the WebDragOperation enum values stay in sync with the original
230 // DragOperation constants.
231 #define COMPILE_ASSERT_MATCHING_ENUM(coreName) \
232     COMPILE_ASSERT(int(coreName) == int(Web##coreName), dummy##coreName)
233 COMPILE_ASSERT_MATCHING_ENUM(DragOperationNone);
234 COMPILE_ASSERT_MATCHING_ENUM(DragOperationCopy);
235 COMPILE_ASSERT_MATCHING_ENUM(DragOperationLink);
236 COMPILE_ASSERT_MATCHING_ENUM(DragOperationGeneric);
237 COMPILE_ASSERT_MATCHING_ENUM(DragOperationPrivate);
238 COMPILE_ASSERT_MATCHING_ENUM(DragOperationMove);
239 COMPILE_ASSERT_MATCHING_ENUM(DragOperationDelete);
240 COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery);
241
242 static const PopupContainerSettings autofillPopupSettings = {
243     false, // setTextOnIndexChange
244     false, // acceptOnAbandon
245     true, // loopSelectionNavigation
246     false // restrictWidthOfListBox (For security reasons show the entire entry
247           // so the user doesn't enter information he did not intend to.)
248 };
249
250 static bool shouldUseExternalPopupMenus = false;
251
252 static int webInputEventKeyStateToPlatformEventKeyState(int webInputEventKeyState)
253 {
254     int platformEventKeyState = 0;
255     if (webInputEventKeyState & WebInputEvent::ShiftKey)
256         platformEventKeyState = platformEventKeyState | WebCore::PlatformEvent::ShiftKey;
257     if (webInputEventKeyState & WebInputEvent::ControlKey)
258         platformEventKeyState = platformEventKeyState | WebCore::PlatformEvent::CtrlKey;
259     if (webInputEventKeyState & WebInputEvent::AltKey)
260         platformEventKeyState = platformEventKeyState | WebCore::PlatformEvent::AltKey;
261     if (webInputEventKeyState & WebInputEvent::MetaKey)
262         platformEventKeyState = platformEventKeyState | WebCore::PlatformEvent::MetaKey;
263     return platformEventKeyState;
264 }
265
266 // WebView ----------------------------------------------------------------
267
268 WebView* WebView::create(WebViewClient* client)
269 {
270     // Pass the WebViewImpl's self-reference to the caller.
271     return adoptRef(new WebViewImpl(client)).leakRef();
272 }
273
274 void WebView::setUseExternalPopupMenus(bool useExternalPopupMenus)
275 {
276     shouldUseExternalPopupMenus = useExternalPopupMenus;
277 }
278
279 void WebView::updateVisitedLinkState(unsigned long long linkHash)
280 {
281     Page::visitedStateChanged(PageGroup::pageGroup(pageGroupName), linkHash);
282 }
283
284 void WebView::resetVisitedLinkState()
285 {
286     Page::allVisitedStateChanged(PageGroup::pageGroup(pageGroupName));
287 }
288
289 void WebView::willEnterModalLoop()
290 {
291     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
292     ASSERT(pageGroup);
293
294     if (pageGroup->pages().isEmpty())
295         pageGroupLoadDeferrerStack().append(static_cast<PageGroupLoadDeferrer*>(0));
296     else {
297         // Pick any page in the page group since we are deferring all pages.
298         pageGroupLoadDeferrerStack().append(new PageGroupLoadDeferrer(*pageGroup->pages().begin(), true));
299     }
300 }
301
302 void WebView::didExitModalLoop()
303 {
304     ASSERT(pageGroupLoadDeferrerStack().size());
305
306     delete pageGroupLoadDeferrerStack().last();
307     pageGroupLoadDeferrerStack().removeLast();
308 }
309
310 void WebViewImpl::initializeMainFrame(WebFrameClient* frameClient)
311 {
312     // NOTE: The WebFrameImpl takes a reference to itself within InitMainFrame
313     // and releases that reference once the corresponding Frame is destroyed.
314     RefPtr<WebFrameImpl> frame = WebFrameImpl::create(frameClient);
315
316     frame->initializeAsMainFrame(page());
317
318     // Restrict the access to the local file system
319     // (see WebView.mm WebView::_commonInitializationWithFrameName).
320     SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForLocalOnly);
321 }
322
323 void WebViewImpl::initializeHelperPluginFrame(WebFrameClient* client)
324 {
325     RefPtr<WebFrameImpl> frame = WebFrameImpl::create(client);
326 }
327
328 void WebViewImpl::setAutofillClient(WebAutofillClient* autofillClient)
329 {
330     m_autofillClient = autofillClient;
331 }
332
333 void WebViewImpl::setDevToolsAgentClient(WebDevToolsAgentClient* devToolsClient)
334 {
335     if (devToolsClient)
336         m_devToolsAgent = adoptPtr(new WebDevToolsAgentImpl(this, devToolsClient));
337     else
338         m_devToolsAgent.clear();
339 }
340
341 void WebViewImpl::setPermissionClient(WebPermissionClient* permissionClient)
342 {
343     m_permissionClient = permissionClient;
344     m_featureSwitchClient->setPermissionClient(permissionClient);
345 }
346
347 void WebViewImpl::setPrerendererClient(WebPrerendererClient* prerendererClient)
348 {
349     providePrerendererClientTo(m_page.get(), new PrerendererClientImpl(prerendererClient));
350 }
351
352 void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient)
353 {
354     m_spellCheckClient = spellCheckClient;
355 }
356
357 void WebViewImpl::addTextFieldDecoratorClient(WebTextFieldDecoratorClient* client)
358 {
359     ASSERT(client);
360     // We limit the number of decorators because it affects performance of text
361     // field creation. If you'd like to add more decorators, consider moving
362     // your decorator or existing decorators to WebCore.
363     const unsigned maximumNumberOfDecorators = 8;
364     if (m_textFieldDecorators.size() >= maximumNumberOfDecorators)
365         CRASH();
366     m_textFieldDecorators.append(TextFieldDecoratorImpl::create(client));
367 }
368
369 WebViewImpl::WebViewImpl(WebViewClient* client)
370     : m_client(client)
371     , m_autofillClient(0)
372     , m_permissionClient(0)
373     , m_spellCheckClient(0)
374     , m_chromeClientImpl(this)
375     , m_contextMenuClientImpl(this)
376     , m_dragClientImpl(this)
377     , m_editorClientImpl(this)
378     , m_inspectorClientImpl(this)
379     , m_shouldAutoResize(false)
380     , m_observedNewNavigation(false)
381 #ifndef NDEBUG
382     , m_newNavigationLoader(0)
383 #endif
384     , m_zoomLevel(0)
385     , m_minimumZoomLevel(zoomFactorToZoomLevel(minTextSizeMultiplier))
386     , m_maximumZoomLevel(zoomFactorToZoomLevel(maxTextSizeMultiplier))
387     , m_pageDefinedMinimumPageScaleFactor(-1)
388     , m_pageDefinedMaximumPageScaleFactor(-1)
389     , m_minimumPageScaleFactor(minPageScaleFactor)
390     , m_maximumPageScaleFactor(maxPageScaleFactor)
391     , m_ignoreViewportTagMaximumScale(false)
392     , m_pageScaleFactorIsSet(false)
393     , m_savedPageScaleFactor(0)
394     , m_contextMenuAllowed(false)
395     , m_doingDragAndDrop(false)
396     , m_ignoreInputEvents(false)
397     , m_suppressNextKeypressEvent(false)
398     , m_initialNavigationPolicy(WebNavigationPolicyIgnore)
399     , m_imeAcceptEvents(true)
400     , m_operationsAllowed(WebDragOperationNone)
401     , m_dragOperation(WebDragOperationNone)
402     , m_featureSwitchClient(adoptPtr(new ContextFeaturesClientImpl()))
403     , m_autofillPopupShowing(false)
404     , m_autofillPopup(0)
405     , m_isTransparent(false)
406     , m_tabsToLinks(false)
407     , m_dragScrollTimer(adoptPtr(new DragScrollTimer))
408     , m_isCancelingFullScreen(false)
409     , m_benchmarkSupport(this)
410 #if USE(ACCELERATED_COMPOSITING)
411     , m_rootLayer(0)
412     , m_rootGraphicsLayer(0)
413     , m_isAcceleratedCompositingActive(false)
414     , m_compositorCreationFailed(false)
415     , m_recreatingGraphicsContext(false)
416     , m_compositorSurfaceReady(false)
417     , m_deviceScaleInCompositor(1)
418 #endif
419 #if ENABLE(INPUT_SPEECH)
420     , m_speechInputClient(SpeechInputClientImpl::create(client))
421 #endif
422 #if ENABLE(SCRIPTED_SPEECH)
423     , m_speechRecognitionClient(SpeechRecognitionClientProxy::create(client ? client->speechRecognizer() : 0))
424 #endif
425     , m_deviceOrientationClientProxy(adoptPtr(new DeviceOrientationClientProxy(client ? client->deviceOrientationClient() : 0)))
426     , m_geolocationClientProxy(adoptPtr(new GeolocationClientProxy(client ? client->geolocationClient() : 0)))
427 #if ENABLE(BATTERY_STATUS)
428     , m_batteryClient(adoptPtr(new BatteryClientImpl(client ? client->batteryStatusClient() : 0)))
429 #endif
430     , m_emulatedTextZoomFactor(1)
431 #if ENABLE(MEDIA_STREAM)
432     , m_userMediaClientImpl(this)
433 #endif
434 #if ENABLE(NAVIGATOR_CONTENT_UTILS)
435     , m_navigatorContentUtilsClient(NavigatorContentUtilsClientImpl::create(this))
436 #endif
437     , m_flingModifier(0)
438 {
439     // WebKit/win/WebView.cpp does the same thing, except they call the
440     // KJS specific wrapper around this method. We need to have threading
441     // initialized because CollatorICU requires it.
442     WTF::initializeThreading();
443     WTF::initializeMainThread();
444
445     Page::PageClients pageClients;
446     pageClients.chromeClient = &m_chromeClientImpl;
447     pageClients.contextMenuClient = &m_contextMenuClientImpl;
448     pageClients.editorClient = &m_editorClientImpl;
449     pageClients.dragClient = &m_dragClientImpl;
450     pageClients.inspectorClient = &m_inspectorClientImpl;
451     pageClients.backForwardClient = BackForwardListChromium::create(this);
452
453     m_page = adoptPtr(new Page(pageClients));
454 #if ENABLE(MEDIA_STREAM)
455     provideUserMediaTo(m_page.get(), &m_userMediaClientImpl);
456 #endif
457 #if ENABLE(INPUT_SPEECH)
458     provideSpeechInputTo(m_page.get(), m_speechInputClient.get());
459 #endif
460 #if ENABLE(SCRIPTED_SPEECH)
461     provideSpeechRecognitionTo(m_page.get(), m_speechRecognitionClient.get());
462 #endif
463 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
464     provideNotification(m_page.get(), notificationPresenterImpl());
465 #endif
466 #if ENABLE(NAVIGATOR_CONTENT_UTILS)
467     provideNavigatorContentUtilsTo(m_page.get(), m_navigatorContentUtilsClient.get());
468 #endif
469
470     provideContextFeaturesTo(m_page.get(), m_featureSwitchClient.get());
471     provideDeviceOrientationTo(m_page.get(), m_deviceOrientationClientProxy.get());
472     provideGeolocationTo(m_page.get(), m_geolocationClientProxy.get());
473     m_geolocationClientProxy->setController(GeolocationController::from(m_page.get()));
474
475 #if ENABLE(BATTERY_STATUS)
476     provideBatteryTo(m_page.get(), m_batteryClient.get());
477     m_batteryClient->setController(BatteryController::from(m_page.get()));
478 #endif
479
480     m_page->setGroupName(pageGroupName);
481
482 #if ENABLE(PAGE_VISIBILITY_API)
483     if (m_client)
484         setVisibilityState(m_client->visibilityState(), true);
485 #endif
486
487     m_inspectorSettingsMap = adoptPtr(new SettingsMap);
488 }
489
490 WebViewImpl::~WebViewImpl()
491 {
492     ASSERT(!m_page);
493 }
494
495 RenderTheme* WebViewImpl::theme() const
496 {
497     return m_page ? m_page->theme() : RenderTheme::defaultTheme().get();
498 }
499
500 WebFrameImpl* WebViewImpl::mainFrameImpl()
501 {
502     return m_page ? WebFrameImpl::fromFrame(m_page->mainFrame()) : 0;
503 }
504
505 bool WebViewImpl::tabKeyCyclesThroughElements() const
506 {
507     ASSERT(m_page);
508     return m_page->tabKeyCyclesThroughElements();
509 }
510
511 void WebViewImpl::setTabKeyCyclesThroughElements(bool value)
512 {
513     if (m_page)
514         m_page->setTabKeyCyclesThroughElements(value);
515 }
516
517 void WebViewImpl::handleMouseLeave(Frame& mainFrame, const WebMouseEvent& event)
518 {
519     m_client->setMouseOverURL(WebURL());
520     PageWidgetEventHandler::handleMouseLeave(mainFrame, event);
521 }
522
523 void WebViewImpl::handleMouseDown(Frame& mainFrame, const WebMouseEvent& event)
524 {
525     // If there is a popup open, close it as the user is clicking on the page (outside of the
526     // popup). We also save it so we can prevent a click on an element from immediately
527     // reopening the same popup.
528     RefPtr<WebCore::PopupContainer> selectPopup;
529 #if ENABLE(PAGE_POPUP)
530     RefPtr<WebPagePopupImpl> pagePopup;
531 #endif
532     if (event.button == WebMouseEvent::ButtonLeft) {
533         selectPopup = m_selectPopup;
534 #if ENABLE(PAGE_POPUP)
535         pagePopup = m_pagePopup;
536 #endif
537         hidePopups();
538         ASSERT(!m_selectPopup);
539 #if ENABLE(PAGE_POPUP)
540         ASSERT(!m_pagePopup);
541 #endif
542     }
543
544     m_lastMouseDownPoint = WebPoint(event.x, event.y);
545
546     if (event.button == WebMouseEvent::ButtonLeft) {
547         IntPoint point(event.x, event.y);
548         point = m_page->mainFrame()->view()->windowToContents(point);
549         HitTestResult result(m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false));
550         Node* hitNode = result.innerNonSharedNode();
551
552         // Take capture on a mouse down on a plugin so we can send it mouse events.
553         if (hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject())
554             m_mouseCaptureNode = hitNode;
555     }
556
557     PageWidgetEventHandler::handleMouseDown(mainFrame, event);
558
559     if (m_selectPopup && m_selectPopup == selectPopup) {
560         // That click triggered a select popup which is the same as the one that
561         // was showing before the click.  It means the user clicked the select
562         // while the popup was showing, and as a result we first closed then
563         // immediately reopened the select popup.  It needs to be closed.
564         hideSelectPopup();
565     }
566
567 #if ENABLE(PAGE_POPUP)
568     if (m_pagePopup && pagePopup && m_pagePopup->hasSamePopupClient(pagePopup.get())) {
569         // That click triggered a page popup that is the same as the one we just closed.
570         // It needs to be closed.
571         closePagePopup(m_pagePopup.get());
572     }
573 #endif
574
575     // Dispatch the contextmenu event regardless of if the click was swallowed.
576     // On Windows, we handle it on mouse up, not down.
577 #if OS(DARWIN)
578     if (event.button == WebMouseEvent::ButtonRight
579         || (event.button == WebMouseEvent::ButtonLeft
580             && event.modifiers & WebMouseEvent::ControlKey))
581         mouseContextMenu(event);
582 #elif OS(UNIX) || OS(ANDROID)
583     if (event.button == WebMouseEvent::ButtonRight)
584         mouseContextMenu(event);
585 #endif
586 }
587
588 void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
589 {
590     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
591         return;
592
593     m_page->contextMenuController()->clearContextMenu();
594
595     PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), event);
596
597     // Find the right target frame. See issue 1186900.
598     HitTestResult result = hitTestResultForWindowPos(pme.position());
599     Frame* targetFrame;
600     if (result.innerNonSharedNode())
601         targetFrame = result.innerNonSharedNode()->document()->frame();
602     else
603         targetFrame = m_page->focusController()->focusedOrMainFrame();
604
605 #if OS(WINDOWS)
606     targetFrame->view()->setCursor(pointerCursor());
607 #endif
608
609     m_contextMenuAllowed = true;
610     targetFrame->eventHandler()->sendContextMenuEvent(pme);
611     m_contextMenuAllowed = false;
612     // Actually showing the context menu is handled by the ContextMenuClient
613     // implementation...
614 }
615
616 void WebViewImpl::handleMouseUp(Frame& mainFrame, const WebMouseEvent& event)
617 {
618 #if OS(UNIX) && !OS(DARWIN)
619     // If the event was a middle click, attempt to copy text into the focused
620     // frame. We execute this before we let the page have a go at the event
621     // because the page may change what is focused during in its event handler.
622     //
623     // This code is in the mouse up handler. There is some debate about putting
624     // this here, as opposed to the mouse down handler.
625     //   xterm: pastes on up.
626     //   GTK: pastes on down.
627     //   Firefox: pastes on up.
628     //   Midori: couldn't paste at all with 0.1.2
629     //
630     // There is something of a webcompat angle to this well, as highlighted by
631     // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
632     // down then the text is pasted just before the onclick handler runs and
633     // clears the text box. So it's important this happens after the
634     // handleMouseReleaseEvent() earlier in this function
635     if (event.button == WebMouseEvent::ButtonMiddle) {
636         Frame* focused = focusedWebCoreFrame();
637         FrameView* view = m_page->mainFrame()->view();
638         IntPoint clickPoint(m_lastMouseDownPoint.x, m_lastMouseDownPoint.y);
639         IntPoint contentPoint = view->windowToContents(clickPoint);
640         HitTestResult hitTestResult = focused->eventHandler()->hitTestResultAtPoint(contentPoint, false, false, ShouldHitTestScrollbars);
641         // We don't want to send a paste when middle clicking a scroll bar or a
642         // link (which will navigate later in the code).  The main scrollbars
643         // have to be handled separately.
644         if (!hitTestResult.scrollbar() && !hitTestResult.isLiveLink() && focused && !view->scrollbarAtPoint(clickPoint)) {
645             Editor* editor = focused->editor();
646             editor->command(AtomicString("PasteGlobalSelection")).execute();
647         }
648     }
649 #endif
650
651     PageWidgetEventHandler::handleMouseUp(mainFrame, event);
652
653 #if OS(WINDOWS)
654     // Dispatch the contextmenu event regardless of if the click was swallowed.
655     // On Mac/Linux, we handle it on mouse down, not up.
656     if (event.button == WebMouseEvent::ButtonRight)
657         mouseContextMenu(event);
658 #endif
659 }
660
661 void WebViewImpl::scrollBy(const WebCore::IntPoint& delta)
662 {
663     WebMouseWheelEvent syntheticWheel;
664     const float tickDivisor = WebCore::WheelEvent::tickMultiplier;
665
666     syntheticWheel.deltaX = delta.x();
667     syntheticWheel.deltaY = delta.y();
668     syntheticWheel.wheelTicksX = delta.x() / tickDivisor;
669     syntheticWheel.wheelTicksY = delta.y() / tickDivisor;
670     syntheticWheel.hasPreciseScrollingDeltas = true;
671     syntheticWheel.x = m_lastWheelPosition.x;
672     syntheticWheel.y = m_lastWheelPosition.y;
673     syntheticWheel.globalX = m_lastWheelGlobalPosition.x;
674     syntheticWheel.globalY = m_lastWheelGlobalPosition.y;
675     syntheticWheel.modifiers = m_flingModifier;
676
677     if (m_page && m_page->mainFrame() && m_page->mainFrame()->view())
678         handleMouseWheel(*m_page->mainFrame(), syntheticWheel);
679 }
680
681 #if ENABLE(GESTURE_EVENTS)
682 bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event)
683 {
684     switch (event.type) {
685     case WebInputEvent::GestureFlingStart: {
686         m_client->cancelScheduledContentIntents();
687         m_lastWheelPosition = WebPoint(event.x, event.y);
688         m_lastWheelGlobalPosition = WebPoint(event.globalX, event.globalY);
689         m_flingModifier = event.modifiers;
690         // FIXME: Make the curve parametrizable from the browser.
691         OwnPtr<PlatformGestureCurve> flingCurve = PlatformGestureCurveFactory::get()->createCurve(event.data.flingStart.sourceDevice, FloatPoint(event.data.flingStart.velocityX, event.data.flingStart.velocityY));
692         m_gestureAnimation = ActivePlatformGestureAnimation::create(flingCurve.release(), this);
693         scheduleAnimation();
694         return true;
695     }
696     case WebInputEvent::GestureFlingCancel:
697         if (m_gestureAnimation) {
698             m_gestureAnimation.clear();
699             return true;
700         }
701         return false;
702     case WebInputEvent::GestureTap: {
703         m_client->cancelScheduledContentIntents();
704         if (detectContentOnTouch(WebPoint(event.x, event.y), event.type))
705             return true;
706
707         RefPtr<WebCore::PopupContainer> selectPopup;
708         selectPopup = m_selectPopup;
709         hideSelectPopup();
710         ASSERT(!m_selectPopup);
711
712         if (!event.boundingBox.isEmpty()) {
713             Vector<IntRect> goodTargets;
714             findGoodTouchTargets(event.boundingBox, mainFrameImpl()->frame(), pageScaleFactor(), goodTargets);
715             // FIXME: replace touch adjustment code when numberOfGoodTargets == 1?
716             // Single candidate case is currently handled by: https://bugs.webkit.org/show_bug.cgi?id=85101
717             if (goodTargets.size() >= 2 && m_client && m_client->didTapMultipleTargets(event, goodTargets))
718                 return true;
719         }
720
721         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
722         bool gestureHandled = mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
723
724         if (m_selectPopup && m_selectPopup == selectPopup) {
725             // That tap triggered a select popup which is the same as the one that
726             // was showing before the tap. It means the user tapped the select
727             // while the popup was showing, and as a result we first closed then
728             // immediately reopened the select popup. It needs to be closed.
729             hideSelectPopup();
730         }
731
732         return gestureHandled;
733     }
734     case WebInputEvent::GestureTwoFingerTap:
735     case WebInputEvent::GestureLongPress: {
736         if (!mainFrameImpl() || !mainFrameImpl()->frameView())
737             return false;
738
739         m_client->cancelScheduledContentIntents();
740         if (detectContentOnTouch(WebPoint(event.x, event.y), event.type))
741             return true;
742
743         m_page->contextMenuController()->clearContextMenu();
744         m_contextMenuAllowed = true;
745         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
746         bool handled = mainFrameImpl()->frame()->eventHandler()->sendContextMenuEventForGesture(platformEvent);
747         m_contextMenuAllowed = false;
748         return handled;
749     }
750     case WebInputEvent::GestureTapDown: {
751         m_client->cancelScheduledContentIntents();
752         // Queue a highlight animation, then hand off to regular handler.
753 #if OS(LINUX)
754         if (settingsImpl()->gestureTapHighlightEnabled())
755             enableTouchHighlight(IntPoint(event.x, event.y));
756 #endif
757         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
758         return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
759     }
760     case WebInputEvent::GestureDoubleTap:
761     case WebInputEvent::GestureScrollBegin:
762     case WebInputEvent::GesturePinchBegin:
763         m_client->cancelScheduledContentIntents();
764     case WebInputEvent::GestureScrollEnd:
765     case WebInputEvent::GestureScrollUpdate:
766     case WebInputEvent::GesturePinchEnd:
767     case WebInputEvent::GesturePinchUpdate: {
768         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
769         return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
770     }
771     default:
772         ASSERT_NOT_REACHED();
773     }
774     return false;
775 }
776
777 void WebViewImpl::transferActiveWheelFlingAnimation(const WebActiveWheelFlingParameters& parameters)
778 {
779     TRACE_EVENT0("webkit", "WebViewImpl::transferActiveWheelFlingAnimation");
780     ASSERT(!m_gestureAnimation);
781     m_lastWheelPosition = parameters.point;
782     m_lastWheelGlobalPosition = parameters.globalPoint;
783     m_flingModifier = parameters.modifiers;
784     OwnPtr<PlatformGestureCurve> curve = PlatformGestureCurveFactory::get()->createCurve(parameters.sourceDevice, parameters.delta, IntPoint(parameters.cumulativeScroll));
785     m_gestureAnimation = ActivePlatformGestureAnimation::create(curve.release(), this, parameters.startTime);
786     scheduleAnimation();
787 }
788
789 void WebViewImpl::renderingStats(WebRenderingStats& stats) const
790 {
791     if (m_layerTreeView)
792         m_layerTreeView->renderingStats(stats);
793 }
794
795 void WebViewImpl::startPageScaleAnimation(const IntPoint& targetPosition, bool useAnchor, float newScale, double durationInSeconds)
796 {
797     if (!m_layerTreeView)
798         return;
799
800     IntPoint clampedPoint = targetPosition;
801     if (!useAnchor)
802         clampedPoint = clampOffsetAtScale(targetPosition, newScale);
803
804     if (!durationInSeconds && !useAnchor) {
805         setPageScaleFactor(newScale, clampedPoint);
806         return;
807     }
808
809     m_layerTreeView->startPageScaleAnimation(targetPosition, useAnchor, newScale, durationInSeconds);
810 }
811 #endif
812
813 WebViewBenchmarkSupport* WebViewImpl::benchmarkSupport()
814 {
815     return &m_benchmarkSupport;
816 }
817
818 bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
819 {
820     ASSERT((event.type == WebInputEvent::RawKeyDown)
821         || (event.type == WebInputEvent::KeyDown)
822         || (event.type == WebInputEvent::KeyUp));
823
824     // Halt an in-progress fling on a key event.
825     if (m_gestureAnimation)
826         m_gestureAnimation.clear();
827
828     // Please refer to the comments explaining the m_suppressNextKeypressEvent
829     // member.
830     // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
831     // Webkit. A keyDown event is typically associated with a keyPress(char)
832     // event and a keyUp event. We reset this flag here as this is a new keyDown
833     // event.
834     m_suppressNextKeypressEvent = false;
835
836     // If there is a select popup, it should be the one processing the event,
837     // not the page.
838     if (m_selectPopup)
839         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
840 #if ENABLE(PAGE_POPUP)
841     if (m_pagePopup) {
842         m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
843         // We need to ignore the next Char event after this otherwise pressing
844         // enter when selecting an item in the popup will go to the page.
845         if (WebInputEvent::RawKeyDown == event.type)
846             m_suppressNextKeypressEvent = true;
847         return true;
848     }
849 #endif
850
851     // Give Autocomplete a chance to consume the key events it is interested in.
852     if (autocompleteHandleKeyEvent(event))
853         return true;
854
855     RefPtr<Frame> frame = focusedWebCoreFrame();
856     if (!frame)
857         return false;
858
859     EventHandler* handler = frame->eventHandler();
860     if (!handler)
861         return keyEventDefault(event);
862
863 #if !OS(DARWIN)
864     const WebInputEvent::Type contextMenuTriggeringEventType =
865 #if OS(WINDOWS)
866         WebInputEvent::KeyUp;
867 #elif OS(UNIX)
868         WebInputEvent::RawKeyDown;
869 #endif
870
871     bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS;
872     bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10;
873     if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) {
874         sendContextMenuEvent(event);
875         return true;
876     }
877 #endif // !OS(DARWIN)
878
879     PlatformKeyboardEventBuilder evt(event);
880
881     if (handler->keyEvent(evt)) {
882         if (WebInputEvent::RawKeyDown == event.type) {
883             // Suppress the next keypress event unless the focused node is a plug-in node.
884             // (Flash needs these keypress events to handle non-US keyboards.)
885             Node* node = focusedWebCoreNode();
886             if (!node || !node->renderer() || !node->renderer()->isEmbeddedObject())
887                 m_suppressNextKeypressEvent = true;
888         }
889         return true;
890     }
891
892     return keyEventDefault(event);
893 }
894
895 bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event)
896 {
897     if (!m_autofillPopupShowing
898         // Home and End should be left to the text field to process.
899         || event.windowsKeyCode == VKEY_HOME
900         || event.windowsKeyCode == VKEY_END)
901       return false;
902
903     // Pressing delete triggers the removal of the selected suggestion from the DB.
904     if (event.windowsKeyCode == VKEY_DELETE
905         && m_autofillPopup->selectedIndex() != -1) {
906         Node* node = focusedWebCoreNode();
907         if (!node || (node->nodeType() != Node::ELEMENT_NODE)) {
908             ASSERT_NOT_REACHED();
909             return false;
910         }
911         Element* element = static_cast<Element*>(node);
912         if (!element->hasLocalName(HTMLNames::inputTag)) {
913             ASSERT_NOT_REACHED();
914             return false;
915         }
916
917         int selectedIndex = m_autofillPopup->selectedIndex();
918
919         if (!m_autofillPopupClient->canRemoveSuggestionAtIndex(selectedIndex))
920             return false;
921
922         WebString name = WebInputElement(static_cast<HTMLInputElement*>(element)).nameForAutofill();
923         WebString value = m_autofillPopupClient->itemText(selectedIndex);
924         m_autofillClient->removeAutocompleteSuggestion(name, value);
925         // Update the entries in the currently showing popup to reflect the
926         // deletion.
927         m_autofillPopupClient->removeSuggestionAtIndex(selectedIndex);
928         refreshAutofillPopup();
929         return false;
930     }
931
932     if (!m_autofillPopup->isInterestedInEventForKey(event.windowsKeyCode))
933         return false;
934
935     if (m_autofillPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event))) {
936         // We need to ignore the next Char event after this otherwise pressing
937         // enter when selecting an item in the menu will go to the page.
938         if (WebInputEvent::RawKeyDown == event.type)
939             m_suppressNextKeypressEvent = true;
940         return true;
941     }
942
943     return false;
944 }
945
946 bool WebViewImpl::handleCharEvent(const WebKeyboardEvent& event)
947 {
948     ASSERT(event.type == WebInputEvent::Char);
949
950     // Please refer to the comments explaining the m_suppressNextKeypressEvent
951     // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
952     // handled by Webkit. A keyDown event is typically associated with a
953     // keyPress(char) event and a keyUp event. We reset this flag here as it
954     // only applies to the current keyPress event.
955     bool suppress = m_suppressNextKeypressEvent;
956     m_suppressNextKeypressEvent = false;
957
958     // If there is a select popup, it should be the one processing the event,
959     // not the page.
960     if (m_selectPopup)
961         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
962 #if ENABLE(PAGE_POPUP)
963     if (m_pagePopup)
964         return m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
965 #endif
966
967     Frame* frame = focusedWebCoreFrame();
968     if (!frame)
969         return suppress;
970
971     EventHandler* handler = frame->eventHandler();
972     if (!handler)
973         return suppress || keyEventDefault(event);
974
975     PlatformKeyboardEventBuilder evt(event);
976     if (!evt.isCharacterKey())
977         return true;
978
979     // Accesskeys are triggered by char events and can't be suppressed.
980     if (handler->handleAccessKey(evt))
981         return true;
982
983     // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
984     // the eventHandler::keyEvent. We mimic this behavior on all platforms since
985     // for now we are converting other platform's key events to windows key
986     // events.
987     if (evt.isSystemKey())
988         return false;
989
990     if (!suppress && !handler->keyEvent(evt))
991         return keyEventDefault(event);
992
993     return true;
994 }
995
996 #if ENABLE(GESTURE_EVENTS)
997 WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, AutoZoomType zoomType)
998 {
999     if (!mainFrameImpl())
1000         return WebRect();
1001
1002     // Use the rect-based hit test to find the node.
1003     IntPoint point = mainFrameImpl()->frameView()->windowToContents(IntPoint(rect.x, rect.y));
1004     HitTestResult result = mainFrameImpl()->frame()->eventHandler()->hitTestResultAtPoint(point,
1005             false, zoomType == FindInPage, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
1006             IntSize(rect.width, rect.height));
1007
1008     Node* node = result.innerNonSharedNode();
1009     if (!node)
1010         return WebRect();
1011
1012     // Find the block type node based on the hit node.
1013     while (node && (!node->renderer() || node->renderer()->isInline()))
1014         node = node->parentNode();
1015
1016     // Return the bounding box in the window coordinate system.
1017     if (node) {
1018         IntRect rect = node->Node::getPixelSnappedRect();
1019         Frame* frame = node->document()->frame();
1020         return frame->view()->contentsToWindow(rect);
1021     }
1022     return WebRect();
1023 }
1024
1025 WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int targetMargin, int minimumMargin)
1026 {
1027     WebSize maxSize;
1028     if (mainFrame())
1029         maxSize = mainFrame()->contentsSize();
1030     IntSize scrollOffset;
1031     if (mainFrame())
1032         scrollOffset = mainFrame()->scrollOffset();
1033     int leftMargin = targetMargin;
1034     int rightMargin = targetMargin;
1035
1036     const int absoluteSourceX = source.x + scrollOffset.width();
1037     if (leftMargin > absoluteSourceX) {
1038         leftMargin = absoluteSourceX;
1039         rightMargin = max(leftMargin, minimumMargin);
1040     }
1041
1042     const int maximumRightMargin = maxSize.width - (source.width + absoluteSourceX);
1043     if (rightMargin > maximumRightMargin) {
1044         rightMargin = maximumRightMargin;
1045         leftMargin = min(leftMargin, max(rightMargin, minimumMargin));
1046     }
1047
1048     const int newWidth = source.width + leftMargin + rightMargin;
1049     const int newX = source.x - leftMargin;
1050
1051     ASSERT(newWidth >= 0);
1052     ASSERT(scrollOffset.width() + newX + newWidth <= maxSize.width);
1053
1054     return WebRect(newX, source.y, newWidth, source.height);
1055 }
1056
1057 void WebViewImpl::computeScaleAndScrollForHitRect(const WebRect& hitRect, AutoZoomType zoomType, float& scale, WebPoint& scroll)
1058 {
1059     scale = pageScaleFactor();
1060     scroll.x = scroll.y = 0;
1061     WebRect targetRect = hitRect;
1062     if (targetRect.isEmpty())
1063         targetRect.width = targetRect.height = touchPointPadding;
1064
1065     WebRect rect = computeBlockBounds(targetRect, zoomType);
1066
1067     const float overviewScale = m_minimumPageScaleFactor;
1068     bool scaleUnchanged = true;
1069     if (!rect.isEmpty()) {
1070         // Pages should be as legible as on desktop when at dpi scale, so no
1071         // need to zoom in further when automatically determining zoom level
1072         // (after double tap, find in page, etc), though the user should still
1073         // be allowed to manually pinch zoom in further if they desire.
1074         const float maxScale = deviceScaleFactor();
1075
1076         const float defaultMargin = doubleTapZoomContentDefaultMargin * deviceScaleFactor();
1077         const float minimumMargin = doubleTapZoomContentMinimumMargin * deviceScaleFactor();
1078         // We want the margins to have the same physical size, which means we
1079         // need to express them in post-scale size. To do that we'd need to know
1080         // the scale we're scaling to, but that depends on the margins. Instead
1081         // we express them as a fraction of the target rectangle: this will be
1082         // correct if we end up fully zooming to it, and won't matter if we
1083         // don't.
1084         rect = widenRectWithinPageBounds(rect,
1085                 static_cast<int>(defaultMargin * rect.width / m_size.width),
1086                 static_cast<int>(minimumMargin * rect.width / m_size.width));
1087
1088         // Fit block to screen, respecting limits.
1089         scale *= static_cast<float>(m_size.width) / rect.width;
1090         scale = min(scale, maxScale);
1091         scale = clampPageScaleFactorToLimits(scale);
1092
1093         scaleUnchanged = fabs(pageScaleFactor() - scale) < minScaleDifference;
1094     }
1095
1096     if (zoomType == DoubleTap) {
1097         if (rect.isEmpty() || scaleUnchanged) {
1098             // Zoom out to overview mode.
1099             if (overviewScale)
1100                 scale = overviewScale;
1101             return;
1102         }
1103     } else if (rect.isEmpty()) {
1104         // Keep current scale (no need to scroll as x,y will normally already
1105         // be visible). FIXME: Revisit this if it isn't always true.
1106         return;
1107     }
1108
1109     // FIXME: If this is being called for auto zoom during find in page,
1110     // then if the user manually zooms in it'd be nice to preserve the relative
1111     // increase in zoom they caused (if they zoom out then it's ok to zoom
1112     // them back in again). This isn't compatible with our current double-tap
1113     // zoom strategy (fitting the containing block to the screen) though.
1114
1115     float screenHeight = m_size.height / scale * pageScaleFactor();
1116     float screenWidth = m_size.width / scale * pageScaleFactor();
1117
1118     // Scroll to vertically align the block.
1119     if (rect.height < screenHeight) {
1120         // Vertically center short blocks.
1121         rect.y -= 0.5 * (screenHeight - rect.height);
1122     } else {
1123         // Ensure position we're zooming to (+ padding) isn't off the bottom of
1124         // the screen.
1125         rect.y = max<float>(rect.y, hitRect.y + touchPointPadding - screenHeight);
1126     } // Otherwise top align the block.
1127
1128     // Do the same thing for horizontal alignment.
1129     if (rect.width < screenWidth)
1130         rect.x -= 0.5 * (screenWidth - rect.width);
1131     else
1132         rect.x = max<float>(rect.x, hitRect.x + touchPointPadding - screenWidth);
1133
1134     scroll.x = rect.x;
1135     scroll.y = rect.y;
1136 }
1137
1138 static bool highlightConditions(Node* node)
1139 {
1140     return node->supportsFocus()
1141            || node->hasEventListeners(eventNames().clickEvent)
1142            || node->hasEventListeners(eventNames().mousedownEvent)
1143            || node->hasEventListeners(eventNames().mouseupEvent);
1144 }
1145
1146 Node* WebViewImpl::bestTouchLinkNode(IntPoint touchEventLocation)
1147 {
1148     if (!m_page || !m_page->mainFrame())
1149         return 0;
1150
1151     Node* bestTouchNode = 0;
1152
1153     // FIXME: Should accept a search region from the caller instead of hard-coding the size.
1154     IntSize touchEventSearchRegionSize(4, 2);
1155     m_page->mainFrame()->eventHandler()->bestClickableNodeForTouchPoint(touchEventLocation, touchEventSearchRegionSize, touchEventLocation, bestTouchNode);
1156     // bestClickableNodeForTouchPoint() doesn't always return a node that is a link, so let's try and find
1157     // a link to highlight.
1158     while (bestTouchNode && !highlightConditions(bestTouchNode))
1159         bestTouchNode = bestTouchNode->parentNode();
1160
1161     // If the document has click handlers installed, we don't want to default to applying the highlight to the entire RenderView, or the
1162     // entire body. Also, if the node has non-auto Z-index, we cannot be sure of it's ordering with respect to other possible target nodes.
1163     RenderObject* touchNodeRenderer = bestTouchNode ? bestTouchNode->renderer() : 0;
1164     if (bestTouchNode && (!touchNodeRenderer || touchNodeRenderer->isRenderView() || touchNodeRenderer->isBody() || !touchNodeRenderer->style()->hasAutoZIndex()))
1165         return 0;
1166
1167     return bestTouchNode;
1168 }
1169
1170 void WebViewImpl::enableTouchHighlight(IntPoint touchEventLocation)
1171 {
1172     // Always clear any existing highlight when this is invoked, even if we don't get a new target to highlight.
1173     m_linkHighlight.clear();
1174
1175     Node* touchNode = bestTouchLinkNode(touchEventLocation);
1176
1177     if (!touchNode || !touchNode->renderer() || !touchNode->renderer()->enclosingLayer())
1178         return;
1179
1180     Color highlightColor = touchNode->renderer()->style()->tapHighlightColor();
1181     // Safari documentation for -webkit-tap-highlight-color says if the specified color has 0 alpha,
1182     // then tap highlighting is disabled.
1183     // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
1184     if (!highlightColor.alpha())
1185         return;
1186
1187     m_linkHighlight = LinkHighlight::create(touchNode, this);
1188     m_linkHighlight->startHighlightAnimation();
1189 }
1190
1191 #endif
1192
1193 void WebViewImpl::animateZoomAroundPoint(const IntPoint& point, AutoZoomType zoomType)
1194 {
1195 #if ENABLE(GESTURE_EVENTS)
1196     if (!mainFrameImpl())
1197         return;
1198
1199     float scale;
1200     WebPoint scroll;
1201     computeScaleAndScrollForHitRect(WebRect(point.x(), point.y(), 0, 0), zoomType, scale, scroll);
1202
1203     bool isDoubleTap = (zoomType == DoubleTap);
1204     double durationInSeconds = isDoubleTap ? doubleTapZoomAnimationDurationInSeconds : 0;
1205     startPageScaleAnimation(scroll, isDoubleTap, scale, durationInSeconds);
1206 #endif
1207 }
1208
1209 void WebViewImpl::zoomToFindInPageRect(const WebRect& rect)
1210 {
1211     animateZoomAroundPoint(IntRect(rect).center(), FindInPage);
1212 }
1213
1214 void WebViewImpl::numberOfWheelEventHandlersChanged(unsigned numberOfWheelHandlers)
1215 {
1216     if (m_client)
1217         m_client->numberOfWheelEventHandlersChanged(numberOfWheelHandlers);
1218 }
1219
1220 void WebViewImpl::hasTouchEventHandlers(bool hasTouchHandlers)
1221 {
1222     if (m_client)
1223         m_client->hasTouchEventHandlers(hasTouchHandlers);
1224 }
1225
1226 #if !OS(DARWIN)
1227 // Mac has no way to open a context menu based on a keyboard event.
1228 bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
1229 {
1230     // The contextMenuController() holds onto the last context menu that was
1231     // popped up on the page until a new one is created. We need to clear
1232     // this menu before propagating the event through the DOM so that we can
1233     // detect if we create a new menu for this event, since we won't create
1234     // a new menu if the DOM swallows the event and the defaultEventHandler does
1235     // not run.
1236     page()->contextMenuController()->clearContextMenu();
1237
1238     m_contextMenuAllowed = true;
1239     Frame* focusedFrame = page()->focusController()->focusedOrMainFrame();
1240     bool handled = focusedFrame->eventHandler()->sendContextMenuEventForKey();
1241     m_contextMenuAllowed = false;
1242     return handled;
1243 }
1244 #endif
1245
1246 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
1247 {
1248     Frame* frame = focusedWebCoreFrame();
1249     if (!frame)
1250         return false;
1251
1252     switch (event.type) {
1253     case WebInputEvent::Char:
1254         if (event.windowsKeyCode == VKEY_SPACE) {
1255             int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
1256             return scrollViewWithKeyboard(keyCode, event.modifiers);
1257         }
1258         break;
1259     case WebInputEvent::RawKeyDown:
1260         if (event.modifiers == WebInputEvent::ControlKey) {
1261             switch (event.windowsKeyCode) {
1262 #if !OS(DARWIN)
1263             case 'A':
1264                 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
1265                 return true;
1266             case VKEY_INSERT:
1267             case 'C':
1268                 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
1269                 return true;
1270 #endif
1271             // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
1272             // key combinations which affect scrolling. Safari is buggy in the
1273             // sense that it scrolls the page for all Ctrl+scrolling key
1274             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
1275             case VKEY_HOME:
1276             case VKEY_END:
1277                 break;
1278             default:
1279                 return false;
1280             }
1281         }
1282         if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
1283             return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
1284         break;
1285     default:
1286         break;
1287     }
1288     return false;
1289 }
1290
1291 bool WebViewImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
1292 {
1293     ScrollDirection scrollDirection;
1294     ScrollGranularity scrollGranularity;
1295 #if OS(DARWIN)
1296     // Control-Up/Down should be PageUp/Down on Mac.
1297     if (modifiers & WebMouseEvent::ControlKey) {
1298       if (keyCode == VKEY_UP)
1299         keyCode = VKEY_PRIOR;
1300       else if (keyCode == VKEY_DOWN)
1301         keyCode = VKEY_NEXT;
1302     }
1303 #endif
1304     if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
1305         return false;
1306     return propagateScroll(scrollDirection, scrollGranularity);
1307 }
1308
1309 bool WebViewImpl::mapKeyCodeForScroll(int keyCode,
1310                                       WebCore::ScrollDirection* scrollDirection,
1311                                       WebCore::ScrollGranularity* scrollGranularity)
1312 {
1313     switch (keyCode) {
1314     case VKEY_LEFT:
1315         *scrollDirection = ScrollLeft;
1316         *scrollGranularity = ScrollByLine;
1317         break;
1318     case VKEY_RIGHT:
1319         *scrollDirection = ScrollRight;
1320         *scrollGranularity = ScrollByLine;
1321         break;
1322     case VKEY_UP:
1323         *scrollDirection = ScrollUp;
1324         *scrollGranularity = ScrollByLine;
1325         break;
1326     case VKEY_DOWN:
1327         *scrollDirection = ScrollDown;
1328         *scrollGranularity = ScrollByLine;
1329         break;
1330     case VKEY_HOME:
1331         *scrollDirection = ScrollUp;
1332         *scrollGranularity = ScrollByDocument;
1333         break;
1334     case VKEY_END:
1335         *scrollDirection = ScrollDown;
1336         *scrollGranularity = ScrollByDocument;
1337         break;
1338     case VKEY_PRIOR:  // page up
1339         *scrollDirection = ScrollUp;
1340         *scrollGranularity = ScrollByPage;
1341         break;
1342     case VKEY_NEXT:  // page down
1343         *scrollDirection = ScrollDown;
1344         *scrollGranularity = ScrollByPage;
1345         break;
1346     default:
1347         return false;
1348     }
1349
1350     return true;
1351 }
1352
1353 void WebViewImpl::hideSelectPopup()
1354 {
1355     if (m_selectPopup)
1356         m_selectPopup->hidePopup();
1357 }
1358
1359 bool WebViewImpl::propagateScroll(ScrollDirection scrollDirection,
1360                                   ScrollGranularity scrollGranularity)
1361 {
1362     Frame* frame = focusedWebCoreFrame();
1363     if (!frame)
1364         return false;
1365
1366     bool scrollHandled = frame->eventHandler()->scrollOverflow(scrollDirection, scrollGranularity);
1367     Frame* currentFrame = frame;
1368     while (!scrollHandled && currentFrame) {
1369         scrollHandled = currentFrame->view()->scroll(scrollDirection, scrollGranularity);
1370         currentFrame = currentFrame->tree()->parent();
1371     }
1372     return scrollHandled;
1373 }
1374
1375 void  WebViewImpl::popupOpened(WebCore::PopupContainer* popupContainer)
1376 {
1377     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
1378         ASSERT(!m_selectPopup);
1379         m_selectPopup = popupContainer;
1380     }
1381 }
1382
1383 void  WebViewImpl::popupClosed(WebCore::PopupContainer* popupContainer)
1384 {
1385     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
1386         ASSERT(m_selectPopup);
1387         m_selectPopup = 0;
1388     }
1389 }
1390
1391 #if ENABLE(PAGE_POPUP)
1392 PagePopup* WebViewImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
1393 {
1394     ASSERT(client);
1395     if (hasOpenedPopup())
1396         hidePopups();
1397     ASSERT(!m_pagePopup);
1398
1399     WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypePage);
1400     ASSERT(popupWidget);
1401     m_pagePopup = static_cast<WebPagePopupImpl*>(popupWidget);
1402     if (!m_pagePopup->init(this, client, originBoundsInRootView)) {
1403         m_pagePopup->closePopup();
1404         m_pagePopup = 0;
1405     }
1406
1407     if (Frame* frame = focusedWebCoreFrame())
1408         frame->selection()->setCaretVisible(false);
1409     return m_pagePopup.get();
1410 }
1411
1412 void WebViewImpl::closePagePopup(PagePopup* popup)
1413 {
1414     ASSERT(popup);
1415     WebPagePopupImpl* popupImpl = static_cast<WebPagePopupImpl*>(popup);
1416     ASSERT(m_pagePopup.get() == popupImpl);
1417     if (m_pagePopup.get() != popupImpl)
1418         return;
1419     m_pagePopup->closePopup();
1420     m_pagePopup = 0;
1421
1422     if (Frame* frame = focusedWebCoreFrame())
1423         frame->selection()->pageActivationChanged();
1424 }
1425 #endif
1426
1427 void WebViewImpl::hideAutofillPopup()
1428 {
1429     if (m_autofillPopupShowing) {
1430         m_autofillPopup->hidePopup();
1431         m_autofillPopupShowing = false;
1432     }
1433 }
1434
1435 WebHelperPluginImpl* WebViewImpl::createHelperPlugin(const String& pluginType)
1436 {
1437     WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypeHelperPlugin);
1438     ASSERT(popupWidget);
1439     WebHelperPluginImpl* helperPlugin = static_cast<WebHelperPluginImpl*>(popupWidget);
1440
1441     if (!helperPlugin->init(this, pluginType)) {
1442         helperPlugin->closeHelperPlugin();
1443         helperPlugin = 0;
1444     }
1445     return helperPlugin;
1446 }
1447
1448 Frame* WebViewImpl::focusedWebCoreFrame() const
1449 {
1450     return m_page ? m_page->focusController()->focusedOrMainFrame() : 0;
1451 }
1452
1453 WebViewImpl* WebViewImpl::fromPage(Page* page)
1454 {
1455     if (!page)
1456         return 0;
1457
1458     ChromeClientImpl* chromeClient = static_cast<ChromeClientImpl*>(page->chrome()->client());
1459     return static_cast<WebViewImpl*>(chromeClient->webView());
1460 }
1461
1462 PageGroup* WebViewImpl::defaultPageGroup()
1463 {
1464     return PageGroup::pageGroup(pageGroupName);
1465 }
1466
1467 // WebWidget ------------------------------------------------------------------
1468
1469 void WebViewImpl::close()
1470 {
1471     RefPtr<WebFrameImpl> mainFrameImpl;
1472
1473     if (m_page) {
1474         // Initiate shutdown for the entire frameset.  This will cause a lot of
1475         // notifications to be sent.
1476         if (m_page->mainFrame()) {
1477             mainFrameImpl = WebFrameImpl::fromFrame(m_page->mainFrame());
1478             m_page->mainFrame()->loader()->frameDetached();
1479         }
1480         m_page.clear();
1481     }
1482
1483     // Should happen after m_page.clear().
1484     if (m_devToolsAgent)
1485         m_devToolsAgent.clear();
1486
1487     // Reset the delegate to prevent notifications being sent as we're being
1488     // deleted.
1489     m_client = 0;
1490
1491     deref();  // Balances ref() acquired in WebView::create
1492 }
1493
1494 void WebViewImpl::willStartLiveResize()
1495 {
1496     if (mainFrameImpl() && mainFrameImpl()->frameView())
1497         mainFrameImpl()->frameView()->willStartLiveResize();
1498
1499     Frame* frame = mainFrameImpl()->frame();
1500     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
1501     if (pluginContainer)
1502         pluginContainer->willStartLiveResize();
1503 }
1504
1505 void WebViewImpl::resize(const WebSize& newSize)
1506 {
1507     if (m_shouldAutoResize || m_size == newSize)
1508         return;
1509
1510     FrameView* view = mainFrameImpl()->frameView();
1511     if (!view)
1512         return;
1513
1514     WebSize oldSize = m_size;
1515     float oldPageScaleFactor = pageScaleFactor();
1516     IntSize oldScrollOffset = view->scrollOffset();
1517     int oldFixedLayoutWidth = fixedLayoutSize().width;
1518
1519     m_size = newSize;
1520
1521 #if ENABLE(VIEWPORT)
1522     if (settings()->viewportEnabled()) {
1523         // Fallback width is used to layout sites designed for desktop. The
1524         // conventional size used by all mobile browsers is 980. When a mobile
1525         // device has a particularly wide screen (such as a 10" tablet held in
1526         // landscape), it can be larger.
1527         const int standardFallbackWidth = 980;
1528         int dpiIndependentViewportWidth = newSize.width / page()->deviceScaleFactor();
1529         settings()->setLayoutFallbackWidth(std::max(standardFallbackWidth, dpiIndependentViewportWidth));
1530
1531         ViewportArguments viewportArguments = mainFrameImpl()->frame()->document()->viewportArguments();
1532         m_page->chrome()->client()->dispatchViewportPropertiesDidChange(viewportArguments);
1533     }
1534 #endif
1535
1536     WebDevToolsAgentPrivate* agentPrivate = devToolsAgentPrivate();
1537     if (agentPrivate && agentPrivate->metricsOverridden())
1538         agentPrivate->webViewResized();
1539     else {
1540         WebFrameImpl* webFrame = mainFrameImpl();
1541         if (webFrame->frameView())
1542             webFrame->frameView()->resize(newSize.width, newSize.height);
1543     }
1544
1545 #if ENABLE(VIEWPORT)
1546     if (settings()->viewportEnabled()) {
1547         // Relayout immediately to obtain the new content width, which is needed
1548         // to calculate the minimum scale limit.
1549         view->layout();
1550         computePageScaleFactorLimits();
1551         // When the device rotates:
1552         // - If the page width is unchanged, then zoom by new width/old width
1553         //   such as to keep the same content horizontally onscreen.
1554         // - If the page width stretches proportionally to the change in
1555         //   screen width, then don't zoom at all (assuming the content has
1556         //   scaled uniformly, then the same content will be horizontally
1557         //   onscreen).
1558         //   - If the page width partially stretches, then zoom partially to
1559         //   make up the difference.
1560         // In all cases try to keep the same content at the top of the screen.
1561         float viewportWidthRatio = !oldSize.width ? 1 : newSize.width / (float) oldSize.width;
1562         float fixedLayoutWidthRatio = !oldFixedLayoutWidth ? 1 : fixedLayoutSize().width / (float) oldFixedLayoutWidth;
1563         float scaleMultiplier = viewportWidthRatio / fixedLayoutWidthRatio;
1564         if (scaleMultiplier != 1) {
1565             IntSize scrollOffsetAtNewScale = oldScrollOffset;
1566             scrollOffsetAtNewScale.scale(scaleMultiplier);
1567             setPageScaleFactor(oldPageScaleFactor * scaleMultiplier, IntPoint(scrollOffsetAtNewScale));
1568         }
1569     }
1570 #endif
1571
1572     sendResizeEventAndRepaint();
1573 }
1574
1575 void WebViewImpl::willEndLiveResize()
1576 {
1577     if (mainFrameImpl() && mainFrameImpl()->frameView())
1578         mainFrameImpl()->frameView()->willEndLiveResize();
1579
1580     Frame* frame = mainFrameImpl()->frame();
1581     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
1582     if (pluginContainer)
1583         pluginContainer->willEndLiveResize();
1584 }
1585
1586 void WebViewImpl::willEnterFullScreen()
1587 {
1588 #if ENABLE(FULLSCREEN_API)
1589     if (!m_provisionalFullScreenElement)
1590         return;
1591
1592     // Ensure that this element's document is still attached.
1593     Document* doc = m_provisionalFullScreenElement->document();
1594     if (doc->frame()) {
1595         doc->webkitWillEnterFullScreenForElement(m_provisionalFullScreenElement.get());
1596         m_fullScreenFrame = doc->frame();
1597     }
1598     m_provisionalFullScreenElement.clear();
1599 #endif
1600 }
1601
1602 void WebViewImpl::didEnterFullScreen()
1603 {
1604 #if ENABLE(FULLSCREEN_API)
1605     if (!m_fullScreenFrame)
1606         return;
1607
1608     if (Document* doc = m_fullScreenFrame->document()) {
1609         if (doc->webkitIsFullScreen())
1610             doc->webkitDidEnterFullScreenForElement(0);
1611     }
1612 #endif
1613 }
1614
1615 void WebViewImpl::willExitFullScreen()
1616 {
1617 #if ENABLE(FULLSCREEN_API)
1618     if (!m_fullScreenFrame)
1619         return;
1620
1621     if (Document* doc = m_fullScreenFrame->document()) {
1622         if (doc->webkitIsFullScreen()) {
1623             // When the client exits from full screen we have to call webkitCancelFullScreen to
1624             // notify the document. While doing that, suppress notifications back to the client.
1625             m_isCancelingFullScreen = true;
1626             doc->webkitCancelFullScreen();
1627             m_isCancelingFullScreen = false;
1628             doc->webkitWillExitFullScreenForElement(0);
1629         }
1630     }
1631 #endif
1632 }
1633
1634 void WebViewImpl::didExitFullScreen()
1635 {
1636 #if ENABLE(FULLSCREEN_API)
1637     if (!m_fullScreenFrame)
1638         return;
1639
1640     if (Document* doc = m_fullScreenFrame->document()) {
1641         if (doc->webkitIsFullScreen())
1642             doc->webkitDidExitFullScreenForElement(0);
1643     }
1644
1645     m_fullScreenFrame.clear();
1646 #endif
1647 }
1648
1649 void WebViewImpl::instrumentBeginFrame()
1650 {
1651     InspectorInstrumentation::didBeginFrame(m_page.get());
1652 }
1653
1654 void WebViewImpl::instrumentCancelFrame()
1655 {
1656     InspectorInstrumentation::didCancelFrame(m_page.get());
1657 }
1658
1659 #if ENABLE(BATTERY_STATUS)
1660 void WebViewImpl::updateBatteryStatus(const WebBatteryStatus& status)
1661 {
1662     m_batteryClient->updateBatteryStatus(status);
1663 }
1664 #endif
1665
1666 void WebViewImpl::setCompositorSurfaceReady()
1667 {
1668     m_compositorSurfaceReady = true;
1669     if (m_layerTreeView)
1670         m_layerTreeView->setSurfaceReady();
1671 }
1672
1673 void WebViewImpl::animate(double)
1674 {
1675 #if ENABLE(REQUEST_ANIMATION_FRAME)
1676     double monotonicFrameBeginTime = monotonicallyIncreasingTime();
1677
1678 #if USE(ACCELERATED_COMPOSITING)
1679     // In composited mode, we always go through the compositor so it can apply
1680     // appropriate flow-control mechanisms.
1681     if (isAcceleratedCompositingActive())
1682         m_layerTreeView->updateAnimations(monotonicFrameBeginTime);
1683     else
1684 #endif
1685         updateAnimations(monotonicFrameBeginTime);
1686 #endif
1687 }
1688
1689 void WebViewImpl::willBeginFrame()
1690 {
1691     instrumentBeginFrame();
1692     m_client->willBeginCompositorFrame();
1693 }
1694
1695 void WebViewImpl::didBeginFrame()
1696 {
1697     InspectorInstrumentation::didComposite(m_page.get());
1698 }
1699
1700 void WebViewImpl::updateAnimations(double monotonicFrameBeginTime)
1701 {
1702 #if ENABLE(REQUEST_ANIMATION_FRAME)
1703     TRACE_EVENT0("webkit", "WebViewImpl::updateAnimations");
1704
1705     WebFrameImpl* webframe = mainFrameImpl();
1706     if (!webframe)
1707         return;
1708     FrameView* view = webframe->frameView();
1709     if (!view)
1710         return;
1711
1712     // Create synthetic wheel events as necessary for fling.
1713     if (m_gestureAnimation) {
1714         if (m_gestureAnimation->animate(monotonicFrameBeginTime))
1715             scheduleAnimation();
1716         else
1717             m_gestureAnimation.clear();
1718     }
1719
1720     PageWidgetDelegate::animate(m_page.get(), monotonicFrameBeginTime);
1721 #endif
1722 }
1723
1724 void WebViewImpl::layout()
1725 {
1726     TRACE_EVENT0("webkit", "WebViewImpl::layout");
1727     PageWidgetDelegate::layout(m_page.get());
1728
1729     if (m_linkHighlight)
1730         m_linkHighlight->updateGeometry();
1731 }
1732
1733 #if USE(ACCELERATED_COMPOSITING)
1734 void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect)
1735 {
1736     ASSERT(m_layerTreeView);
1737
1738     PlatformContextSkia context(canvas);
1739
1740     // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
1741     GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
1742     int bitmapHeight = canvas->getDevice()->accessBitmap(false).height();
1743
1744     // Compute rect to sample from inverted GPU buffer.
1745     IntRect invertRect(rect.x(), bitmapHeight - rect.maxY(), rect.width(), rect.height());
1746
1747     OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(rect.size()));
1748     RefPtr<Uint8ClampedArray> pixelArray(Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4));
1749     if (imageBuffer && pixelArray) {
1750         m_layerTreeView->compositeAndReadback(pixelArray->data(), invertRect);
1751         imageBuffer->putByteArray(Premultiplied, pixelArray.get(), rect.size(), IntRect(IntPoint(), rect.size()), IntPoint());
1752         gc.save();
1753         gc.translate(IntSize(0, bitmapHeight));
1754         gc.scale(FloatSize(1.0f, -1.0f));
1755         // Use invertRect in next line, so that transform above inverts it back to
1756         // desired destination rect.
1757         gc.drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, invertRect.location());
1758         gc.restore();
1759     }
1760 }
1761 #endif
1762
1763 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions option)
1764 {
1765 #if !OS(ANDROID)
1766     // ReadbackFromCompositorIfAvailable is the only option available on non-Android.
1767     // Ideally, Android would always use ReadbackFromCompositorIfAvailable as well.
1768     ASSERT(option == ReadbackFromCompositorIfAvailable);
1769 #endif
1770
1771     if (option == ReadbackFromCompositorIfAvailable && isAcceleratedCompositingActive()) {
1772 #if USE(ACCELERATED_COMPOSITING)
1773         // If a canvas was passed in, we use it to grab a copy of the
1774         // freshly-rendered pixels.
1775         if (canvas) {
1776             // Clip rect to the confines of the rootLayerTexture.
1777             IntRect resizeRect(rect);
1778             resizeRect.intersect(IntRect(IntPoint(0, 0), m_layerTreeView->deviceViewportSize()));
1779             doPixelReadbackToCanvas(canvas, resizeRect);
1780         }
1781 #endif
1782     } else {
1783         FrameView* view = page()->mainFrame()->view();
1784         PaintBehavior oldPaintBehavior = view->paintBehavior();
1785         if (isAcceleratedCompositingActive()) {
1786             ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);            
1787             view->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers);
1788         }
1789
1790         double paintStart = currentTime();
1791         PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
1792         double paintEnd = currentTime();
1793         double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart);
1794         WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
1795         WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
1796
1797         if (isAcceleratedCompositingActive()) {
1798             ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);            
1799             view->setPaintBehavior(oldPaintBehavior);
1800         }
1801     }
1802 }
1803
1804 void WebViewImpl::themeChanged()
1805 {
1806     if (!page())
1807         return;
1808     FrameView* view = page()->mainFrame()->view();
1809
1810     WebRect damagedRect(0, 0, m_size.width, m_size.height);
1811     view->invalidateRect(damagedRect);
1812 }
1813
1814 void WebViewImpl::composite(bool)
1815 {
1816 #if USE(ACCELERATED_COMPOSITING)
1817     if (Platform::current()->compositorSupport()->isThreadingEnabled())
1818         m_layerTreeView->setNeedsRedraw();
1819     else {
1820         ASSERT(isAcceleratedCompositingActive());
1821         if (!page())
1822             return;
1823
1824         if (m_pageOverlays)
1825             m_pageOverlays->update();
1826
1827         m_layerTreeView->composite();
1828     }
1829 #endif
1830 }
1831
1832 void WebViewImpl::setNeedsRedraw()
1833 {
1834 #if USE(ACCELERATED_COMPOSITING)
1835     if (m_layerTreeView && isAcceleratedCompositingActive())
1836         m_layerTreeView->setNeedsRedraw();
1837 #endif
1838 }
1839
1840 bool WebViewImpl::isInputThrottled() const
1841 {
1842 #if USE(ACCELERATED_COMPOSITING)
1843     if (m_layerTreeView && isAcceleratedCompositingActive())
1844         return m_layerTreeView->commitRequested();
1845 #endif
1846     return false;
1847 }
1848
1849 void WebViewImpl::loseCompositorContext(int numTimes)
1850 {
1851 #if USE(ACCELERATED_COMPOSITING)
1852     if (m_layerTreeView)
1853         m_layerTreeView->loseCompositorContext(numTimes);
1854 #endif
1855 }
1856
1857 void WebViewImpl::enterFullScreenForElement(WebCore::Element* element)
1858 {
1859     // We are already transitioning to fullscreen for a different element.
1860     if (m_provisionalFullScreenElement) {
1861         m_provisionalFullScreenElement = element;
1862         return;
1863     }
1864
1865     // We are already in fullscreen mode.
1866     if (m_fullScreenFrame) {
1867         m_provisionalFullScreenElement = element;
1868         willEnterFullScreen();
1869         didEnterFullScreen();
1870         return;
1871     }
1872
1873 #if USE(NATIVE_FULLSCREEN_VIDEO)
1874     if (element && element->isMediaElement()) {
1875         HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element);
1876         if (mediaElement->player() && mediaElement->player()->canEnterFullscreen()) {
1877             mediaElement->player()->enterFullscreen();
1878             m_provisionalFullScreenElement = element;
1879         }
1880         return;
1881     }
1882 #endif
1883
1884     // We need to transition to fullscreen mode.
1885     if (m_client && m_client->enterFullScreen())
1886         m_provisionalFullScreenElement = element;
1887 }
1888
1889 void WebViewImpl::exitFullScreenForElement(WebCore::Element* element)
1890 {
1891     // The client is exiting full screen, so don't send a notification.
1892     if (m_isCancelingFullScreen)
1893         return;
1894 #if USE(NATIVE_FULLSCREEN_VIDEO)
1895     if (element && element->isMediaElement()) {
1896         HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element);
1897         if (mediaElement->player())
1898             mediaElement->player()->exitFullscreen();
1899         return;
1900     }
1901 #endif
1902     if (m_client)
1903         m_client->exitFullScreen();
1904 }
1905
1906 bool WebViewImpl::hasHorizontalScrollbar()
1907 {
1908     return mainFrameImpl()->frameView()->horizontalScrollbar();
1909 }
1910
1911 bool WebViewImpl::hasVerticalScrollbar()
1912 {
1913     return mainFrameImpl()->frameView()->verticalScrollbar();
1914 }
1915
1916 const WebInputEvent* WebViewImpl::m_currentInputEvent = 0;
1917
1918 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
1919 {
1920     UserGestureIndicator gestureIndicator(WebInputEvent::isUserGestureEventType(inputEvent.type) ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
1921
1922     // If we've started a drag and drop operation, ignore input events until
1923     // we're done.
1924     if (m_doingDragAndDrop)
1925         return true;
1926
1927     // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
1928     if (m_ignoreInputEvents)
1929         return false;
1930
1931     TemporaryChange<const WebInputEvent*> currentEventChange(m_currentInputEvent, &inputEvent);
1932
1933 #if ENABLE(POINTER_LOCK)
1934     if (isPointerLocked() && WebInputEvent::isMouseEventType(inputEvent.type)) {
1935       pointerLockMouseEvent(inputEvent);
1936       return true;
1937     }
1938 #endif
1939
1940     if (m_mouseCaptureNode && WebInputEvent::isMouseEventType(inputEvent.type)) {
1941         // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
1942         RefPtr<Node> node = m_mouseCaptureNode;
1943
1944         // Not all platforms call mouseCaptureLost() directly.
1945         if (inputEvent.type == WebInputEvent::MouseUp)
1946             mouseCaptureLost();
1947
1948         AtomicString eventType;
1949         switch (inputEvent.type) {
1950         case WebInputEvent::MouseMove:
1951             eventType = eventNames().mousemoveEvent;
1952             break;
1953         case WebInputEvent::MouseLeave:
1954             eventType = eventNames().mouseoutEvent;
1955             break;
1956         case WebInputEvent::MouseDown:
1957             eventType = eventNames().mousedownEvent;
1958             break;
1959         case WebInputEvent::MouseUp:
1960             eventType = eventNames().mouseupEvent;
1961             break;
1962         default:
1963             ASSERT_NOT_REACHED();
1964         }
1965
1966         node->dispatchMouseEvent(
1967               PlatformMouseEventBuilder(mainFrameImpl()->frameView(), *static_cast<const WebMouseEvent*>(&inputEvent)),
1968               eventType, static_cast<const WebMouseEvent*>(&inputEvent)->clickCount);
1969         return true;
1970     }
1971
1972     bool handled = PageWidgetDelegate::handleInputEvent(m_page.get(), *this, inputEvent);
1973     return handled;
1974 }
1975
1976 void WebViewImpl::mouseCaptureLost()
1977 {
1978     m_mouseCaptureNode = 0;
1979 }
1980
1981 void WebViewImpl::setFocus(bool enable)
1982 {
1983     m_page->focusController()->setFocused(enable);
1984     if (enable) {
1985         m_page->focusController()->setActive(true);
1986         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
1987         if (focusedFrame) {
1988             Node* focusedNode = focusedFrame->document()->focusedNode();
1989             if (focusedNode && focusedNode->isElementNode()
1990                 && focusedFrame->selection()->selection().isNone()) {
1991                 // If the selection was cleared while the WebView was not
1992                 // focused, then the focus element shows with a focus ring but
1993                 // no caret and does respond to keyboard inputs.
1994                 Element* element = static_cast<Element*>(focusedNode);
1995                 if (element->isTextFormControl())
1996                     element->updateFocusAppearance(true);
1997                 else if (focusedNode->isContentEditable()) {
1998                     // updateFocusAppearance() selects all the text of
1999                     // contentseditable DIVs. So we set the selection explicitly
2000                     // instead. Note that this has the side effect of moving the
2001                     // caret back to the beginning of the text.
2002                     Position position(focusedNode, 0,
2003                                       Position::PositionIsOffsetInAnchor);
2004                     focusedFrame->selection()->setSelection(
2005                         VisibleSelection(position, SEL_DEFAULT_AFFINITY));
2006                 }
2007             }
2008         }
2009         m_imeAcceptEvents = true;
2010     } else {
2011         hidePopups();
2012
2013         // Clear focus on the currently focused frame if any.
2014         if (!m_page)
2015             return;
2016
2017         Frame* frame = m_page->mainFrame();
2018         if (!frame)
2019             return;
2020
2021         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
2022         if (focusedFrame) {
2023             // Finish an ongoing composition to delete the composition node.
2024             Editor* editor = focusedFrame->editor();
2025             if (editor && editor->hasComposition())
2026                 editor->confirmComposition();
2027             m_imeAcceptEvents = false;
2028         }
2029     }
2030 }
2031
2032 bool WebViewImpl::setComposition(
2033     const WebString& text,
2034     const WebVector<WebCompositionUnderline>& underlines,
2035     int selectionStart,
2036     int selectionEnd)
2037 {
2038     Frame* focused = focusedWebCoreFrame();
2039     if (!focused || !m_imeAcceptEvents)
2040         return false;
2041     Editor* editor = focused->editor();
2042     if (!editor)
2043         return false;
2044
2045     // The input focus has been moved to another WebWidget object.
2046     // We should use this |editor| object only to complete the ongoing
2047     // composition.
2048     if (!editor->canEdit() && !editor->hasComposition())
2049         return false;
2050
2051     // We should verify the parent node of this IME composition node are
2052     // editable because JavaScript may delete a parent node of the composition
2053     // node. In this case, WebKit crashes while deleting texts from the parent
2054     // node, which doesn't exist any longer.
2055     PassRefPtr<Range> range = editor->compositionRange();
2056     if (range) {
2057         Node* node = range->startContainer();
2058         if (!node || !node->isContentEditable())
2059             return false;
2060     }
2061
2062     // If we're not going to fire a keypress event, then the keydown event was
2063     // canceled.  In that case, cancel any existing composition.
2064     if (text.isEmpty() || m_suppressNextKeypressEvent) {
2065         // A browser process sent an IPC message which does not contain a valid
2066         // string, which means an ongoing composition has been canceled.
2067         // If the ongoing composition has been canceled, replace the ongoing
2068         // composition string with an empty string and complete it.
2069         String emptyString;
2070         Vector<CompositionUnderline> emptyUnderlines;
2071         editor->setComposition(emptyString, emptyUnderlines, 0, 0);
2072         return text.isEmpty();
2073     }
2074
2075     // When the range of composition underlines overlap with the range between
2076     // selectionStart and selectionEnd, WebKit somehow won't paint the selection
2077     // at all (see InlineTextBox::paint() function in InlineTextBox.cpp).
2078     // But the selection range actually takes effect.
2079     editor->setComposition(String(text),
2080                            CompositionUnderlineVectorBuilder(underlines),
2081                            selectionStart, selectionEnd);
2082
2083     return editor->hasComposition();
2084 }
2085
2086 bool WebViewImpl::confirmComposition()
2087 {
2088     return confirmComposition(WebString());
2089 }
2090
2091 bool WebViewImpl::confirmComposition(const WebString& text)
2092 {
2093     Frame* focused = focusedWebCoreFrame();
2094     if (!focused || !m_imeAcceptEvents)
2095         return false;
2096     Editor* editor = focused->editor();
2097     if (!editor || (!editor->hasComposition() && !text.length()))
2098         return false;
2099
2100     // We should verify the parent node of this IME composition node are
2101     // editable because JavaScript may delete a parent node of the composition
2102     // node. In this case, WebKit crashes while deleting texts from the parent
2103     // node, which doesn't exist any longer.
2104     PassRefPtr<Range> range = editor->compositionRange();
2105     if (range) {
2106         Node* node = range->startContainer();
2107         if (!node || !node->isContentEditable())
2108             return false;
2109     }
2110
2111     if (editor->hasComposition()) {
2112         if (text.length())
2113             editor->confirmComposition(String(text));
2114         else
2115             editor->confirmComposition();
2116     } else
2117         editor->insertText(String(text), 0);
2118
2119     return true;
2120 }
2121
2122 bool WebViewImpl::compositionRange(size_t* location, size_t* length)
2123 {
2124     Frame* focused = focusedWebCoreFrame();
2125     if (!focused || !focused->selection() || !m_imeAcceptEvents)
2126         return false;
2127     Editor* editor = focused->editor();
2128     if (!editor || !editor->hasComposition())
2129         return false;
2130
2131     RefPtr<Range> range = editor->compositionRange();
2132     if (!range)
2133         return false;
2134
2135     if (TextIterator::getLocationAndLengthFromRange(focused->selection()->rootEditableElementOrDocumentElement(), range.get(), *location, *length))
2136         return true;
2137     return false;
2138 }
2139
2140 WebTextInputInfo WebViewImpl::textInputInfo()
2141 {
2142     WebTextInputInfo info;
2143
2144     Frame* focused = focusedWebCoreFrame();
2145     if (!focused)
2146         return info;
2147
2148     Editor* editor = focused->editor();
2149     if (!editor || !editor->canEdit())
2150         return info;
2151
2152     FrameSelection* selection = focused->selection();
2153     if (!selection)
2154         return info;
2155
2156     Node* node = selection->selection().rootEditableElement();
2157     if (!node)
2158         return info;
2159
2160     info.type = textInputType();
2161     if (info.type == WebTextInputTypeNone)
2162         return info;
2163
2164     info.value = plainText(rangeOfContents(node).get());
2165
2166     if (info.value.isEmpty())
2167         return info;
2168
2169     size_t location;
2170     size_t length;
2171     RefPtr<Range> range = selection->selection().firstRange();
2172     if (range && TextIterator::getLocationAndLengthFromRange(selection->rootEditableElement(), range.get(), location, length)) {
2173         info.selectionStart = location;
2174         info.selectionEnd = location + length;
2175     }
2176     range = editor->compositionRange();
2177     if (range && TextIterator::getLocationAndLengthFromRange(selection->rootEditableElement(), range.get(), location, length)) {
2178         info.compositionStart = location;
2179         info.compositionEnd = location + length;
2180     }
2181
2182     return info;
2183 }
2184
2185 WebTextInputType WebViewImpl::textInputType()
2186 {
2187     Node* node = focusedWebCoreNode();
2188     if (!node)
2189         return WebTextInputTypeNone;
2190
2191     if (node->hasTagName(HTMLNames::inputTag)) {
2192         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
2193
2194         if (input->readOnly() || input->disabled())
2195             return WebTextInputTypeNone;
2196
2197         if (input->isPasswordField())
2198             return WebTextInputTypePassword;
2199         if (input->isSearchField())
2200             return WebTextInputTypeSearch;
2201         if (input->isEmailField())
2202             return WebTextInputTypeEmail;
2203         if (input->isNumberField())
2204             return WebTextInputTypeNumber;
2205         if (input->isTelephoneField())
2206             return WebTextInputTypeTelephone;
2207         if (input->isURLField())
2208             return WebTextInputTypeURL;
2209         if (input->isDateField())
2210             return WebTextInputTypeDate;
2211         if (input->isDateTimeField())
2212             return WebTextInputTypeDateTime;
2213         if (input->isDateTimeLocalField())
2214             return WebTextInputTypeDateTimeLocal;
2215         if (input->isMonthField())
2216             return WebTextInputTypeMonth;
2217         if (input->isTimeField())
2218             return WebTextInputTypeTime;
2219         if (input->isWeekField())
2220             return WebTextInputTypeWeek;
2221         if (input->isTextField())
2222             return WebTextInputTypeText;
2223
2224         return WebTextInputTypeNone;
2225     }
2226
2227     if (node->hasTagName(HTMLNames::textareaTag)) {
2228         HTMLTextAreaElement* textarea = static_cast<HTMLTextAreaElement*>(node);
2229
2230         if (textarea->readOnly() || textarea->disabled())
2231             return WebTextInputTypeNone;
2232
2233         return WebTextInputTypeTextArea;
2234     }
2235
2236     if (node->shouldUseInputMethod())
2237         return WebTextInputTypeContentEditable;
2238
2239     return WebTextInputTypeNone;
2240 }
2241
2242 bool WebViewImpl::selectionBounds(WebRect& start, WebRect& end) const
2243 {
2244     const Frame* frame = focusedWebCoreFrame();
2245     if (!frame)
2246         return false;
2247     FrameSelection* selection = frame->selection();
2248     if (!selection)
2249         return false;
2250
2251     if (selection->isCaret()) {
2252         start = end = frame->view()->contentsToWindow(selection->absoluteCaretBounds());
2253         return true;
2254     }
2255
2256     RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
2257     if (!selectedRange)
2258         return false;
2259
2260     RefPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
2261                                       selectedRange->startContainer(),
2262                                       selectedRange->startOffset(),
2263                                       selectedRange->startContainer(),
2264                                       selectedRange->startOffset()));
2265     start = frame->editor()->firstRectForRange(range.get());
2266
2267     range = Range::create(selectedRange->endContainer()->document(),
2268                           selectedRange->endContainer(),
2269                           selectedRange->endOffset(),
2270                           selectedRange->endContainer(),
2271                           selectedRange->endOffset());
2272     end = frame->editor()->firstRectForRange(range.get());
2273
2274     start = frame->view()->contentsToWindow(start);
2275     end = frame->view()->contentsToWindow(end);
2276
2277     if (!frame->selection()->selection().isBaseFirst())
2278         std::swap(start, end);
2279     return true;
2280 }
2281
2282 bool WebViewImpl::selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const
2283 {
2284     const Frame* frame = focusedWebCoreFrame();
2285     if (!frame)
2286         return false;
2287     FrameSelection* selection = frame->selection();
2288     if (!selection)
2289         return false;
2290     if (!selection->toNormalizedRange())
2291         return false;
2292     start = selection->start().primaryDirection() == RTL ? WebTextDirectionRightToLeft : WebTextDirectionLeftToRight;
2293     end = selection->end().primaryDirection() == RTL ? WebTextDirectionRightToLeft : WebTextDirectionLeftToRight;
2294     return true;
2295 }
2296
2297 bool WebViewImpl::setEditableSelectionOffsets(int start, int end)
2298 {
2299     const Frame* focused = focusedWebCoreFrame();
2300     if (!focused)
2301         return false;
2302
2303     Editor* editor = focused->editor();
2304     if (!editor || !editor->canEdit())
2305         return false;
2306
2307     return editor->setSelectionOffsets(start, end);
2308 }
2309
2310 bool WebViewImpl::setCompositionFromExistingText(int compositionStart, int compositionEnd, const WebVector<WebCompositionUnderline>& underlines)
2311 {
2312     const Frame* focused = focusedWebCoreFrame();
2313     if (!focused)
2314         return false;
2315
2316     Editor* editor = focused->editor();
2317     if (!editor || !editor->canEdit())
2318         return false;
2319
2320     editor->cancelComposition();
2321
2322     if (compositionStart == compositionEnd)
2323         return true;
2324
2325     size_t location;
2326     size_t length;
2327     caretOrSelectionRange(&location, &length);
2328     editor->setIgnoreCompositionSelectionChange(true);
2329     editor->setSelectionOffsets(compositionStart, compositionEnd);
2330     String text = editor->selectedText();
2331     focused->document()->execCommand("delete", true);
2332     editor->setComposition(text, CompositionUnderlineVectorBuilder(underlines), 0, 0);
2333     editor->setSelectionOffsets(location, location + length);
2334     editor->setIgnoreCompositionSelectionChange(false);
2335
2336     return true;
2337 }
2338
2339 void WebViewImpl::extendSelectionAndDelete(int before, int after)
2340 {
2341     const Frame* focused = focusedWebCoreFrame();
2342     if (!focused)
2343         return;
2344
2345     Editor* editor = focused->editor();
2346     if (!editor || !editor->canEdit())
2347         return;
2348
2349     FrameSelection* selection = focused->selection();
2350     if (!selection)
2351         return;
2352
2353     size_t location;
2354     size_t length;
2355     RefPtr<Range> range = selection->selection().firstRange();
2356     if (range && TextIterator::getLocationAndLengthFromRange(selection->rootEditableElement(), range.get(), location, length)) {
2357         editor->setSelectionOffsets(max(static_cast<int>(location) - before, 0), location + length + after);
2358         focused->document()->execCommand("delete", true);
2359     }
2360 }
2361
2362 bool WebViewImpl::isSelectionEditable() const
2363 {
2364     const Frame* frame = focusedWebCoreFrame();
2365     if (!frame)
2366         return false;
2367     return frame->selection()->isContentEditable();
2368 }
2369
2370 WebColor WebViewImpl::backgroundColor() const
2371 {
2372     if (!m_page)
2373         return Color::white;
2374     FrameView* view = m_page->mainFrame()->view();
2375     Color backgroundColor = view->documentBackgroundColor();
2376     if (!backgroundColor.isValid())
2377         return Color::white;
2378     return backgroundColor.rgb();
2379 }
2380
2381 bool WebViewImpl::caretOrSelectionRange(size_t* location, size_t* length)
2382 {
2383     const Frame* focused = focusedWebCoreFrame();
2384     if (!focused)
2385         return false;
2386
2387     FrameSelection* selection = focused->selection();
2388     if (!selection)
2389         return false;
2390
2391     RefPtr<Range> range = selection->selection().firstRange();
2392     if (!range)
2393         return false;
2394
2395     if (TextIterator::getLocationAndLengthFromRange(selection->rootEditableElementOrDocumentElement(), range.get(), *location, *length))
2396         return true;
2397     return false;
2398 }
2399
2400 void WebViewImpl::setTextDirection(WebTextDirection direction)
2401 {
2402     // The Editor::setBaseWritingDirection() function checks if we can change
2403     // the text direction of the selected node and updates its DOM "dir"
2404     // attribute and its CSS "direction" property.
2405     // So, we just call the function as Safari does.
2406     const Frame* focused = focusedWebCoreFrame();
2407     if (!focused)
2408         return;
2409
2410     Editor* editor = focused->editor();
2411     if (!editor || !editor->canEdit())
2412         return;
2413
2414     switch (direction) {
2415     case WebTextDirectionDefault:
2416         editor->setBaseWritingDirection(NaturalWritingDirection);
2417         break;
2418
2419     case WebTextDirectionLeftToRight:
2420         editor->setBaseWritingDirection(LeftToRightWritingDirection);
2421         break;
2422
2423     case WebTextDirectionRightToLeft:
2424         editor->setBaseWritingDirection(RightToLeftWritingDirection);
2425         break;
2426
2427     default:
2428         notImplemented();
2429         break;
2430     }
2431 }
2432
2433 bool WebViewImpl::isAcceleratedCompositingActive() const
2434 {
2435 #if USE(ACCELERATED_COMPOSITING)
2436     return m_isAcceleratedCompositingActive;
2437 #else
2438     return false;
2439 #endif
2440 }
2441
2442 void WebViewImpl::didAcquirePointerLock()
2443 {
2444 #if ENABLE(POINTER_LOCK)
2445     if (page())
2446         page()->pointerLockController()->didAcquirePointerLock();
2447 #endif
2448 }
2449
2450 void WebViewImpl::didNotAcquirePointerLock()
2451 {
2452 #if ENABLE(POINTER_LOCK)
2453     if (page())
2454         page()->pointerLockController()->didNotAcquirePointerLock();
2455 #endif
2456 }
2457
2458 void WebViewImpl::didLosePointerLock()
2459 {
2460 #if ENABLE(POINTER_LOCK)
2461     if (page())
2462         page()->pointerLockController()->didLosePointerLock();
2463 #endif
2464 }
2465
2466 void WebViewImpl::didChangeWindowResizerRect()
2467 {
2468     if (mainFrameImpl()->frameView())
2469         mainFrameImpl()->frameView()->windowResizerRectChanged();
2470 }
2471
2472 // WebView --------------------------------------------------------------------
2473
2474 WebSettingsImpl* WebViewImpl::settingsImpl()
2475 {
2476     if (!m_webSettings)
2477         m_webSettings = adoptPtr(new WebSettingsImpl(m_page->settings()));
2478     ASSERT(m_webSettings);
2479     return m_webSettings.get();
2480 }
2481
2482 WebSettings* WebViewImpl::settings()
2483 {
2484     return settingsImpl();
2485 }
2486
2487 WebString WebViewImpl::pageEncoding() const
2488 {
2489     if (!m_page)
2490         return WebString();
2491
2492     // FIXME: Is this check needed?
2493     if (!m_page->mainFrame()->document()->loader())
2494         return WebString();
2495
2496     return m_page->mainFrame()->document()->encoding();
2497 }
2498
2499 void WebViewImpl::setPageEncoding(const WebString& encodingName)
2500 {
2501     if (!m_page)
2502         return;
2503
2504     // Only change override encoding, don't change default encoding.
2505     // Note that the new encoding must be 0 if it isn't supposed to be set.
2506     String newEncodingName;
2507     if (!encodingName.isEmpty())
2508         newEncodingName = encodingName;
2509     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(newEncodingName);
2510 }
2511
2512 bool WebViewImpl::dispatchBeforeUnloadEvent()
2513 {
2514     // FIXME: This should really cause a recursive depth-first walk of all
2515     // frames in the tree, calling each frame's onbeforeunload.  At the moment,
2516     // we're consistent with Safari 3.1, not IE/FF.
2517     Frame* frame = m_page->mainFrame();
2518     if (!frame)
2519         return true;
2520
2521     return frame->loader()->shouldClose();
2522 }
2523
2524 void WebViewImpl::dispatchUnloadEvent()
2525 {
2526     // Run unload handlers.
2527     m_page->mainFrame()->loader()->closeURL();
2528 }
2529
2530 WebFrame* WebViewImpl::mainFrame()
2531 {
2532     return mainFrameImpl();
2533 }
2534
2535 WebFrame* WebViewImpl::findFrameByName(
2536     const WebString& name, WebFrame* relativeToFrame)
2537 {
2538     if (!relativeToFrame)
2539         relativeToFrame = mainFrame();
2540     Frame* frame = static_cast<WebFrameImpl*>(relativeToFrame)->frame();
2541     frame = frame->tree()->find(name);
2542     return WebFrameImpl::fromFrame(frame);
2543 }
2544
2545 WebFrame* WebViewImpl::focusedFrame()
2546 {
2547     return WebFrameImpl::fromFrame(focusedWebCoreFrame());
2548 }
2549
2550 void WebViewImpl::setFocusedFrame(WebFrame* frame)
2551 {
2552     if (!frame) {
2553         // Clears the focused frame if any.
2554         Frame* frame = focusedWebCoreFrame();
2555         if (frame)
2556             frame->selection()->setFocused(false);
2557         return;
2558     }
2559     WebFrameImpl* frameImpl = static_cast<WebFrameImpl*>(frame);
2560     Frame* webcoreFrame = frameImpl->frame();
2561     webcoreFrame->page()->focusController()->setFocusedFrame(webcoreFrame);
2562 }
2563
2564 void WebViewImpl::setInitialFocus(bool reverse)
2565 {
2566     if (!m_page)
2567         return;
2568
2569     // Since we don't have a keyboard event, we'll create one.
2570     WebKeyboardEvent keyboardEvent;
2571     keyboardEvent.type = WebInputEvent::RawKeyDown;
2572     if (reverse)
2573         keyboardEvent.modifiers = WebInputEvent::ShiftKey;
2574
2575     // VK_TAB which is only defined on Windows.
2576     keyboardEvent.windowsKeyCode = 0x09;
2577     PlatformKeyboardEventBuilder platformEvent(keyboardEvent);
2578     RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
2579
2580     Frame* frame = page()->focusController()->focusedOrMainFrame();
2581     if (Document* document = frame->document())
2582         document->setFocusedNode(0);
2583     page()->focusController()->setInitialFocus(
2584         reverse ? FocusDirectionBackward : FocusDirectionForward,
2585         webkitEvent.get());
2586 }
2587
2588 void WebViewImpl::clearFocusedNode()
2589 {
2590     RefPtr<Frame> frame = focusedWebCoreFrame();
2591     if (!frame)
2592         return;
2593
2594     RefPtr<Document> document = frame->document();
2595     if (!document)
2596         return;
2597
2598     RefPtr<Node> oldFocusedNode = document->focusedNode();
2599
2600     // Clear the focused node.
2601     document->setFocusedNode(0);
2602
2603     if (!oldFocusedNode)
2604         return;
2605
2606     // If a text field has focus, we need to make sure the selection controller
2607     // knows to remove selection from it. Otherwise, the text field is still
2608     // processing keyboard events even though focus has been moved to the page and
2609     // keystrokes get eaten as a result.
2610     if (oldFocusedNode->isContentEditable()
2611         || (oldFocusedNode->isElementNode()
2612             && static_cast<Element*>(oldFocusedNode.get())->isTextFormControl())) {
2613         frame->selection()->clear();
2614     }
2615 }
2616
2617 void WebViewImpl::scrollFocusedNodeIntoView()
2618 {
2619     Node* focusedNode = focusedWebCoreNode();
2620     if (focusedNode && focusedNode->isElementNode()) {
2621         Element* elementNode = static_cast<Element*>(focusedNode);
2622         elementNode->scrollIntoViewIfNeeded(true);
2623     }
2624 }
2625
2626 void WebViewImpl::scrollFocusedNodeIntoRect(const WebRect& rect)
2627 {
2628     Frame* frame = page()->mainFrame();
2629     Node* focusedNode = focusedWebCoreNode();
2630     if (!frame || !frame->view() || !focusedNode || !focusedNode->isElementNode())
2631         return;
2632     Element* elementNode = static_cast<Element*>(focusedNode);
2633     frame->view()->scrollElementToRect(elementNode, IntRect(rect.x, rect.y, rect.width, rect.height));
2634 }
2635
2636 void WebViewImpl::advanceFocus(bool reverse)
2637 {
2638     page()->focusController()->advanceFocus(reverse ? FocusDirectionBackward : FocusDirectionForward, 0);
2639 }
2640
2641 double WebViewImpl::zoomLevel()
2642 {
2643     return m_zoomLevel;
2644 }
2645
2646 double WebViewImpl::setZoomLevel(bool textOnly, double zoomLevel)
2647 {
2648     if (zoomLevel < m_minimumZoomLevel)
2649         m_zoomLevel = m_minimumZoomLevel;
2650     else if (zoomLevel > m_maximumZoomLevel)
2651         m_zoomLevel = m_maximumZoomLevel;
2652     else
2653         m_zoomLevel = zoomLevel;
2654
2655     Frame* frame = mainFrameImpl()->frame();
2656     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
2657     if (pluginContainer)
2658         pluginContainer->plugin()->setZoomLevel(m_zoomLevel, textOnly);
2659     else {
2660         float zoomFactor = static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel));
2661         if (textOnly)
2662             frame->setPageAndTextZoomFactors(1, zoomFactor * m_emulatedTextZoomFactor);
2663         else
2664             frame->setPageAndTextZoomFactors(zoomFactor, m_emulatedTextZoomFactor);
2665     }
2666     return m_zoomLevel;
2667 }
2668
2669 void WebViewImpl::zoomLimitsChanged(double minimumZoomLevel,
2670                                     double maximumZoomLevel)
2671 {
2672     m_minimumZoomLevel = minimumZoomLevel;
2673     m_maximumZoomLevel = maximumZoomLevel;
2674     m_client->zoomLimitsChanged(m_minimumZoomLevel, m_maximumZoomLevel);
2675 }
2676
2677 void WebViewImpl::fullFramePluginZoomLevelChanged(double zoomLevel)
2678 {
2679     if (zoomLevel == m_zoomLevel)
2680         return;
2681
2682     m_zoomLevel = max(min(zoomLevel, m_maximumZoomLevel), m_minimumZoomLevel);
2683     m_client->zoomLevelChanged();
2684 }
2685
2686 double WebView::zoomLevelToZoomFactor(double zoomLevel)
2687 {
2688     return pow(textSizeMultiplierRatio, zoomLevel);
2689 }
2690
2691 double WebView::zoomFactorToZoomLevel(double factor)
2692 {
2693     // Since factor = 1.2^level, level = log(factor) / log(1.2)
2694     return log(factor) / log(textSizeMultiplierRatio);
2695 }
2696
2697 float WebViewImpl::pageScaleFactor() const
2698 {
2699     if (!page())
2700         return 1;
2701
2702     return page()->pageScaleFactor();
2703 }
2704
2705 bool WebViewImpl::isPageScaleFactorSet() const
2706 {
2707     return m_pageScaleFactorIsSet;
2708 }
2709
2710 float WebViewImpl::clampPageScaleFactorToLimits(float scaleFactor)
2711 {
2712     return min(max(scaleFactor, m_minimumPageScaleFactor), m_maximumPageScaleFactor);
2713 }
2714
2715 WebPoint WebViewImpl::clampOffsetAtScale(const WebPoint& offset, float scale)
2716 {
2717     // This is the scaled content size. We need to convert it to the new scale factor.
2718     WebSize contentSize = mainFrame()->contentsSize();
2719     float deltaScale = scale / pageScaleFactor();
2720     int docWidthAtNewScale = contentSize.width * deltaScale;
2721     int docHeightAtNewScale = contentSize.height * deltaScale;
2722     int viewWidth = m_size.width;
2723     int viewHeight = m_size.height;
2724
2725     // Enforce the maximum and minimum scroll positions at the new scale.
2726     IntPoint clampedOffset = offset;
2727     clampedOffset = clampedOffset.shrunkTo(IntPoint(docWidthAtNewScale - viewWidth, docHeightAtNewScale - viewHeight));
2728     clampedOffset.clampNegativeToZero();
2729     return clampedOffset;
2730 }
2731
2732 void WebViewImpl::setPageScaleFactorPreservingScrollOffset(float scaleFactor)
2733 {
2734     // Pick a scale factor that is within the expected limits
2735     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
2736
2737     IntPoint scrollOffsetAtNewScale(mainFrame()->scrollOffset().width, mainFrame()->scrollOffset().height);
2738     float deltaScale = scaleFactor / pageScaleFactor();
2739     scrollOffsetAtNewScale.scale(deltaScale, deltaScale);
2740
2741     WebPoint clampedOffsetAtNewScale = clampOffsetAtScale(scrollOffsetAtNewScale, scaleFactor);
2742     setPageScaleFactor(scaleFactor, clampedOffsetAtNewScale);
2743 }
2744
2745 void WebViewImpl::setPageScaleFactor(float scaleFactor, const WebPoint& origin)
2746 {
2747     if (!page())
2748         return;
2749
2750     if (!scaleFactor)
2751         scaleFactor = 1;
2752
2753     if (m_deviceScaleInCompositor != 1) {
2754         // Don't allow page scaling when compositor scaling is being used,
2755         // as they are currently incompatible.
2756         ASSERT(scaleFactor == 1);
2757     }
2758
2759     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
2760     WebPoint clampedOrigin = clampOffsetAtScale(origin, scaleFactor);
2761     page()->setPageScaleFactor(scaleFactor, clampedOrigin);
2762     m_pageScaleFactorIsSet = true;
2763 }
2764
2765 float WebViewImpl::deviceScaleFactor() const
2766 {
2767     if (!page())
2768         return 1;
2769
2770     return page()->deviceScaleFactor();
2771 }
2772
2773 void WebViewImpl::setDeviceScaleFactor(float scaleFactor)
2774 {
2775     if (!page())
2776         return;
2777
2778     page()->setDeviceScaleFactor(scaleFactor);
2779
2780     if (m_layerTreeView && m_webSettings->applyDefaultDeviceScaleFactorInCompositor()) {
2781         m_deviceScaleInCompositor = page()->deviceScaleFactor();
2782         m_layerTreeView->setDeviceScaleFactor(m_deviceScaleInCompositor);
2783     }
2784     if (m_deviceScaleInCompositor != 1) {
2785         // Don't allow page scaling when compositor scaling is being used,
2786         // as they are currently incompatible. This means the deviceScale
2787         // needs to match the one in the compositor.
2788         ASSERT(scaleFactor == m_deviceScaleInCompositor);
2789     }
2790 }
2791
2792 bool WebViewImpl::isFixedLayoutModeEnabled() const
2793 {
2794     if (!page())
2795         return false;
2796
2797     Frame* frame = page()->mainFrame();
2798     if (!frame || !frame->view())
2799         return false;
2800
2801     return frame->view()->useFixedLayout();
2802 }
2803
2804 void WebViewImpl::enableFixedLayoutMode(bool enable)
2805 {
2806     if (!page())
2807         return;
2808
2809     Frame* frame = page()->mainFrame();
2810     if (!frame || !frame->view())
2811         return;
2812
2813     frame->view()->setUseFixedLayout(enable);
2814
2815 #if USE(ACCELERATED_COMPOSITING)
2816     // Also notify the base layer, which RenderLayerCompositor does not see.
2817     if (m_nonCompositedContentHost)
2818         updateLayerTreeViewport();
2819 #endif
2820 }
2821
2822
2823 void WebViewImpl::enableAutoResizeMode(const WebSize& minSize, const WebSize& maxSize)
2824 {
2825     m_shouldAutoResize = true;
2826     m_minAutoSize = minSize;
2827     m_maxAutoSize = maxSize;
2828     configureAutoResizeMode();
2829 }
2830
2831 void WebViewImpl::disableAutoResizeMode()
2832 {
2833     m_shouldAutoResize = false;
2834     configureAutoResizeMode();
2835 }
2836
2837 void WebViewImpl::setPageScaleFactorLimits(float minPageScale, float maxPageScale)
2838 {
2839     m_pageDefinedMinimumPageScaleFactor = minPageScale;
2840     m_pageDefinedMaximumPageScaleFactor = maxPageScale;
2841     computePageScaleFactorLimits();
2842 }
2843
2844 void WebViewImpl::setIgnoreViewportTagMaximumScale(bool flag)
2845 {
2846     m_ignoreViewportTagMaximumScale = flag;
2847
2848     if (!page() || !page()->mainFrame())
2849         return;
2850
2851     m_page->chrome()->client()->dispatchViewportPropertiesDidChange(page()->mainFrame()->document()->viewportArguments());
2852 }
2853
2854 bool WebViewImpl::computePageScaleFactorLimits()
2855 {
2856     if (m_pageDefinedMinimumPageScaleFactor == -1 || m_pageDefinedMaximumPageScaleFactor == -1)
2857         return false;
2858
2859     if (!mainFrame() || !page() || !page()->mainFrame() || !page()->mainFrame()->view())
2860         return false;
2861
2862     m_minimumPageScaleFactor = min(max(m_pageDefinedMinimumPageScaleFactor, minPageScaleFactor), maxPageScaleFactor) * (deviceScaleFactor() / m_deviceScaleInCompositor);
2863     m_maximumPageScaleFactor = max(min(m_pageDefinedMaximumPageScaleFactor, maxPageScaleFactor), minPageScaleFactor) * (deviceScaleFactor() / m_deviceScaleInCompositor);
2864
2865     int viewWidthNotIncludingScrollbars = page()->mainFrame()->view()->visibleContentRect(false).width();
2866     int contentsWidth = mainFrame()->contentsSize().width;
2867     if (viewWidthNotIncludingScrollbars && contentsWidth) {
2868         // Limit page scaling down to the document width.
2869         int unscaledContentWidth = contentsWidth / pageScaleFactor();
2870         m_minimumPageScaleFactor = max(m_minimumPageScaleFactor, static_cast<float>(viewWidthNotIncludingScrollbars) / unscaledContentWidth);
2871         m_maximumPageScaleFactor = max(m_minimumPageScaleFactor, m_maximumPageScaleFactor);
2872     }
2873     ASSERT(m_minimumPageScaleFactor <= m_maximumPageScaleFactor);
2874
2875     float clampedScale = clampPageScaleFactorToLimits(pageScaleFactor());
2876 #if USE(ACCELERATED_COMPOSITING)
2877     if (m_layerTreeView)
2878         m_layerTreeView->setPageScaleFactorAndLimits(clampedScale, m_minimumPageScaleFactor, m_maximumPageScaleFactor);
2879 #endif
2880     if (clampedScale != pageScaleFactor()) {
2881         setPageScaleFactorPreservingScrollOffset(clampedScale);
2882         return true;
2883     }
2884
2885     return false;
2886 }
2887
2888 float WebViewImpl::minimumPageScaleFactor() const
2889 {
2890     return m_minimumPageScaleFactor;
2891 }
2892
2893 float WebViewImpl::maximumPageScaleFactor() const
2894 {
2895     return m_maximumPageScaleFactor;
2896 }
2897
2898 void WebViewImpl::saveScrollAndScaleState()
2899 {
2900     m_savedPageScaleFactor = pageScaleFactor();
2901     m_savedScrollOffset = mainFrame()->scrollOffset();
2902 }
2903
2904 void WebViewImpl::restoreScrollAndScaleState()
2905 {
2906     if (!m_savedPageScaleFactor)
2907         return;
2908
2909 #if ENABLE(GESTURE_EVENTS)
2910     startPageScaleAnimation(IntPoint(m_savedScrollOffset), false, m_savedPageScaleFactor, scrollAndScaleAnimationDurationInSeconds);
2911 #else
2912     setPageScaleFactor(m_savedPageScaleFactor, WebPoint());
2913     mainFrame()->setScrollOffset(m_savedScrollOffset);
2914 #endif
2915
2916     resetSavedScrollAndScaleState();
2917 }
2918
2919 void WebViewImpl::resetSavedScrollAndScaleState()
2920 {
2921     m_savedPageScaleFactor = 0;
2922     m_savedScrollOffset = IntSize();
2923 }
2924
2925 WebSize WebViewImpl::fixedLayoutSize() const
2926 {
2927     if (!page())
2928         return WebSize();
2929
2930     Frame* frame = page()->mainFrame();
2931     if (!frame || !frame->view())
2932         return WebSize();
2933
2934     return frame->view()->fixedLayoutSize();
2935 }
2936
2937 void WebViewImpl::setFixedLayoutSize(const WebSize& layoutSize)
2938 {
2939     if (!page())
2940         return;
2941
2942     Frame* frame = page()->mainFrame();
2943     if (!frame || !frame->view())
2944         return;
2945
2946     frame->view()->setFixedLayoutSize(layoutSize);
2947 }
2948
2949 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
2950                                            const WebPoint& location)
2951 {
2952     HitTestResult result = hitTestResultForWindowPos(location);
2953     RefPtr<Node> node = result.innerNonSharedNode();
2954     if (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))
2955         return;
2956
2957     RefPtr<HTMLMediaElement> mediaElement =
2958         static_pointer_cast<HTMLMediaElement>(node);
2959     switch (action.type) {
2960     case WebMediaPlayerAction::Play:
2961         if (action.enable)
2962             mediaElement->play();
2963         else
2964             mediaElement->pause();
2965         break;
2966     case WebMediaPlayerAction::Mute:
2967         mediaElement->setMuted(action.enable);
2968         break;
2969     case WebMediaPlayerAction::Loop:
2970         mediaElement->setLoop(action.enable);
2971         break;
2972     case WebMediaPlayerAction::Controls:
2973         mediaElement->setControls(action.enable);
2974         break;
2975     default:
2976         ASSERT_NOT_REACHED();
2977     }
2978 }
2979
2980 void WebViewImpl::performPluginAction(const WebPluginAction& action,
2981                                       const WebPoint& location)
2982 {
2983     HitTestResult result = hitTestResultForWindowPos(location);
2984     RefPtr<Node> node = result.innerNonSharedNode();
2985     if (!node->hasTagName(HTMLNames::objectTag) && !node->hasTagName(HTMLNames::embedTag))
2986         return;
2987
2988     RenderObject* object = node->renderer();
2989     if (object && object->isWidget()) {
2990         Widget* widget = toRenderWidget(object)->widget();
2991         if (widget && widget->isPluginContainer()) {
2992             WebPluginContainerImpl* plugin = static_cast<WebPluginContainerImpl*>(widget);
2993             switch (action.type) {
2994             case WebPluginAction::Rotate90Clockwise:
2995                 plugin->plugin()->rotateView(WebPlugin::RotationType90Clockwise);
2996                 break;
2997             case WebPluginAction::Rotate90Counterclockwise:
2998                 plugin->plugin()->rotateView(WebPlugin::RotationType90Counterclockwise);
2999                 break;
3000             default:
3001                 ASSERT_NOT_REACHED();
3002             }
3003         }
3004     }
3005 }
3006
3007 void WebViewImpl::copyImageAt(const WebPoint& point)
3008 {
3009     if (!m_page)
3010         return;
3011
3012     HitTestResult result = hitTestResultForWindowPos(point);
3013
3014     if (result.absoluteImageURL().isEmpty()) {
3015         // There isn't actually an image at these coordinates.  Might be because
3016         // the window scrolled while the context menu was open or because the page
3017         // changed itself between when we thought there was an image here and when
3018         // we actually tried to retreive the image.
3019         //
3020         // FIXME: implement a cache of the most recent HitTestResult to avoid having
3021         //        to do two hit tests.
3022         return;
3023     }
3024
3025     m_page->mainFrame()->editor()->copyImage(result);
3026 }
3027
3028 void WebViewImpl::dragSourceEndedAt(
3029     const WebPoint& clientPoint,
3030     const WebPoint& screenPoint,
3031     WebDragOperation operation)
3032 {
3033     PlatformMouseEvent pme(clientPoint,
3034                            screenPoint,
3035                            LeftButton, PlatformEvent::MouseMoved, 0, false, false, false,
3036                            false, 0);
3037     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(pme,
3038         static_cast<DragOperation>(operation));
3039     m_dragScrollTimer->stop();
3040 }
3041
3042 void WebViewImpl::dragSourceMovedTo(
3043     const WebPoint& clientPoint,
3044     const WebPoint& screenPoint,
3045     WebDragOperation operation)
3046 {
3047     m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
3048 }
3049
3050 void WebViewImpl::dragSourceSystemDragEnded()
3051 {
3052     // It's possible for us to get this callback while not doing a drag if
3053     // it's from a previous page that got unloaded.
3054     if (m_doingDragAndDrop) {
3055         m_page->dragController()->dragEnded();
3056         m_doingDragAndDrop = false;
3057     }
3058 }
3059
3060 WebDragOperation WebViewImpl::dragTargetDragEnter(
3061     const WebDragData& webDragData,
3062     const WebPoint& clientPoint,
3063     const WebPoint& screenPoint,
3064     WebDragOperationsMask operationsAllowed,
3065     int keyModifiers)
3066 {
3067     ASSERT(!m_currentDragData);
3068
3069     m_currentDragData = webDragData;
3070     m_operationsAllowed = operationsAllowed;
3071
3072     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragEnter, keyModifiers);
3073 }
3074
3075 WebDragOperation WebViewImpl::dragTargetDragOver(
3076     const WebPoint& clientPoint,
3077     const WebPoint& screenPoint,
3078     WebDragOperationsMask operationsAllowed,
3079     int keyModifiers)
3080 {
3081     m_operationsAllowed = operationsAllowed;
3082
3083     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragOver, keyModifiers);
3084 }
3085
3086 void WebViewImpl::dragTargetDragLeave()
3087 {
3088     ASSERT(m_currentDragData);
3089
3090     DragData dragData(
3091         m_currentDragData.get(),
3092         IntPoint(),
3093         IntPoint(),
3094         static_cast<DragOperation>(m_operationsAllowed));
3095
3096     m_page->dragController()->dragExited(&dragData);
3097
3098     // FIXME: why is the drag scroll timer not stopped here?
3099
3100     m_dragOperation = WebDragOperationNone;
3101     m_currentDragData = 0;
3102 }
3103
3104 void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
3105                                  const WebPoint& screenPoint,
3106                                  int keyModifiers)
3107 {
3108     ASSERT(m_currentDragData);
3109
3110     // If this webview transitions from the "drop accepting" state to the "not
3111     // accepting" state, then our IPC message reply indicating that may be in-
3112     // flight, or else delayed by javascript processing in this webview.  If a
3113     // drop happens before our IPC reply has reached the browser process, then
3114     // the browser forwards the drop to this webview.  So only allow a drop to
3115     // proceed if our webview m_dragOperation state is not DragOperationNone.
3116
3117     if (m_dragOperation == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop.
3118         dragTargetDragLeave();
3119         return;
3120     }
3121
3122     m_currentDragData->setModifierKeyState(webInputEventKeyStateToPlatformEventKeyState(keyModifiers));
3123     DragData dragData(
3124         m_currentDragData.get(),
3125         clientPoint,
3126         screenPoint,
3127         static_cast<DragOperation>(m_operationsAllowed));
3128
3129     m_page->dragController()->performDrag(&dragData);
3130
3131     m_dragOperation = WebDragOperationNone;
3132     m_currentDragData = 0;
3133
3134     m_dragScrollTimer->stop();
3135 }
3136
3137 WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPoint, const WebPoint& screenPoint, DragAction dragAction, int keyModifiers)
3138 {
3139     ASSERT(m_currentDragData);
3140
3141     m_currentDragData->setModifierKeyState(webInputEventKeyStateToPlatformEventKeyState(keyModifiers));
3142     DragData dragData(
3143         m_currentDragData.get(),
3144         clientPoint,
3145         screenPoint,
3146         static_cast<DragOperation>(m_operationsAllowed));
3147
3148     DragSession dragSession;
3149     if (dragAction == DragEnter)
3150         dragSession = m_page->dragController()->dragEntered(&dragData);
3151     else
3152         dragSession = m_page->dragController()->dragUpdated(&dragData);
3153
3154     DragOperation dropEffect = dragSession.operation;
3155
3156     // Mask the drop effect operation against the drag source's allowed operations.
3157     if (!(dropEffect & dragData.draggingSourceOperationMask()))
3158         dropEffect = DragOperationNone;
3159
3160      m_dragOperation = static_cast<WebDragOperation>(dropEffect);
3161
3162     if (dragAction == DragOver)
3163         m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
3164     else
3165         m_dragScrollTimer->stop();
3166
3167     return m_dragOperation;
3168 }
3169
3170 void WebViewImpl::sendResizeEventAndRepaint()
3171 {
3172     if (mainFrameImpl()->frameView()) {
3173         // Enqueues the resize event.
3174         mainFrameImpl()->frame()->eventHandler()->sendResizeEvent();
3175     }
3176
3177     if (m_client) {
3178         if (isAcceleratedCompositingActive()) {
3179 #if USE(ACCELERATED_COMPOSITING)
3180             updateLayerTreeViewport();
3181 #endif
3182         } else {
3183             WebRect damagedRect(0, 0, m_size.width, m_size.height);
3184             m_client->didInvalidateRect(damagedRect);
3185         }
3186     }
3187 }
3188
3189 void WebViewImpl::configureAutoResizeMode()
3190 {
3191     if (!mainFrameImpl() || !mainFrameImpl()->frame() || !mainFrameImpl()->frame()->view())
3192         return;
3193
3194     mainFrameImpl()->frame()->view()->enableAutoSizeMode(m_shouldAutoResize, m_minAutoSize, m_maxAutoSize);
3195 }
3196
3197 unsigned long WebViewImpl::createUniqueIdentifierForRequest()
3198 {
3199     if (m_page)
3200         return m_page->progress()->createUniqueIdentifier();
3201     return 0;
3202 }
3203
3204 void WebViewImpl::inspectElementAt(const WebPoint& point)
3205 {
3206     if (!m_page)
3207         return;
3208
3209     if (point.x == -1 || point.y == -1)
3210         m_page->inspectorController()->inspect(0);
3211     else {
3212         HitTestResult result = hitTestResultForWindowPos(point);
3213
3214         if (!result.innerNonSharedNode())
3215             return;
3216
3217         m_page->inspectorController()->inspect(result.innerNonSharedNode());
3218     }
3219 }
3220
3221 WebString WebViewImpl::inspectorSettings() const
3222 {
3223     return m_inspectorSettings;
3224 }
3225
3226 void WebViewImpl::setInspectorSettings(const WebString& settings)
3227 {
3228     m_inspectorSettings = settings;
3229 }
3230
3231 bool WebViewImpl::inspectorSetting(const WebString& key, WebString* value) const
3232 {
3233     if (!m_inspectorSettingsMap->contains(key))
3234         return false;
3235     *value = m_inspectorSettingsMap->get(key);
3236     return true;
3237 }
3238
3239 void WebViewImpl::setInspectorSetting(const WebString& key,
3240                                       const WebString& value)
3241 {
3242     m_inspectorSettingsMap->set(key, value);
3243     client()->didUpdateInspectorSetting(key, value);
3244 }
3245
3246 WebDevToolsAgent* WebViewImpl::devToolsAgent()
3247 {
3248     return m_devToolsAgent.get();
3249 }
3250
3251 WebAccessibilityObject WebViewImpl::accessibilityObject()
3252 {
3253     if (!mainFrameImpl())
3254         return WebAccessibilityObject();
3255
3256     Document* document = mainFrameImpl()->frame()->document();
3257     return WebAccessibilityObject(
3258         document->axObjectCache()->getOrCreate(document->renderer()));
3259 }
3260
3261 void WebViewImpl::applyAutofillSuggestions(
3262     const WebNode& node,
3263     const WebVector<WebString>& names,
3264     const WebVector<WebString>& labels,
3265     const WebVector<WebString>& icons,
3266     const WebVector<int>& itemIDs,
3267     int separatorIndex)
3268 {
3269     ASSERT(names.size() == labels.size());
3270     ASSERT(names.size() == itemIDs.size());
3271
3272     if (names.isEmpty()) {
3273         hideAutofillPopup();
3274         return;
3275     }
3276
3277     RefPtr<Node> focusedNode = focusedWebCoreNode();
3278     // If the node for which we queried the Autofill suggestions is not the
3279     // focused node, then we have nothing to do.  FIXME: also check the
3280     // caret is at the end and that the text has not changed.
3281     if (!focusedNode || focusedNode != PassRefPtr<Node>(node)) {
3282         hideAutofillPopup();
3283         return;
3284     }
3285
3286     HTMLInputElement* inputElem = focusedNode->toInputElement();
3287     ASSERT(inputElem);
3288
3289     // The first time the Autofill popup is shown we'll create the client and
3290     // the popup.
3291     if (!m_autofillPopupClient)
3292         m_autofillPopupClient = adoptPtr(new AutofillPopupMenuClient);
3293
3294     m_autofillPopupClient->initialize(
3295         inputElem, names, labels, icons, itemIDs, separatorIndex);
3296
3297     if (!m_autofillPopup) {
3298         PopupContainerSettings popupSettings = autofillPopupSettings;
3299         popupSettings.deviceSupportsTouch = settingsImpl()->deviceSupportsTouch();
3300         m_autofillPopup = PopupContainer::create(m_autofillPopupClient.get(),
3301                                                  PopupContainer::Suggestion,
3302                                                  popupSettings);
3303     }
3304
3305     if (m_autofillPopupShowing) {
3306         refreshAutofillPopup();
3307     } else {
3308         m_autofillPopupShowing = true;
3309         m_autofillPopup->showInRect(focusedNode->getPixelSnappedRect(), focusedNode->ownerDocument()->view(), 0);
3310     }
3311 }
3312
3313 void WebViewImpl::hidePopups()
3314 {
3315     hideSelectPopup();
3316     hideAutofillPopup();
3317 #if ENABLE(PAGE_POPUP)
3318     if (m_pagePopup)
3319         closePagePopup(m_pagePopup.get());
3320 #endif
3321 }
3322
3323 void WebViewImpl::performCustomContextMenuAction(unsigned action)
3324 {
3325     if (!m_page)
3326         return;
3327     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
3328     if (!menu)
3329         return;
3330     ContextMenuItem* item = menu->itemWithAction(static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + action));
3331     if (item)
3332         m_page->contextMenuController()->contextMenuItemSelected(item);
3333     m_page->contextMenuController()->clearContextMenu();
3334 }
3335
3336 // WebView --------------------------------------------------------------------
3337
3338 void WebViewImpl::setIsTransparent(bool isTransparent)
3339 {
3340     // Set any existing frames to be transparent.
3341     Frame* frame = m_page->mainFrame();
3342     while (frame) {
3343         frame->view()->setTransparent(isTransparent);
3344         frame = frame->tree()->traverseNext();
3345     }
3346
3347     // Future frames check this to know whether to be transparent.
3348     m_isTransparent = isTransparent;
3349
3350     if (m_nonCompositedContentHost)
3351         m_nonCompositedContentHost->setOpaque(!isTransparent);
3352
3353     if (m_layerTreeView)
3354         m_layerTreeView->setHasTransparentBackground(isTransparent);
3355 }
3356
3357 bool WebViewImpl::isTransparent() const
3358 {
3359     return m_isTransparent;
3360 }
3361
3362 void WebViewImpl::setIsActive(bool active)
3363 {
3364     if (page() && page()->focusController())
3365         page()->focusController()->setActive(active);
3366 }
3367
3368 bool WebViewImpl::isActive() const
3369 {
3370     return (page() && page()->focusController()) ? page()->focusController()->isActive() : false;
3371 }
3372
3373 void WebViewImpl::setDomainRelaxationForbidden(bool forbidden, const WebString& scheme)
3374 {
3375     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme));
3376 }
3377
3378 void WebViewImpl::setScrollbarColors(unsigned inactiveColor,
3379                                      unsigned activeColor,
3380                                      unsigned trackColor) {
3381 #if OS(UNIX) && !OS(DARWIN) && !OS(ANDROID)
3382     PlatformThemeChromiumLinux::setScrollbarColors(inactiveColor, activeColor, trackColor);
3383 #endif
3384 }
3385
3386 void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor,
3387                                      unsigned activeForegroundColor,
3388                                      unsigned inactiveBackgroundColor,
3389                                      unsigned inactiveForegroundColor) {
3390 #if OS(UNIX) && !OS(DARWIN) && !OS(ANDROID)
3391     RenderThemeChromiumLinux::setSelectionColors(activeBackgroundColor,
3392                                                  activeForegroundColor,
3393                                                  inactiveBackgroundColor,
3394                                                  inactiveForegroundColor);
3395     theme()->platformColorsDidChange();
3396 #endif
3397 }
3398
3399 void WebView::addUserScript(const WebString& sourceCode,
3400                             const WebVector<WebString>& patternsIn,
3401                             WebView::UserScriptInjectAt injectAt,
3402                             WebView::UserContentInjectIn injectIn)
3403 {
3404     OwnPtr<Vector<String> > patterns = adoptPtr(new Vector<String>);
3405     for (size_t i = 0; i < patternsIn.size(); ++i)
3406         patterns->append(patternsIn[i]);
3407
3408     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
3409     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::createUninitializedWorld());
3410     pageGroup->addUserScriptToWorld(world.get(), sourceCode, WebURL(), patterns.release(), nullptr,
3411                                     static_cast<UserScriptInjectionTime>(injectAt),
3412                                     static_cast<UserContentInjectedFrames>(injectIn));
3413 }
3414
3415 void WebView::addUserStyleSheet(const WebString& sourceCode,
3416                                 const WebVector<WebString>& patternsIn,
3417                                 WebView::UserContentInjectIn injectIn,
3418                                 WebView::UserStyleInjectionTime injectionTime)
3419 {
3420     OwnPtr<Vector<String> > patterns = adoptPtr(new Vector<String>);
3421     for (size_t i = 0; i < patternsIn.size(); ++i)
3422         patterns->append(patternsIn[i]);
3423
3424     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
3425     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::createUninitializedWorld());
3426
3427     // FIXME: Current callers always want the level to be "author". It probably makes sense to let
3428     // callers specify this though, since in other cases the caller will probably want "user" level.
3429     //
3430     // FIXME: It would be nice to populate the URL correctly, instead of passing an empty URL.
3431     pageGroup->addUserStyleSheetToWorld(world.get(), sourceCode, WebURL(), patterns.release(), nullptr,
3432                                         static_cast<UserContentInjectedFrames>(injectIn),
3433                                         UserStyleAuthorLevel,
3434                                         static_cast<WebCore::UserStyleInjectionTime>(injectionTime));
3435 }
3436
3437 void WebView::removeAllUserContent()
3438 {
3439     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
3440     pageGroup->removeAllUserContent();
3441 }
3442
3443 void WebViewImpl::didCommitLoad(bool* isNewNavigation, bool isNavigationWithinPage)
3444 {
3445     if (isNewNavigation)
3446         *isNewNavigation = m_observedNewNavigation;
3447
3448 #ifndef NDEBUG
3449     ASSERT(!m_observedNewNavigation
3450         || m_page->mainFrame()->loader()->documentLoader() == m_newNavigationLoader);
3451     m_newNavigationLoader = 0;
3452 #endif
3453     m_observedNewNavigation = false;
3454     if (*isNewNavigation && !isNavigationWithinPage)
3455         m_pageScaleFactorIsSet = false;
3456
3457     // Make sure link highlight from previous page is cleared.
3458     m_linkHighlight.clear();
3459     m_gestureAnimation.clear();
3460     resetSavedScrollAndScaleState();
3461 }
3462
3463 void WebViewImpl::layoutUpdated(WebFrameImpl* webframe)
3464 {
3465     if (!m_client || webframe != mainFrameImpl())
3466         return;
3467
3468     if (m_shouldAutoResize && mainFrameImpl()->frame() && mainFrameImpl()->frame()->view()) {
3469         WebSize frameSize = mainFrameImpl()->frame()->view()->frameRect().size();
3470         if (frameSize != m_size) {
3471             m_size = frameSize;
3472             m_client->didAutoResize(m_size);
3473             sendResizeEventAndRepaint();
3474         }
3475     }
3476
3477     m_client->didUpdateLayout();
3478 }
3479
3480 void WebViewImpl::didChangeContentsSize()
3481 {
3482 #if ENABLE(VIEWPORT)
3483     if (!settings()->viewportEnabled())
3484         return;
3485
3486     bool didChangeScale = false;
3487     if (!isPageScaleFactorSet()) {
3488         // If the viewport tag failed to be processed earlier, we need
3489         // to recompute it now.
3490         ViewportArguments viewportArguments = mainFrameImpl()->frame()->document()->viewportArguments();
3491         m_page->chrome()->client()->dispatchViewportPropertiesDidChange(viewportArguments);
3492         didChangeScale = true;
3493     } else
3494         didChangeScale = computePageScaleFactorLimits();
3495
3496     if (!didChangeScale)
3497         return;
3498
3499     if (!mainFrameImpl())
3500         return;
3501
3502     FrameView* view = mainFrameImpl()->frameView();
3503     if (view && view->needsLayout())
3504         view->layout();
3505 #endif
3506 }
3507
3508 bool WebViewImpl::useExternalPopupMenus()
3509 {
3510     return shouldUseExternalPopupMenus;
3511 }
3512
3513 void WebViewImpl::setEmulatedTextZoomFactor(float textZoomFactor)
3514 {
3515     m_emulatedTextZoomFactor = textZoomFactor;
3516     Frame* frame = mainFrameImpl()->frame();
3517     if (frame)
3518         frame->setPageAndTextZoomFactors(frame->pageZoomFactor(), m_emulatedTextZoomFactor);
3519 }
3520
3521 bool WebViewImpl::navigationPolicyFromMouseEvent(unsigned short button,
3522                                                  bool ctrl, bool shift,
3523                                                  bool alt, bool meta,
3524                                                  WebNavigationPolicy* policy)
3525 {
3526 #if OS(DARWIN)
3527     const bool newTabModifier = (button == 1) || meta;
3528 #else
3529     const bool newTabModifier = (button == 1) || ctrl;
3530 #endif
3531     if (!newTabModifier && !shift && !alt)
3532       return false;
3533
3534     ASSERT(policy);
3535     if (newTabModifier) {
3536         if (shift)
3537           *policy = WebNavigationPolicyNewForegroundTab;
3538         else
3539           *policy = WebNavigationPolicyNewBackgroundTab;
3540     } else {
3541         if (shift)
3542           *policy = WebNavigationPolicyNewWindow;
3543         else
3544           *policy = WebNavigationPolicyDownload;
3545     }
3546     return true;
3547 }
3548
3549 void WebViewImpl::startDragging(Frame* frame,
3550                                 const WebDragData& dragData,
3551                                 WebDragOperationsMask mask,
3552                                 const WebImage& dragImage,
3553                                 const WebPoint& dragImageOffset)
3554 {
3555     if (!m_client)
3556         return;
3557     ASSERT(!m_doingDragAndDrop);
3558     m_doingDragAndDrop = true;
3559     m_client->startDragging(WebFrameImpl::fromFrame(frame), dragData, mask, dragImage, dragImageOffset);
3560 }
3561
3562 void WebViewImpl::observeNewNavigation()
3563 {
3564     m_observedNewNavigation = true;
3565 #ifndef NDEBUG
3566     m_newNavigationLoader = m_page->mainFrame()->loader()->documentLoader();
3567 #endif
3568 }
3569
3570 void WebViewImpl::setIgnoreInputEvents(bool newValue)
3571 {
3572     ASSERT(m_ignoreInputEvents != newValue);
3573     m_ignoreInputEvents = newValue;
3574 }
3575
3576 void WebViewImpl::addPageOverlay(WebPageOverlay* overlay, int zOrder)
3577 {
3578     if (!m_pageOverlays)
3579         m_pageOverlays = PageOverlayList::create(this);
3580
3581     m_pageOverlays->add(overlay, zOrder);
3582 }
3583
3584 void WebViewImpl::removePageOverlay(WebPageOverlay* overlay)
3585 {
3586     if (m_pageOverlays && m_pageOverlays->remove(overlay) && m_pageOverlays->empty())
3587         m_pageOverlays = nullptr;
3588 }
3589
3590 void WebViewImpl::setOverlayLayer(WebCore::GraphicsLayer* layer)
3591 {
3592     if (m_rootGraphicsLayer) {
3593         if (layer->parent() != m_rootGraphicsLayer)
3594             m_rootGraphicsLayer->addChild(layer);
3595     }
3596 }
3597
3598 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
3599 NotificationPresenterImpl* WebViewImpl::notificationPresenterImpl()
3600 {
3601     if (!m_notificationPresenter.isInitialized() && m_client)
3602         m_notificationPresenter.initialize(m_client->notificationPresenter());
3603     return &m_notificationPresenter;
3604 }
3605 #endif
3606
3607 void WebViewImpl::refreshAutofillPopup()
3608 {
3609     ASSERT(m_autofillPopupShowing);
3610
3611     // Hide the popup if it has become empty.
3612     if (!m_autofillPopupClient->listSize()) {
3613         hideAutofillPopup();
3614         return;
3615     }
3616
3617     WebRect newWidgetRect = m_autofillPopup->refresh(focusedWebCoreNode()->getPixelSnappedRect());
3618     // Let's resize the backing window if necessary.
3619     WebPopupMenuImpl* popupMenu = static_cast<WebPopupMenuImpl*>(m_autofillPopup->client());
3620     if (popupMenu && popupMenu->client()->windowRect() != newWidgetRect)
3621         popupMenu->client()->setWindowRect(newWidgetRect);
3622 }
3623
3624 Node* WebViewImpl::focusedWebCoreNode()
3625 {
3626     Frame* frame = m_page->focusController()->focusedFrame();
3627     if (!frame)
3628         return 0;
3629
3630     Document* document = frame->document();
3631     if (!document)
3632         return 0;
3633
3634     return document->focusedNode();
3635 }
3636
3637 HitTestResult WebViewImpl::hitTestResultForWindowPos(const IntPoint& pos)
3638 {
3639     IntPoint docPoint(m_page->mainFrame()->view()->windowToContents(pos));
3640     return m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(docPoint, false);
3641 }
3642
3643 void WebViewImpl::setTabsToLinks(bool enable)
3644 {
3645     m_tabsToLinks = enable;
3646 }
3647
3648 bool WebViewImpl::tabsToLinks() const
3649 {
3650     return m_tabsToLinks;
3651 }
3652
3653 #if USE(ACCELERATED_COMPOSITING)
3654 bool WebViewImpl::allowsAcceleratedCompositing()
3655 {
3656     return !m_compositorCreationFailed;
3657 }
3658
3659 void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
3660 {
3661     m_rootGraphicsLayer = layer;
3662     m_rootLayer = layer ? layer->platformLayer() : 0;
3663
3664     setIsAcceleratedCompositingActive(layer);
3665     if (m_nonCompositedContentHost) {
3666         GraphicsLayer* scrollLayer = 0;
3667         if (layer) {
3668             Document* document = page()->mainFrame()->document();
3669             RenderView* renderView = document->renderView();
3670             RenderLayerCompositor* compositor = renderView->compositor();
3671             scrollLayer = compositor->scrollLayer();
3672         }
3673         m_nonCompositedContentHost->setScrollLayer(scrollLayer);
3674     }
3675
3676     if (m_layerTreeView) {
3677         if (m_rootLayer)
3678             m_layerTreeView->setRootLayer(*m_rootLayer);
3679         else
3680             m_layerTreeView->clearRootLayer();
3681     }
3682
3683     IntRect damagedRect(0, 0, m_size.width, m_size.height);
3684     if (!m_isAcceleratedCompositingActive)
3685         m_client->didInvalidateRect(damagedRect);
3686 }
3687
3688 void WebViewImpl::scheduleCompositingLayerSync()
3689 {
3690     m_layerTreeView->setNeedsRedraw();
3691 }
3692
3693 void WebViewImpl::scrollRootLayerRect(const IntSize&, const IntRect&)
3694 {
3695     updateLayerTreeViewport();
3696 }
3697
3698 void WebViewImpl::invalidateRootLayerRect(const IntRect& rect)
3699 {
3700     ASSERT(m_layerTreeView);
3701
3702     if (!page())
3703         return;
3704
3705     FrameView* view = page()->mainFrame()->view();
3706     IntRect dirtyRect = view->windowToContents(rect);
3707     updateLayerTreeViewport();
3708     m_nonCompositedContentHost->invalidateRect(dirtyRect);
3709 }
3710
3711 NonCompositedContentHost* WebViewImpl::nonCompositedContentHost()
3712 {
3713     return m_nonCompositedContentHost.get();
3714 }
3715
3716 void WebViewImpl::setBackgroundColor(const WebCore::Color& color)
3717 {
3718     WebCore::Color documentBackgroundColor = color.isValid() ? color : WebCore::Color::white;
3719     WebColor webDocumentBackgroundColor = documentBackgroundColor.rgb();
3720     m_nonCompositedContentHost->setBackgroundColor(documentBackgroundColor);
3721     m_layerTreeView->setBackgroundColor(webDocumentBackgroundColor);
3722 }
3723
3724 WebCore::GraphicsLayer* WebViewImpl::rootGraphicsLayer()
3725 {
3726     return m_rootGraphicsLayer;
3727 }
3728
3729 #if ENABLE(REQUEST_ANIMATION_FRAME)
3730 void WebViewImpl::scheduleAnimation()
3731 {
3732     if (isAcceleratedCompositingActive()) {
3733         if (Platform::current()->compositorSupport()->isThreadingEnabled()) {
3734             ASSERT(m_layerTreeView);
3735             m_layerTreeView->setNeedsAnimate();
3736         } else
3737             m_client->scheduleAnimation();
3738     } else
3739             m_client->scheduleAnimation();
3740 }
3741 #endif
3742
3743 void WebViewImpl::paintRootLayer(GraphicsContext& context, const IntRect& contentRect)
3744 {
3745     double paintStart = currentTime();
3746     if (!page())
3747         return;
3748     FrameView* view = page()->mainFrame()->view();
3749     view->paintContents(&context, contentRect);
3750     double paintEnd = currentTime();
3751     double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart);
3752     WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelRootPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
3753     WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelRootPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
3754
3755     setBackgroundColor(view->documentBackgroundColor());
3756 }
3757
3758 void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
3759 {
3760     WebKit::Platform::current()->histogramEnumeration("GPU.setIsAcceleratedCompositingActive", active * 2 + m_isAcceleratedCompositingActive, 4);
3761
3762     if (m_isAcceleratedCompositingActive == active)
3763         return;
3764
3765     if (!active) {
3766         m_isAcceleratedCompositingActive = false;
3767         // We need to finish all GL rendering before sending didDeactivateCompositor() to prevent
3768         // flickering when compositing turns off.
3769         if (m_layerTreeView)
3770             m_layerTreeView->finishAllRendering();
3771         m_client->didDeactivateCompositor();
3772     } else if (m_layerTreeView) {
3773         m_isAcceleratedCompositingActive = true;
3774         updateLayerTreeViewport();
3775
3776         m_client->didActivateCompositor(m_layerTreeView->compositorIdentifier());
3777     } else {
3778         TRACE_EVENT0("webkit", "WebViewImpl::setIsAcceleratedCompositingActive(true)");
3779
3780         WebLayerTreeView::Settings layerTreeViewSettings;
3781         layerTreeViewSettings.acceleratePainting = page()->settings()->acceleratedDrawingEnabled();
3782         layerTreeViewSettings.showFPSCounter = settingsImpl()->showFPSCounter();
3783         layerTreeViewSettings.showPlatformLayerTree = settingsImpl()->showPlatformLayerTree();
3784         layerTreeViewSettings.showPaintRects = settingsImpl()->showPaintRects();
3785         layerTreeViewSettings.renderVSyncEnabled = settingsImpl()->renderVSyncEnabled();
3786
3787         layerTreeViewSettings.defaultTileSize = settingsImpl()->defaultTileSize();
3788         layerTreeViewSettings.maxUntiledLayerSize = settingsImpl()->maxUntiledLayerSize();
3789
3790         m_nonCompositedContentHost = NonCompositedContentHost::create(this);
3791         m_nonCompositedContentHost->setShowDebugBorders(page()->settings()->showDebugBorders());
3792         m_nonCompositedContentHost->setOpaque(!isTransparent());
3793
3794         m_layerTreeView = adoptPtr(WebLayerTreeView::create(this, *m_rootLayer, layerTreeViewSettings));
3795         if (m_layerTreeView) {
3796             if (m_webSettings->applyDefaultDeviceScaleFactorInCompositor() && page()->deviceScaleFactor() != 1) {
3797                 ASSERT(page()->deviceScaleFactor());
3798
3799                 m_deviceScaleInCompositor = page()->deviceScaleFactor();
3800                 setDeviceScaleFactor(m_deviceScaleInCompositor);
3801             }
3802
3803             bool visible = page()->visibilityState() == PageVisibilityStateVisible;
3804             m_layerTreeView->setVisible(visible);
3805             m_layerTreeView->setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor);
3806             if (m_compositorSurfaceReady)
3807                 m_layerTreeView->setSurfaceReady();
3808             m_layerTreeView->setHasTransparentBackground(isTransparent());
3809             updateLayerTreeViewport();
3810             m_client->didActivateCompositor(m_layerTreeView->compositorIdentifier());
3811             m_isAcceleratedCompositingActive = true;
3812             m_compositorCreationFailed = false;
3813             if (m_pageOverlays)
3814                 m_pageOverlays->update();
3815
3816             // Only allocate the font atlas if we have reason to use the heads-up display.
3817             if (layerTreeViewSettings.showFPSCounter || layerTreeViewSettings.showPlatformLayerTree) {
3818                 TRACE_EVENT0("cc", "WebViewImpl::setIsAcceleratedCompositingActive(true) initialize font atlas");
3819                 WebRect asciiToRectTable[128];
3820                 int fontHeight;
3821                 SkBitmap bitmap = WebCore::CompositorHUDFontAtlas::generateFontAtlas(asciiToRectTable, fontHeight);
3822                 m_layerTreeView->setFontAtlas(bitmap, asciiToRectTable, fontHeight);
3823             }
3824         } else {
3825             m_nonCompositedContentHost.clear();
3826             m_isAcceleratedCompositingActive = false;
3827             m_client->didDeactivateCompositor();
3828             m_compositorCreationFailed = true;
3829         }
3830     }
3831     if (page())
3832         page()->mainFrame()->view()->setClipsRepaints(!m_isAcceleratedCompositingActive);
3833 }
3834
3835 #endif
3836
3837 namespace {
3838
3839 // Adapts a pure WebGraphicsContext3D into a WebCompositorOutputSurface until
3840 // downstream code can be updated to produce output surfaces directly.
3841 class WebGraphicsContextToOutputSurfaceAdapter : public WebCompositorOutputSurface {
3842 public:
3843     explicit WebGraphicsContextToOutputSurfaceAdapter(PassOwnPtr<WebGraphicsContext3D> context)
3844         : m_context3D(context)
3845         , m_client(0)
3846     {
3847     }
3848
3849     virtual bool bindToClient(WebCompositorOutputSurfaceClient* client) OVERRIDE
3850     {
3851         ASSERT(client);
3852         if (!m_context3D->makeContextCurrent())
3853             return false;
3854         m_client = client;
3855         return true;
3856     }
3857
3858     virtual const Capabilities& capabilities() const OVERRIDE
3859     {
3860         return m_capabilities;
3861     }
3862
3863     virtual WebGraphicsContext3D* context3D() const OVERRIDE
3864     {
3865         return m_context3D.get();
3866     }
3867
3868     virtual void sendFrameToParentCompositor(const WebCompositorFrame&) OVERRIDE
3869     {
3870     }
3871
3872 private:
3873     OwnPtr<WebGraphicsContext3D> m_context3D;
3874     Capabilities m_capabilities;
3875     WebCompositorOutputSurfaceClient* m_client;
3876 };
3877
3878 } // namespace
3879
3880 WebGraphicsContext3D* WebViewImpl::createContext3D()
3881 {
3882     // Temporarily, if the output surface can't be created, create a WebGraphicsContext3D
3883     // directly. This allows bootstrapping the output surface system while downstream
3884     // users of the API still use the old approach.
3885     WebKit::WebGraphicsContext3D::Attributes attributes;
3886     attributes.antialias = false;
3887     attributes.shareResources = true;
3888     return m_client->createGraphicsContext3D(attributes);
3889 }
3890
3891 WebCompositorOutputSurface* WebViewImpl::createOutputSurface()
3892 {
3893     return m_client->createOutputSurface();
3894 }
3895
3896 void WebViewImpl::applyScrollAndScale(const WebSize& scrollDelta, float pageScaleDelta)
3897 {
3898     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
3899         return;
3900
3901     if (pageScaleDelta == 1) {
3902         TRACE_EVENT_INSTANT2("webkit", "WebViewImpl::applyScrollAndScale::scrollBy", "x", scrollDelta.width, "y", scrollDelta.height);
3903         mainFrameImpl()->frameView()->scrollBy(scrollDelta);
3904     } else {
3905         // The page scale changed, so apply a scale and scroll in a single
3906         // operation. The old scroll offset (and passed-in delta) are
3907         // in the old coordinate space, so we first need to multiply them
3908         // by the page scale delta.
3909         WebSize scrollOffset = mainFrame()->scrollOffset();
3910         scrollOffset.width += scrollDelta.width;
3911         scrollOffset.height += scrollDelta.height;
3912         WebPoint scaledScrollOffset(scrollOffset.width * pageScaleDelta,
3913                                     scrollOffset.height * pageScaleDelta);
3914         setPageScaleFactor(pageScaleFactor() * pageScaleDelta, scaledScrollOffset);
3915     }
3916 }
3917
3918 void WebViewImpl::willCommit()
3919 {
3920     InspectorInstrumentation::willComposite(m_page.get());
3921 }
3922
3923 void WebViewImpl::didCommit()
3924 {
3925     if (m_client)
3926         m_client->didBecomeReadyForAdditionalInput();
3927 }
3928
3929 void WebViewImpl::didCommitAndDrawFrame()
3930 {
3931     if (m_client)
3932         m_client->didCommitAndDrawCompositorFrame();
3933 }
3934
3935 void WebViewImpl::didCompleteSwapBuffers()
3936 {
3937     if (m_client)
3938         m_client->didCompleteSwapBuffers();
3939 }
3940
3941 void WebViewImpl::didRebindGraphicsContext(bool success)
3942 {
3943     didRecreateOutputSurface(success);
3944 }
3945
3946 void WebViewImpl::didRecreateOutputSurface(bool success)
3947 {
3948     // Switch back to software rendering mode, if necessary
3949     if (!success) {
3950         ASSERT(m_isAcceleratedCompositingActive);
3951         setIsAcceleratedCompositingActive(false);
3952         m_compositorCreationFailed = true;
3953         m_client->didInvalidateRect(IntRect(0, 0, m_size.width, m_size.height));
3954
3955         // Force a style recalc to remove all the composited layers.
3956         m_page->mainFrame()->document()->scheduleForcedStyleRecalc();
3957         return;
3958     }
3959
3960     if (m_pageOverlays)
3961         m_pageOverlays->update();
3962 }
3963
3964 void WebViewImpl::scheduleComposite()
3965 {
3966     ASSERT(!Platform::current()->compositorSupport()->isThreadingEnabled());
3967     m_client->scheduleComposite();
3968 }
3969
3970 void WebViewImpl::updateLayerTreeViewport()
3971 {
3972     if (!page() || !m_nonCompositedContentHost || !m_layerTreeView)
3973         return;
3974
3975     FrameView* view = page()->mainFrame()->view();
3976     IntRect visibleRect = view->visibleContentRect(true /* include scrollbars */);
3977     IntPoint scroll(view->scrollX(), view->scrollY());
3978
3979     m_nonCompositedContentHost->setViewport(visibleRect.size(), view->contentsSize(), scroll, view->scrollOrigin());
3980
3981     IntSize layoutViewportSize = size();
3982     IntSize deviceViewportSize = size();
3983
3984     // This part of the deviceScale will be used to scale the contents of
3985     // the NCCH's GraphicsLayer.
3986     deviceViewportSize.scale(m_deviceScaleInCompositor);
3987     m_layerTreeView->setViewportSize(layoutViewportSize, deviceViewportSize);
3988     m_layerTreeView->setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor);
3989 }
3990
3991 WebGraphicsContext3D* WebViewImpl::sharedGraphicsContext3D()
3992 {
3993     if (!m_page->settings()->acceleratedCompositingEnabled() || !allowsAcceleratedCompositing())
3994         return 0;
3995
3996     return GraphicsContext3DPrivate::extractWebGraphicsContext3D(SharedGraphicsContext3D::get().get());
3997 }
3998
3999 void WebViewImpl::selectAutofillSuggestionAtIndex(unsigned listIndex)
4000 {
4001     if (m_autofillPopupClient && listIndex < m_autofillPopupClient->getSuggestionsCount())
4002         m_autofillPopupClient->valueChanged(listIndex);
4003 }
4004
4005 bool WebViewImpl::detectContentOnTouch(const WebPoint& position, WebInputEvent::Type touchType)
4006 {
4007     ASSERT(touchType == WebInputEvent::GestureTap
4008            || touchType == WebInputEvent::GestureTwoFingerTap
4009            || touchType == WebInputEvent::GestureLongPress);
4010
4011     HitTestResult touchHit = hitTestResultForWindowPos(position);
4012
4013     if (touchHit.isContentEditable())
4014         return false;
4015
4016     Node* node = touchHit.innerNode();
4017     if (!node || !node->isTextNode())
4018         return false;
4019
4020     // Ignore when tapping on links or nodes listening to click events, unless the click event is on the
4021     // body element, in which case it's unlikely that the original node itself was intended to be clickable.
4022     for (; node && !node->hasTagName(HTMLNames::bodyTag); node = node->parentNode()) {
4023         if (node->isLink() || (touchType == WebInputEvent::GestureTap
4024                 && (node->willRespondToTouchEvents() || node->willRespondToMouseClickEvents()))) {
4025             return false;
4026         }
4027     }
4028
4029     WebContentDetectionResult content = m_client->detectContentAround(touchHit);
4030     if (!content.isValid())
4031         return false;
4032
4033     if (touchType != WebInputEvent::GestureTap) {
4034         // Select the detected content as a block.
4035         focusedFrame()->selectRange(content.range());
4036         return true;
4037     }
4038
4039     m_client->scheduleContentIntent(content.intent());
4040     return true;
4041 }
4042
4043 void WebViewImpl::setVisibilityState(WebPageVisibilityState visibilityState,
4044                                      bool isInitialState) {
4045     if (!page())
4046         return;
4047
4048 #if ENABLE(PAGE_VISIBILITY_API)
4049     ASSERT(visibilityState == WebPageVisibilityStateVisible
4050            || visibilityState == WebPageVisibilityStateHidden
4051            || visibilityState == WebPageVisibilityStatePrerender
4052            || visibilityState == WebPageVisibilityStatePreview);
4053     m_page->setVisibilityState(static_cast<PageVisibilityState>(static_cast<int>(visibilityState)), isInitialState);
4054 #endif
4055
4056 #if USE(ACCELERATED_COMPOSITING)
4057     if (m_layerTreeView) {
4058         bool visible = visibilityState == WebPageVisibilityStateVisible;
4059         m_layerTreeView->setVisible(visible);
4060     }
4061 #endif
4062 }
4063
4064 #if ENABLE(POINTER_LOCK)
4065 bool WebViewImpl::requestPointerLock()
4066 {
4067     return m_client && m_client->requestPointerLock();
4068 }
4069
4070 void WebViewImpl::requestPointerUnlock()
4071 {
4072     if (m_client)
4073         m_client->requestPointerUnlock();
4074 }
4075
4076 bool WebViewImpl::isPointerLocked()
4077 {
4078     return m_client && m_client->isPointerLocked();
4079 }
4080
4081 void WebViewImpl::pointerLockMouseEvent(const WebInputEvent& event)
4082 {
4083     AtomicString eventType;
4084     switch (event.type) {
4085     case WebInputEvent::MouseDown:
4086         eventType = eventNames().mousedownEvent;
4087         break;
4088     case WebInputEvent::MouseUp:
4089         eventType = eventNames().mouseupEvent;
4090         break;
4091     case WebInputEvent::MouseMove:
4092         eventType = eventNames().mousemoveEvent;
4093         break;
4094     default:
4095         ASSERT_NOT_REACHED();
4096     }
4097
4098     const WebMouseEvent& mouseEvent = static_cast<const WebMouseEvent&>(event);
4099
4100     if (page())
4101         page()->pointerLockController()->dispatchLockedMouseEvent(
4102             PlatformMouseEventBuilder(mainFrameImpl()->frameView(), mouseEvent),
4103             eventType);
4104 }
4105 #endif
4106
4107 } // namespace WebKit