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