[chromium] Change WebLayer from a concrete type to a pure virtual interface
[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_rootLayer(0)
413     , m_rootGraphicsLayer(0)
414     , m_isAcceleratedCompositingActive(false)
415     , m_compositorCreationFailed(false)
416     , m_recreatingGraphicsContext(false)
417     , m_compositorSurfaceReady(false)
418     , m_deviceScaleInCompositor(1)
419 #endif
420 #if ENABLE(INPUT_SPEECH)
421     , m_speechInputClient(SpeechInputClientImpl::create(client))
422 #endif
423 #if ENABLE(SCRIPTED_SPEECH)
424     , m_speechRecognitionClient(SpeechRecognitionClientProxy::create(client ? client->speechRecognizer() : 0))
425 #endif
426     , m_deviceOrientationClientProxy(adoptPtr(new DeviceOrientationClientProxy(client ? client->deviceOrientationClient() : 0)))
427     , m_geolocationClientProxy(adoptPtr(new GeolocationClientProxy(client ? client->geolocationClient() : 0)))
428 #if ENABLE(BATTERY_STATUS)
429     , m_batteryClient(adoptPtr(new BatteryClientImpl(client ? client->batteryStatusClient() : 0)))
430 #endif
431     , m_emulatedTextZoomFactor(1)
432 #if ENABLE(MEDIA_STREAM)
433     , m_userMediaClientImpl(this)
434 #endif
435 #if ENABLE(REGISTER_PROTOCOL_HANDLER)
436     , m_registerProtocolHandlerClient(RegisterProtocolHandlerClientImpl::create(this))
437 #endif
438     , m_flingModifier(0)
439 {
440     // WebKit/win/WebView.cpp does the same thing, except they call the
441     // KJS specific wrapper around this method. We need to have threading
442     // initialized because CollatorICU requires it.
443     WTF::initializeThreading();
444     WTF::initializeMainThread();
445
446     Page::PageClients pageClients;
447     pageClients.chromeClient = &m_chromeClientImpl;
448     pageClients.contextMenuClient = &m_contextMenuClientImpl;
449     pageClients.editorClient = &m_editorClientImpl;
450     pageClients.dragClient = &m_dragClientImpl;
451     pageClients.inspectorClient = &m_inspectorClientImpl;
452     pageClients.backForwardClient = BackForwardListChromium::create(this);
453
454     m_page = adoptPtr(new Page(pageClients));
455 #if ENABLE(MEDIA_STREAM)
456     provideUserMediaTo(m_page.get(), &m_userMediaClientImpl);
457 #endif
458 #if ENABLE(INPUT_SPEECH)
459     provideSpeechInputTo(m_page.get(), m_speechInputClient.get());
460 #endif
461 #if ENABLE(SCRIPTED_SPEECH)
462     provideSpeechRecognitionTo(m_page.get(), m_speechRecognitionClient.get());
463 #endif
464 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
465     provideNotification(m_page.get(), notificationPresenterImpl());
466 #endif
467 #if ENABLE(REGISTER_PROTOCOL_HANDLER)
468     provideRegisterProtocolHandlerTo(m_page.get(), m_registerProtocolHandlerClient.get());
469 #endif
470
471     provideContextFeaturesTo(m_page.get(), m_featureSwitchClient.get());
472     provideDeviceOrientationTo(m_page.get(), m_deviceOrientationClientProxy.get());
473     provideGeolocationTo(m_page.get(), m_geolocationClientProxy.get());
474     m_geolocationClientProxy->setController(GeolocationController::from(m_page.get()));
475
476 #if ENABLE(BATTERY_STATUS)
477     provideBatteryTo(m_page.get(), m_batteryClient.get());
478     m_batteryClient->setController(BatteryController::from(m_page.get()));
479 #endif
480
481     m_page->setGroupName(pageGroupName);
482
483 #if ENABLE(PAGE_VISIBILITY_API)
484     if (m_client)
485         setVisibilityState(m_client->visibilityState(), true);
486 #endif
487
488     m_inspectorSettingsMap = adoptPtr(new SettingsMap);
489 }
490
491 WebViewImpl::~WebViewImpl()
492 {
493     ASSERT(!m_page);
494 }
495
496 RenderTheme* WebViewImpl::theme() const
497 {
498     return m_page ? m_page->theme() : RenderTheme::defaultTheme().get();
499 }
500
501 WebFrameImpl* WebViewImpl::mainFrameImpl()
502 {
503     return m_page ? WebFrameImpl::fromFrame(m_page->mainFrame()) : 0;
504 }
505
506 bool WebViewImpl::tabKeyCyclesThroughElements() const
507 {
508     ASSERT(m_page);
509     return m_page->tabKeyCyclesThroughElements();
510 }
511
512 void WebViewImpl::setTabKeyCyclesThroughElements(bool value)
513 {
514     if (m_page)
515         m_page->setTabKeyCyclesThroughElements(value);
516 }
517
518 void WebViewImpl::handleMouseLeave(Frame& mainFrame, const WebMouseEvent& event)
519 {
520     m_client->setMouseOverURL(WebURL());
521     PageWidgetEventHandler::handleMouseLeave(mainFrame, event);
522 }
523
524 void WebViewImpl::handleMouseDown(Frame& mainFrame, const WebMouseEvent& event)
525 {
526     // If there is a popup open, close it as the user is clicking on the page (outside of the
527     // popup). We also save it so we can prevent a click on an element from immediately
528     // reopening the same popup.
529     RefPtr<WebCore::PopupContainer> selectPopup;
530 #if ENABLE(PAGE_POPUP)
531     RefPtr<WebPagePopupImpl> pagePopup;
532 #endif
533     if (event.button == WebMouseEvent::ButtonLeft) {
534         selectPopup = m_selectPopup;
535 #if ENABLE(PAGE_POPUP)
536         pagePopup = m_pagePopup;
537 #endif
538         hidePopups();
539         ASSERT(!m_selectPopup);
540 #if ENABLE(PAGE_POPUP)
541         ASSERT(!m_pagePopup);
542 #endif
543     }
544
545     m_lastMouseDownPoint = WebPoint(event.x, event.y);
546
547     if (event.button == WebMouseEvent::ButtonLeft) {
548         IntPoint point(event.x, event.y);
549         point = m_page->mainFrame()->view()->windowToContents(point);
550         HitTestResult result(m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false));
551         Node* hitNode = result.innerNonSharedNode();
552
553         // Take capture on a mouse down on a plugin so we can send it mouse events.
554         if (hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject())
555             m_mouseCaptureNode = hitNode;
556     }
557
558     PageWidgetEventHandler::handleMouseDown(mainFrame, event);
559
560     if (m_selectPopup && m_selectPopup == selectPopup) {
561         // That click triggered a select popup which is the same as the one that
562         // was showing before the click.  It means the user clicked the select
563         // while the popup was showing, and as a result we first closed then
564         // immediately reopened the select popup.  It needs to be closed.
565         hideSelectPopup();
566     }
567
568 #if ENABLE(PAGE_POPUP)
569     if (m_pagePopup && pagePopup && m_pagePopup->hasSamePopupClient(pagePopup.get())) {
570         // That click triggered a page popup that is the same as the one we just closed.
571         // It needs to be closed.
572         closePagePopup(m_pagePopup.get());
573     }
574 #endif
575
576     // Dispatch the contextmenu event regardless of if the click was swallowed.
577     // On Windows, we handle it on mouse up, not down.
578 #if OS(DARWIN)
579     if (event.button == WebMouseEvent::ButtonRight
580         || (event.button == WebMouseEvent::ButtonLeft
581             && event.modifiers & WebMouseEvent::ControlKey))
582         mouseContextMenu(event);
583 #elif OS(UNIX) || OS(ANDROID)
584     if (event.button == WebMouseEvent::ButtonRight)
585         mouseContextMenu(event);
586 #endif
587 }
588
589 void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
590 {
591     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
592         return;
593
594     m_page->contextMenuController()->clearContextMenu();
595
596     PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), event);
597
598     // Find the right target frame. See issue 1186900.
599     HitTestResult result = hitTestResultForWindowPos(pme.position());
600     Frame* targetFrame;
601     if (result.innerNonSharedNode())
602         targetFrame = result.innerNonSharedNode()->document()->frame();
603     else
604         targetFrame = m_page->focusController()->focusedOrMainFrame();
605
606 #if OS(WINDOWS)
607     targetFrame->view()->setCursor(pointerCursor());
608 #endif
609
610     m_contextMenuAllowed = true;
611     targetFrame->eventHandler()->sendContextMenuEvent(pme);
612     m_contextMenuAllowed = false;
613     // Actually showing the context menu is handled by the ContextMenuClient
614     // implementation...
615 }
616
617 void WebViewImpl::handleMouseUp(Frame& mainFrame, const WebMouseEvent& event)
618 {
619 #if OS(UNIX) && !OS(DARWIN)
620     // If the event was a middle click, attempt to copy text into the focused
621     // frame. We execute this before we let the page have a go at the event
622     // because the page may change what is focused during in its event handler.
623     //
624     // This code is in the mouse up handler. There is some debate about putting
625     // this here, as opposed to the mouse down handler.
626     //   xterm: pastes on up.
627     //   GTK: pastes on down.
628     //   Firefox: pastes on up.
629     //   Midori: couldn't paste at all with 0.1.2
630     //
631     // There is something of a webcompat angle to this well, as highlighted by
632     // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
633     // down then the text is pasted just before the onclick handler runs and
634     // clears the text box. So it's important this happens after the
635     // handleMouseReleaseEvent() earlier in this function
636     if (event.button == WebMouseEvent::ButtonMiddle) {
637         Frame* focused = focusedWebCoreFrame();
638         FrameView* view = m_page->mainFrame()->view();
639         IntPoint clickPoint(m_lastMouseDownPoint.x, m_lastMouseDownPoint.y);
640         IntPoint contentPoint = view->windowToContents(clickPoint);
641         HitTestResult hitTestResult = focused->eventHandler()->hitTestResultAtPoint(contentPoint, false, false, ShouldHitTestScrollbars);
642         // We don't want to send a paste when middle clicking a scroll bar or a
643         // link (which will navigate later in the code).  The main scrollbars
644         // have to be handled separately.
645         if (!hitTestResult.scrollbar() && !hitTestResult.isLiveLink() && focused && !view->scrollbarAtPoint(clickPoint)) {
646             Editor* editor = focused->editor();
647             Pasteboard* pasteboard = Pasteboard::generalPasteboard();
648             bool oldSelectionMode = pasteboard->isSelectionMode();
649             pasteboard->setSelectionMode(true);
650             editor->command(AtomicString("Paste")).execute();
651             pasteboard->setSelectionMode(oldSelectionMode);
652         }
653     }
654 #endif
655
656     PageWidgetEventHandler::handleMouseUp(mainFrame, event);
657
658 #if OS(WINDOWS)
659     // Dispatch the contextmenu event regardless of if the click was swallowed.
660     // On Mac/Linux, we handle it on mouse down, not up.
661     if (event.button == WebMouseEvent::ButtonRight)
662         mouseContextMenu(event);
663 #endif
664 }
665
666 void WebViewImpl::scrollBy(const WebCore::IntPoint& delta)
667 {
668     WebMouseWheelEvent syntheticWheel;
669     const float tickDivisor = WebCore::WheelEvent::tickMultiplier;
670
671     syntheticWheel.deltaX = delta.x();
672     syntheticWheel.deltaY = delta.y();
673     syntheticWheel.wheelTicksX = delta.x() / tickDivisor;
674     syntheticWheel.wheelTicksY = delta.y() / tickDivisor;
675     syntheticWheel.hasPreciseScrollingDeltas = true;
676     syntheticWheel.x = m_lastWheelPosition.x;
677     syntheticWheel.y = m_lastWheelPosition.y;
678     syntheticWheel.globalX = m_lastWheelGlobalPosition.x;
679     syntheticWheel.globalY = m_lastWheelGlobalPosition.y;
680     syntheticWheel.modifiers = m_flingModifier;
681
682     if (m_page && m_page->mainFrame() && m_page->mainFrame()->view())
683         handleMouseWheel(*m_page->mainFrame(), syntheticWheel);
684 }
685
686 #if ENABLE(GESTURE_EVENTS)
687 bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event)
688 {
689     switch (event.type) {
690     case WebInputEvent::GestureFlingStart: {
691         m_lastWheelPosition = WebPoint(event.x, event.y);
692         m_lastWheelGlobalPosition = WebPoint(event.globalX, event.globalY);
693         m_flingModifier = event.modifiers;
694         // FIXME: Make the curve parametrizable from the browser.
695         m_gestureAnimation = ActivePlatformGestureAnimation::create(TouchpadFlingPlatformGestureCurve::create(FloatPoint(event.deltaX, event.deltaY)), this);
696         scheduleAnimation();
697         return true;
698     }
699     case WebInputEvent::GestureFlingCancel:
700         if (m_gestureAnimation) {
701             m_gestureAnimation.clear();
702             return true;
703         }
704         return false;
705     case WebInputEvent::GestureTap: {
706         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
707         RefPtr<WebCore::PopupContainer> selectPopup;
708         selectPopup = m_selectPopup;
709         hideSelectPopup();
710         ASSERT(!m_selectPopup);
711         bool gestureHandled = mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
712         if (m_selectPopup && m_selectPopup == selectPopup) {
713             // That tap triggered a select popup which is the same as the one that
714             // was showing before the tap. It means the user tapped the select
715             // while the popup was showing, and as a result we first closed then
716             // immediately reopened the select popup. It needs to be closed.
717             hideSelectPopup();
718         }
719         return gestureHandled;
720     }
721     case WebInputEvent::GestureTwoFingerTap:
722     case WebInputEvent::GestureLongPress: {
723         if (!mainFrameImpl() || !mainFrameImpl()->frameView())
724             return false;
725
726         m_page->contextMenuController()->clearContextMenu();
727         m_contextMenuAllowed = true;
728         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
729         bool handled = mainFrameImpl()->frame()->eventHandler()->sendContextMenuEventForGesture(platformEvent);
730         m_contextMenuAllowed = false;
731         return handled;
732     }
733     case WebInputEvent::GestureTapDown: {
734         // Queue a highlight animation, then hand off to regular handler.
735 #if OS(LINUX)
736         enableTouchHighlight(IntPoint(event.x, event.y));
737 #endif
738         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
739         return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
740     }
741     case WebInputEvent::GestureScrollBegin:
742     case WebInputEvent::GestureScrollEnd:
743     case WebInputEvent::GestureScrollUpdate:
744     case WebInputEvent::GestureDoubleTap:
745     case WebInputEvent::GesturePinchBegin:
746     case WebInputEvent::GesturePinchEnd:
747     case WebInputEvent::GesturePinchUpdate: {
748         PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
749         return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
750     }
751     default:
752         ASSERT_NOT_REACHED();
753     }
754     return false;
755 }
756
757 void WebViewImpl::transferActiveWheelFlingAnimation(const WebActiveWheelFlingParameters& parameters)
758 {
759     TRACE_EVENT0("webkit", "WebViewImpl::transferActiveWheelFlingAnimation");
760     ASSERT(!m_gestureAnimation);
761     m_lastWheelPosition = parameters.point;
762     m_lastWheelGlobalPosition = parameters.globalPoint;
763     m_flingModifier = parameters.modifiers;
764     OwnPtr<PlatformGestureCurve> curve = TouchpadFlingPlatformGestureCurve::create(parameters.delta, IntPoint(parameters.cumulativeScroll));
765     m_gestureAnimation = ActivePlatformGestureAnimation::create(curve.release(), this, parameters.startTime);
766     scheduleAnimation();
767 }
768
769 void WebViewImpl::renderingStats(WebRenderingStats& stats) const
770 {
771     if (!m_layerTreeView.isNull())
772         m_layerTreeView.renderingStats(stats);
773 }
774
775 void WebViewImpl::startPageScaleAnimation(const IntPoint& targetPosition, bool useAnchor, float newScale, double durationInSeconds)
776 {
777     if (m_layerTreeView.isNull())
778         return;
779
780     IntPoint clampedPoint = targetPosition;
781     if (!useAnchor)
782         clampedPoint = clampOffsetAtScale(targetPosition, newScale);
783
784     if (!durationInSeconds && !useAnchor) {
785         setPageScaleFactor(newScale, clampedPoint);
786         return;
787     }
788
789     m_layerTreeView.startPageScaleAnimation(targetPosition, useAnchor, newScale, durationInSeconds);
790 }
791 #endif
792
793 WebViewBenchmarkSupport* WebViewImpl::benchmarkSupport()
794 {
795     return &m_benchmarkSupport;
796 }
797
798 WebVector<WebFloatQuad> WebViewImpl::getTouchHighlightQuads(const WebPoint& point,
799                                                             int padding,
800                                                             WebTouchCandidatesInfo& outTouchInfo,
801                                                             WebColor& outTapHighlightColor)
802 {
803     // FIXME: Upstream this function from the chromium-android branch.
804     notImplemented();
805
806     return WebVector<WebFloatQuad>();
807 }
808
809 bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
810 {
811     ASSERT((event.type == WebInputEvent::RawKeyDown)
812         || (event.type == WebInputEvent::KeyDown)
813         || (event.type == WebInputEvent::KeyUp));
814
815     // Halt an in-progress fling on a key event.
816     if (m_gestureAnimation)
817         m_gestureAnimation.clear();
818
819     // Please refer to the comments explaining the m_suppressNextKeypressEvent
820     // member.
821     // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
822     // Webkit. A keyDown event is typically associated with a keyPress(char)
823     // event and a keyUp event. We reset this flag here as this is a new keyDown
824     // event.
825     m_suppressNextKeypressEvent = false;
826
827     // If there is a select popup, it should be the one processing the event,
828     // not the page.
829     if (m_selectPopup)
830         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
831 #if ENABLE(PAGE_POPUP)
832     if (m_pagePopup) {
833         m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
834         // We need to ignore the next Char event after this otherwise pressing
835         // enter when selecting an item in the popup will go to the page.
836         if (WebInputEvent::RawKeyDown == event.type)
837             m_suppressNextKeypressEvent = true;
838         return true;
839     }
840 #endif
841
842     // Give Autocomplete a chance to consume the key events it is interested in.
843     if (autocompleteHandleKeyEvent(event))
844         return true;
845
846     RefPtr<Frame> frame = focusedWebCoreFrame();
847     if (!frame)
848         return false;
849
850     EventHandler* handler = frame->eventHandler();
851     if (!handler)
852         return keyEventDefault(event);
853
854 #if !OS(DARWIN)
855     const WebInputEvent::Type contextMenuTriggeringEventType =
856 #if OS(WINDOWS)
857         WebInputEvent::KeyUp;
858 #elif OS(UNIX)
859         WebInputEvent::RawKeyDown;
860 #endif
861
862     bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS;
863     bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10;
864     if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) {
865         sendContextMenuEvent(event);
866         return true;
867     }
868 #endif // !OS(DARWIN)
869
870     PlatformKeyboardEventBuilder evt(event);
871
872     if (handler->keyEvent(evt)) {
873         if (WebInputEvent::RawKeyDown == event.type) {
874             // Suppress the next keypress event unless the focused node is a plug-in node.
875             // (Flash needs these keypress events to handle non-US keyboards.)
876             Node* node = focusedWebCoreNode();
877             if (!node || !node->renderer() || !node->renderer()->isEmbeddedObject())
878                 m_suppressNextKeypressEvent = true;
879         }
880         return true;
881     }
882
883     return keyEventDefault(event);
884 }
885
886 bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event)
887 {
888     if (!m_autofillPopupShowing
889         // Home and End should be left to the text field to process.
890         || event.windowsKeyCode == VKEY_HOME
891         || event.windowsKeyCode == VKEY_END)
892       return false;
893
894     // Pressing delete triggers the removal of the selected suggestion from the DB.
895     if (event.windowsKeyCode == VKEY_DELETE
896         && m_autofillPopup->selectedIndex() != -1) {
897         Node* node = focusedWebCoreNode();
898         if (!node || (node->nodeType() != Node::ELEMENT_NODE)) {
899             ASSERT_NOT_REACHED();
900             return false;
901         }
902         Element* element = static_cast<Element*>(node);
903         if (!element->hasLocalName(HTMLNames::inputTag)) {
904             ASSERT_NOT_REACHED();
905             return false;
906         }
907
908         int selectedIndex = m_autofillPopup->selectedIndex();
909
910         if (!m_autofillPopupClient->canRemoveSuggestionAtIndex(selectedIndex))
911             return false;
912
913         WebString name = WebInputElement(static_cast<HTMLInputElement*>(element)).nameForAutofill();
914         WebString value = m_autofillPopupClient->itemText(selectedIndex);
915         m_autofillClient->removeAutocompleteSuggestion(name, value);
916         // Update the entries in the currently showing popup to reflect the
917         // deletion.
918         m_autofillPopupClient->removeSuggestionAtIndex(selectedIndex);
919         refreshAutofillPopup();
920         return false;
921     }
922
923     if (!m_autofillPopup->isInterestedInEventForKey(event.windowsKeyCode))
924         return false;
925
926     if (m_autofillPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event))) {
927         // We need to ignore the next Char event after this otherwise pressing
928         // enter when selecting an item in the menu will go to the page.
929         if (WebInputEvent::RawKeyDown == event.type)
930             m_suppressNextKeypressEvent = true;
931         return true;
932     }
933
934     return false;
935 }
936
937 bool WebViewImpl::handleCharEvent(const WebKeyboardEvent& event)
938 {
939     ASSERT(event.type == WebInputEvent::Char);
940
941     // Please refer to the comments explaining the m_suppressNextKeypressEvent
942     // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
943     // handled by Webkit. A keyDown event is typically associated with a
944     // keyPress(char) event and a keyUp event. We reset this flag here as it
945     // only applies to the current keyPress event.
946     bool suppress = m_suppressNextKeypressEvent;
947     m_suppressNextKeypressEvent = false;
948
949     // If there is a select popup, it should be the one processing the event,
950     // not the page.
951     if (m_selectPopup)
952         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
953 #if ENABLE(PAGE_POPUP)
954     if (m_pagePopup)
955         return m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
956 #endif
957
958     Frame* frame = focusedWebCoreFrame();
959     if (!frame)
960         return suppress;
961
962     EventHandler* handler = frame->eventHandler();
963     if (!handler)
964         return suppress || keyEventDefault(event);
965
966     PlatformKeyboardEventBuilder evt(event);
967     if (!evt.isCharacterKey())
968         return true;
969
970     // Accesskeys are triggered by char events and can't be suppressed.
971     if (handler->handleAccessKey(evt))
972         return true;
973
974     // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
975     // the eventHandler::keyEvent. We mimic this behavior on all platforms since
976     // for now we are converting other platform's key events to windows key
977     // events.
978     if (evt.isSystemKey())
979         return false;
980
981     if (!suppress && !handler->keyEvent(evt))
982         return keyEventDefault(event);
983
984     return true;
985 }
986
987 #if ENABLE(GESTURE_EVENTS)
988 WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, AutoZoomType zoomType)
989 {
990     if (!mainFrameImpl())
991         return WebRect();
992
993     // Use the rect-based hit test to find the node.
994     IntPoint point = mainFrameImpl()->frameView()->windowToContents(IntPoint(rect.x, rect.y));
995     HitTestResult result = mainFrameImpl()->frame()->eventHandler()->hitTestResultAtPoint(point,
996             false, zoomType == FindInPage, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
997             IntSize(rect.width, rect.height));
998
999     Node* node = result.innerNonSharedNode();
1000     if (!node)
1001         return WebRect();
1002
1003     // Find the block type node based on the hit node.
1004     while (node && (!node->renderer() || node->renderer()->isInline()))
1005         node = node->parentNode();
1006
1007     // Return the bounding box in the window coordinate system.
1008     if (node) {
1009         IntRect rect = node->Node::getPixelSnappedRect();
1010         Frame* frame = node->document()->frame();
1011         return frame->view()->contentsToWindow(rect);
1012     }
1013     return WebRect();
1014 }
1015
1016 WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int targetMargin, int minimumMargin)
1017 {
1018     WebSize maxSize;
1019     if (mainFrame())
1020         maxSize = mainFrame()->contentsSize();
1021     IntSize scrollOffset;
1022     if (mainFrame())
1023         scrollOffset = mainFrame()->scrollOffset();
1024     int leftMargin = targetMargin;
1025     int rightMargin = targetMargin;
1026
1027     const int absoluteSourceX = source.x + scrollOffset.width();
1028     if (leftMargin > absoluteSourceX) {
1029         leftMargin = absoluteSourceX;
1030         rightMargin = max(leftMargin, minimumMargin);
1031     }
1032
1033     const int maximumRightMargin = maxSize.width - (source.width + absoluteSourceX);
1034     if (rightMargin > maximumRightMargin) {
1035         rightMargin = maximumRightMargin;
1036         leftMargin = min(leftMargin, max(rightMargin, minimumMargin));
1037     }
1038
1039     const int newWidth = source.width + leftMargin + rightMargin;
1040     const int newX = source.x - leftMargin;
1041
1042     ASSERT(newWidth >= 0);
1043     ASSERT(scrollOffset.width() + newX + newWidth <= maxSize.width);
1044
1045     return WebRect(newX, source.y, newWidth, source.height);
1046 }
1047
1048 void WebViewImpl::computeScaleAndScrollForHitRect(const WebRect& hitRect, AutoZoomType zoomType, float& scale, WebPoint& scroll)
1049 {
1050     scale = pageScaleFactor();
1051     scroll.x = scroll.y = 0;
1052     WebRect targetRect = hitRect;
1053     if (targetRect.isEmpty())
1054         targetRect.width = targetRect.height = touchPointPadding;
1055
1056     WebRect rect = computeBlockBounds(targetRect, zoomType);
1057
1058     const float overviewScale = m_minimumPageScaleFactor;
1059     bool scaleUnchanged = true;
1060     if (!rect.isEmpty()) {
1061         // Pages should be as legible as on desktop when at dpi scale, so no
1062         // need to zoom in further when automatically determining zoom level
1063         // (after double tap, find in page, etc), though the user should still
1064         // be allowed to manually pinch zoom in further if they desire.
1065         const float maxScale = deviceScaleFactor();
1066
1067         const float defaultMargin = doubleTapZoomContentDefaultMargin * deviceScaleFactor();
1068         const float minimumMargin = doubleTapZoomContentMinimumMargin * deviceScaleFactor();
1069         // We want the margins to have the same physical size, which means we
1070         // need to express them in post-scale size. To do that we'd need to know
1071         // the scale we're scaling to, but that depends on the margins. Instead
1072         // we express them as a fraction of the target rectangle: this will be
1073         // correct if we end up fully zooming to it, and won't matter if we
1074         // don't.
1075         rect = widenRectWithinPageBounds(rect,
1076                 static_cast<int>(defaultMargin * rect.width / m_size.width),
1077                 static_cast<int>(minimumMargin * rect.width / m_size.width));
1078
1079         // Fit block to screen, respecting limits.
1080         scale *= static_cast<float>(m_size.width) / rect.width;
1081         scale = min(scale, maxScale);
1082         scale = clampPageScaleFactorToLimits(scale);
1083
1084         scaleUnchanged = fabs(pageScaleFactor() - scale) < minScaleDifference;
1085     }
1086
1087     if (zoomType == DoubleTap) {
1088         if (rect.isEmpty() || scaleUnchanged) {
1089             // Zoom out to overview mode.
1090             if (overviewScale)
1091                 scale = overviewScale;
1092             return;
1093         }
1094     } else if (rect.isEmpty()) {
1095         // Keep current scale (no need to scroll as x,y will normally already
1096         // be visible). FIXME: Revisit this if it isn't always true.
1097         return;
1098     }
1099
1100     // FIXME: If this is being called for auto zoom during find in page,
1101     // then if the user manually zooms in it'd be nice to preserve the relative
1102     // increase in zoom they caused (if they zoom out then it's ok to zoom
1103     // them back in again). This isn't compatible with our current double-tap
1104     // zoom strategy (fitting the containing block to the screen) though.
1105
1106     float screenHeight = m_size.height / scale * pageScaleFactor();
1107     float screenWidth = m_size.width / scale * pageScaleFactor();
1108
1109     // Scroll to vertically align the block.
1110     if (rect.height < screenHeight) {
1111         // Vertically center short blocks.
1112         rect.y -= 0.5 * (screenHeight - rect.height);
1113     } else {
1114         // Ensure position we're zooming to (+ padding) isn't off the bottom of
1115         // the screen.
1116         rect.y = max<float>(rect.y, hitRect.y + touchPointPadding - screenHeight);
1117     } // Otherwise top align the block.
1118
1119     // Do the same thing for horizontal alignment.
1120     if (rect.width < screenWidth)
1121         rect.x -= 0.5 * (screenWidth - rect.width);
1122     else
1123         rect.x = max<float>(rect.x, hitRect.x + touchPointPadding - screenWidth);
1124
1125     scroll.x = rect.x;
1126     scroll.y = rect.y;
1127 }
1128
1129 static bool highlightConditions(Node* node)
1130 {
1131     return node->isLink()
1132            || node->supportsFocus()
1133            || node->hasEventListeners(eventNames().clickEvent)
1134            || node->hasEventListeners(eventNames().mousedownEvent)
1135            || node->hasEventListeners(eventNames().mouseupEvent);
1136 }
1137
1138 Node* WebViewImpl::bestTouchLinkNode(IntPoint touchEventLocation)
1139 {
1140     if (!m_page || !m_page->mainFrame())
1141         return 0;
1142
1143     Node* bestTouchNode = 0;
1144
1145     // FIXME: Should accept a search region from the caller instead of hard-coding the size.
1146     IntSize touchEventSearchRegionSize(4, 2);
1147     m_page->mainFrame()->eventHandler()->bestClickableNodeForTouchPoint(touchEventLocation, touchEventSearchRegionSize, touchEventLocation, bestTouchNode);
1148     // bestClickableNodeForTouchPoint() doesn't always return a node that is a link, so let's try and find
1149     // a link to highlight.
1150     while (bestTouchNode && !highlightConditions(bestTouchNode))
1151         bestTouchNode = bestTouchNode->parentNode();
1152
1153     return bestTouchNode;
1154 }
1155
1156 void WebViewImpl::enableTouchHighlight(IntPoint touchEventLocation)
1157 {
1158     Node* touchNode = bestTouchLinkNode(touchEventLocation);
1159
1160     if (!touchNode || !touchNode->renderer() || !touchNode->renderer()->enclosingLayer())
1161         return;
1162
1163     Color highlightColor = touchNode->renderer()->style()->tapHighlightColor();
1164     // Safari documentation for -webkit-tap-highlight-color says if the specified color has 0 alpha,
1165     // then tap highlighting is disabled.
1166     // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
1167     if (!highlightColor.alpha())
1168         return;
1169
1170     // This will clear any highlight currently being displayed.
1171     m_linkHighlight = LinkHighlight::create(touchNode, this);
1172     m_linkHighlight->startHighlightAnimation();
1173 }
1174
1175 #endif
1176
1177 void WebViewImpl::animateZoomAroundPoint(const IntPoint& point, AutoZoomType zoomType)
1178 {
1179 #if ENABLE(GESTURE_EVENTS)
1180     if (!mainFrameImpl())
1181         return;
1182
1183     float scale;
1184     WebPoint scroll;
1185     computeScaleAndScrollForHitRect(WebRect(point.x(), point.y(), 0, 0), zoomType, scale, scroll);
1186
1187     bool isDoubleTap = (zoomType == DoubleTap);
1188     double durationInSeconds = isDoubleTap ? doubleTapZoomAnimationDurationInSeconds : 0;
1189     startPageScaleAnimation(scroll, isDoubleTap, scale, durationInSeconds);
1190 #endif
1191 }
1192
1193 void WebViewImpl::zoomToFindInPageRect(const WebRect& rect)
1194 {
1195     animateZoomAroundPoint(IntRect(rect).center(), FindInPage);
1196 }
1197
1198 void WebViewImpl::numberOfWheelEventHandlersChanged(unsigned numberOfWheelHandlers)
1199 {
1200     if (m_client)
1201         m_client->numberOfWheelEventHandlersChanged(numberOfWheelHandlers);
1202 }
1203
1204 void WebViewImpl::hasTouchEventHandlers(bool hasTouchHandlers)
1205 {
1206     if (m_client)
1207         m_client->hasTouchEventHandlers(hasTouchHandlers);
1208 }
1209
1210 #if !OS(DARWIN)
1211 // Mac has no way to open a context menu based on a keyboard event.
1212 bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
1213 {
1214     // The contextMenuController() holds onto the last context menu that was
1215     // popped up on the page until a new one is created. We need to clear
1216     // this menu before propagating the event through the DOM so that we can
1217     // detect if we create a new menu for this event, since we won't create
1218     // a new menu if the DOM swallows the event and the defaultEventHandler does
1219     // not run.
1220     page()->contextMenuController()->clearContextMenu();
1221
1222     m_contextMenuAllowed = true;
1223     Frame* focusedFrame = page()->focusController()->focusedOrMainFrame();
1224     bool handled = focusedFrame->eventHandler()->sendContextMenuEventForKey();
1225     m_contextMenuAllowed = false;
1226     return handled;
1227 }
1228 #endif
1229
1230 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
1231 {
1232     Frame* frame = focusedWebCoreFrame();
1233     if (!frame)
1234         return false;
1235
1236     switch (event.type) {
1237     case WebInputEvent::Char:
1238         if (event.windowsKeyCode == VKEY_SPACE) {
1239             int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
1240             return scrollViewWithKeyboard(keyCode, event.modifiers);
1241         }
1242         break;
1243     case WebInputEvent::RawKeyDown:
1244         if (event.modifiers == WebInputEvent::ControlKey) {
1245             switch (event.windowsKeyCode) {
1246 #if !OS(DARWIN)
1247             case 'A':
1248                 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
1249                 return true;
1250             case VKEY_INSERT:
1251             case 'C':
1252                 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
1253                 return true;
1254 #endif
1255             // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
1256             // key combinations which affect scrolling. Safari is buggy in the
1257             // sense that it scrolls the page for all Ctrl+scrolling key
1258             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
1259             case VKEY_HOME:
1260             case VKEY_END:
1261                 break;
1262             default:
1263                 return false;
1264             }
1265         }
1266         if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
1267             return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
1268         break;
1269     default:
1270         break;
1271     }
1272     return false;
1273 }
1274
1275 bool WebViewImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
1276 {
1277     ScrollDirection scrollDirection;
1278     ScrollGranularity scrollGranularity;
1279 #if OS(DARWIN)
1280     // Control-Up/Down should be PageUp/Down on Mac.
1281     if (modifiers & WebMouseEvent::ControlKey) {
1282       if (keyCode == VKEY_UP)
1283         keyCode = VKEY_PRIOR;
1284       else if (keyCode == VKEY_DOWN)
1285         keyCode = VKEY_NEXT;
1286     }
1287 #endif
1288     if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
1289         return false;
1290     return propagateScroll(scrollDirection, scrollGranularity);
1291 }
1292
1293 bool WebViewImpl::mapKeyCodeForScroll(int keyCode,
1294                                       WebCore::ScrollDirection* scrollDirection,
1295                                       WebCore::ScrollGranularity* scrollGranularity)
1296 {
1297     switch (keyCode) {
1298     case VKEY_LEFT:
1299         *scrollDirection = ScrollLeft;
1300         *scrollGranularity = ScrollByLine;
1301         break;
1302     case VKEY_RIGHT:
1303         *scrollDirection = ScrollRight;
1304         *scrollGranularity = ScrollByLine;
1305         break;
1306     case VKEY_UP:
1307         *scrollDirection = ScrollUp;
1308         *scrollGranularity = ScrollByLine;
1309         break;
1310     case VKEY_DOWN:
1311         *scrollDirection = ScrollDown;
1312         *scrollGranularity = ScrollByLine;
1313         break;
1314     case VKEY_HOME:
1315         *scrollDirection = ScrollUp;
1316         *scrollGranularity = ScrollByDocument;
1317         break;
1318     case VKEY_END:
1319         *scrollDirection = ScrollDown;
1320         *scrollGranularity = ScrollByDocument;
1321         break;
1322     case VKEY_PRIOR:  // page up
1323         *scrollDirection = ScrollUp;
1324         *scrollGranularity = ScrollByPage;
1325         break;
1326     case VKEY_NEXT:  // page down
1327         *scrollDirection = ScrollDown;
1328         *scrollGranularity = ScrollByPage;
1329         break;
1330     default:
1331         return false;
1332     }
1333
1334     return true;
1335 }
1336
1337 void WebViewImpl::hideSelectPopup()
1338 {
1339     if (m_selectPopup)
1340         m_selectPopup->hidePopup();
1341 }
1342
1343 bool WebViewImpl::propagateScroll(ScrollDirection scrollDirection,
1344                                   ScrollGranularity scrollGranularity)
1345 {
1346     Frame* frame = focusedWebCoreFrame();
1347     if (!frame)
1348         return false;
1349
1350     bool scrollHandled = frame->eventHandler()->scrollOverflow(scrollDirection, scrollGranularity);
1351     Frame* currentFrame = frame;
1352     while (!scrollHandled && currentFrame) {
1353         scrollHandled = currentFrame->view()->scroll(scrollDirection, scrollGranularity);
1354         currentFrame = currentFrame->tree()->parent();
1355     }
1356     return scrollHandled;
1357 }
1358
1359 void  WebViewImpl::popupOpened(WebCore::PopupContainer* popupContainer)
1360 {
1361     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
1362         ASSERT(!m_selectPopup);
1363         m_selectPopup = popupContainer;
1364     }
1365 }
1366
1367 void  WebViewImpl::popupClosed(WebCore::PopupContainer* popupContainer)
1368 {
1369     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
1370         ASSERT(m_selectPopup);
1371         m_selectPopup = 0;
1372     }
1373 }
1374
1375 #if ENABLE(PAGE_POPUP)
1376 PagePopup* WebViewImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
1377 {
1378     ASSERT(client);
1379     if (hasOpenedPopup())
1380         hidePopups();
1381     ASSERT(!m_pagePopup);
1382
1383     WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypePage);
1384     ASSERT(popupWidget);
1385     m_pagePopup = static_cast<WebPagePopupImpl*>(popupWidget);
1386     if (!m_pagePopup->init(this, client, originBoundsInRootView)) {
1387         m_pagePopup->closePopup();
1388         m_pagePopup = 0;
1389     }
1390
1391     if (Frame* frame = focusedWebCoreFrame())
1392         frame->selection()->setCaretVisible(false);
1393     return m_pagePopup.get();
1394 }
1395
1396 void WebViewImpl::closePagePopup(PagePopup* popup)
1397 {
1398     ASSERT(popup);
1399     WebPagePopupImpl* popupImpl = static_cast<WebPagePopupImpl*>(popup);
1400     ASSERT(m_pagePopup.get() == popupImpl);
1401     if (m_pagePopup.get() != popupImpl)
1402         return;
1403     m_pagePopup->closePopup();
1404     m_pagePopup = 0;
1405
1406     if (Frame* frame = focusedWebCoreFrame())
1407         frame->selection()->pageActivationChanged();
1408 }
1409 #endif
1410
1411 void WebViewImpl::hideAutofillPopup()
1412 {
1413     if (m_autofillPopupShowing) {
1414         m_autofillPopup->hidePopup();
1415         m_autofillPopupShowing = false;
1416     }
1417 }
1418
1419 WebHelperPluginImpl* WebViewImpl::createHelperPlugin(const String& pluginType)
1420 {
1421     WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypeHelperPlugin);
1422     ASSERT(popupWidget);
1423     WebHelperPluginImpl* helperPlugin = static_cast<WebHelperPluginImpl*>(popupWidget);
1424
1425     if (!helperPlugin->init(this, pluginType)) {
1426         helperPlugin->closeHelperPlugin();
1427         helperPlugin = 0;
1428     }
1429     return helperPlugin;
1430 }
1431
1432 Frame* WebViewImpl::focusedWebCoreFrame() const
1433 {
1434     return m_page ? m_page->focusController()->focusedOrMainFrame() : 0;
1435 }
1436
1437 WebViewImpl* WebViewImpl::fromPage(Page* page)
1438 {
1439     if (!page)
1440         return 0;
1441
1442     ChromeClientImpl* chromeClient = static_cast<ChromeClientImpl*>(page->chrome()->client());
1443     return static_cast<WebViewImpl*>(chromeClient->webView());
1444 }
1445
1446 PageGroup* WebViewImpl::defaultPageGroup()
1447 {
1448     return PageGroup::pageGroup(pageGroupName);
1449 }
1450
1451 // WebWidget ------------------------------------------------------------------
1452
1453 void WebViewImpl::close()
1454 {
1455     RefPtr<WebFrameImpl> mainFrameImpl;
1456
1457     if (m_page) {
1458         // Initiate shutdown for the entire frameset.  This will cause a lot of
1459         // notifications to be sent.
1460         if (m_page->mainFrame()) {
1461             mainFrameImpl = WebFrameImpl::fromFrame(m_page->mainFrame());
1462             m_page->mainFrame()->loader()->frameDetached();
1463         }
1464         m_page.clear();
1465     }
1466
1467     // Should happen after m_page.clear().
1468     if (m_devToolsAgent)
1469         m_devToolsAgent.clear();
1470
1471     // Reset the delegate to prevent notifications being sent as we're being
1472     // deleted.
1473     m_client = 0;
1474
1475     deref();  // Balances ref() acquired in WebView::create
1476 }
1477
1478 void WebViewImpl::willStartLiveResize()
1479 {
1480     if (mainFrameImpl() && mainFrameImpl()->frameView())
1481         mainFrameImpl()->frameView()->willStartLiveResize();
1482
1483     Frame* frame = mainFrameImpl()->frame();
1484     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
1485     if (pluginContainer)
1486         pluginContainer->willStartLiveResize();
1487 }
1488
1489 void WebViewImpl::resize(const WebSize& newSize)
1490 {
1491     if (m_shouldAutoResize || m_size == newSize)
1492         return;
1493
1494     FrameView* view = mainFrameImpl()->frameView();
1495     if (!view)
1496         return;
1497
1498     WebSize oldSize = m_size;
1499     float oldPageScaleFactor = pageScaleFactor();
1500     IntSize oldScrollOffset = view->scrollOffset();
1501     int oldFixedLayoutWidth = fixedLayoutSize().width;
1502
1503     m_size = newSize;
1504
1505 #if ENABLE(VIEWPORT)
1506     if (settings()->viewportEnabled()) {
1507         // Fallback width is used to layout sites designed for desktop. The
1508         // conventional size used by all mobile browsers is 980. When a mobile
1509         // device has a particularly wide screen (such as a 10" tablet held in
1510         // landscape), it can be larger.
1511         const int standardFallbackWidth = 980;
1512         int dpiIndependentViewportWidth = newSize.width / page()->deviceScaleFactor();
1513         settings()->setLayoutFallbackWidth(std::max(standardFallbackWidth, dpiIndependentViewportWidth));
1514
1515         ViewportArguments viewportArguments = mainFrameImpl()->frame()->document()->viewportArguments();
1516         m_page->chrome()->client()->dispatchViewportPropertiesDidChange(viewportArguments);
1517     }
1518 #endif
1519
1520     WebDevToolsAgentPrivate* agentPrivate = devToolsAgentPrivate();
1521     if (agentPrivate && agentPrivate->metricsOverridden())
1522         agentPrivate->webViewResized();
1523     else {
1524         WebFrameImpl* webFrame = mainFrameImpl();
1525         if (webFrame->frameView())
1526             webFrame->frameView()->resize(newSize.width, newSize.height);
1527     }
1528
1529 #if ENABLE(VIEWPORT)
1530     if (settings()->viewportEnabled()) {
1531         // Relayout immediately to obtain the new content width, which is needed
1532         // to calculate the minimum scale limit.
1533         view->layout();
1534         computePageScaleFactorLimits();
1535         // When the device rotates:
1536         // - If the page width is unchanged, then zoom by new width/old width
1537         //   such as to keep the same content horizontally onscreen.
1538         // - If the page width stretches proportionally to the change in
1539         //   screen width, then don't zoom at all (assuming the content has
1540         //   scaled uniformly, then the same content will be horizontally
1541         //   onscreen).
1542         //   - If the page width partially stretches, then zoom partially to
1543         //   make up the difference.
1544         // In all cases try to keep the same content at the top of the screen.
1545         float viewportWidthRatio = !oldSize.width ? 1 : newSize.width / (float) oldSize.width;
1546         float fixedLayoutWidthRatio = !oldFixedLayoutWidth ? 1 : fixedLayoutSize().width / (float) oldFixedLayoutWidth;
1547         float scaleMultiplier = viewportWidthRatio / fixedLayoutWidthRatio;
1548         if (scaleMultiplier != 1) {
1549             IntSize scrollOffsetAtNewScale = oldScrollOffset;
1550             scrollOffsetAtNewScale.scale(scaleMultiplier);
1551             setPageScaleFactor(oldPageScaleFactor * scaleMultiplier, IntPoint(scrollOffsetAtNewScale));
1552         }
1553     }
1554 #endif
1555
1556     sendResizeEventAndRepaint();
1557 }
1558
1559 void WebViewImpl::willEndLiveResize()
1560 {
1561     if (mainFrameImpl() && mainFrameImpl()->frameView())
1562         mainFrameImpl()->frameView()->willEndLiveResize();
1563
1564     Frame* frame = mainFrameImpl()->frame();
1565     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
1566     if (pluginContainer)
1567         pluginContainer->willEndLiveResize();
1568 }
1569
1570 void WebViewImpl::willEnterFullScreen()
1571 {
1572 #if ENABLE(FULLSCREEN_API)
1573     if (!m_provisionalFullScreenElement)
1574         return;
1575
1576     // Ensure that this element's document is still attached.
1577     Document* doc = m_provisionalFullScreenElement->document();
1578     if (doc->frame()) {
1579         doc->webkitWillEnterFullScreenForElement(m_provisionalFullScreenElement.get());
1580         m_fullScreenFrame = doc->frame();
1581     }
1582     m_provisionalFullScreenElement.clear();
1583 #endif
1584 }
1585
1586 void WebViewImpl::didEnterFullScreen()
1587 {
1588 #if ENABLE(FULLSCREEN_API)
1589     if (!m_fullScreenFrame)
1590         return;
1591
1592     if (Document* doc = m_fullScreenFrame->document()) {
1593         if (doc->webkitIsFullScreen())
1594             doc->webkitDidEnterFullScreenForElement(0);
1595     }
1596 #endif
1597 }
1598
1599 void WebViewImpl::willExitFullScreen()
1600 {
1601 #if ENABLE(FULLSCREEN_API)
1602     if (!m_fullScreenFrame)
1603         return;
1604
1605     if (Document* doc = m_fullScreenFrame->document()) {
1606         if (doc->webkitIsFullScreen()) {
1607             // When the client exits from full screen we have to call webkitCancelFullScreen to
1608             // notify the document. While doing that, suppress notifications back to the client.
1609             m_isCancelingFullScreen = true;
1610             doc->webkitCancelFullScreen();
1611             m_isCancelingFullScreen = false;
1612             doc->webkitWillExitFullScreenForElement(0);
1613         }
1614     }
1615 #endif
1616 }
1617
1618 void WebViewImpl::didExitFullScreen()
1619 {
1620 #if ENABLE(FULLSCREEN_API)
1621     if (!m_fullScreenFrame)
1622         return;
1623
1624     if (Document* doc = m_fullScreenFrame->document()) {
1625         if (doc->webkitIsFullScreen())
1626             doc->webkitDidExitFullScreenForElement(0);
1627     }
1628
1629     m_fullScreenFrame.clear();
1630 #endif
1631 }
1632
1633 void WebViewImpl::instrumentBeginFrame()
1634 {
1635     InspectorInstrumentation::didBeginFrame(m_page.get());
1636 }
1637
1638 void WebViewImpl::instrumentCancelFrame()
1639 {
1640     InspectorInstrumentation::didCancelFrame(m_page.get());
1641 }
1642
1643 #if ENABLE(BATTERY_STATUS)
1644 void WebViewImpl::updateBatteryStatus(const WebBatteryStatus& status)
1645 {
1646     m_batteryClient->updateBatteryStatus(status);
1647 }
1648 #endif
1649
1650 void WebViewImpl::setCompositorSurfaceReady()
1651 {
1652     m_compositorSurfaceReady = true;
1653     if (!m_layerTreeView.isNull())
1654         m_layerTreeView.setSurfaceReady();
1655 }
1656
1657 void WebViewImpl::animate(double)
1658 {
1659 #if ENABLE(REQUEST_ANIMATION_FRAME)
1660     double monotonicFrameBeginTime = monotonicallyIncreasingTime();
1661
1662 #if USE(ACCELERATED_COMPOSITING)
1663     // In composited mode, we always go through the compositor so it can apply
1664     // appropriate flow-control mechanisms.
1665     if (isAcceleratedCompositingActive())
1666         m_layerTreeView.updateAnimations(monotonicFrameBeginTime);
1667     else
1668 #endif
1669         updateAnimations(monotonicFrameBeginTime);
1670 #endif
1671 }
1672
1673 void WebViewImpl::willBeginFrame()
1674 {
1675     instrumentBeginFrame();
1676     m_client->willBeginCompositorFrame();
1677 }
1678
1679 void WebViewImpl::didBeginFrame()
1680 {
1681     InspectorInstrumentation::didComposite(m_page.get());
1682 }
1683
1684 void WebViewImpl::updateAnimations(double monotonicFrameBeginTime)
1685 {
1686 #if ENABLE(REQUEST_ANIMATION_FRAME)
1687     TRACE_EVENT0("webkit", "WebViewImpl::updateAnimations");
1688
1689     WebFrameImpl* webframe = mainFrameImpl();
1690     if (!webframe)
1691         return;
1692     FrameView* view = webframe->frameView();
1693     if (!view)
1694         return;
1695
1696     // Create synthetic wheel events as necessary for fling.
1697     if (m_gestureAnimation) {
1698         if (m_gestureAnimation->animate(monotonicFrameBeginTime))
1699             scheduleAnimation();
1700         else
1701             m_gestureAnimation.clear();
1702     }
1703
1704     PageWidgetDelegate::animate(m_page.get(), monotonicFrameBeginTime);
1705 #endif
1706 }
1707
1708 void WebViewImpl::layout()
1709 {
1710     TRACE_EVENT0("webkit", "WebViewImpl::layout");
1711     PageWidgetDelegate::layout(m_page.get());
1712
1713     if (m_linkHighlight)
1714         m_linkHighlight->updateGeometry();
1715 }
1716
1717 #if USE(ACCELERATED_COMPOSITING)
1718 void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect)
1719 {
1720     ASSERT(!m_layerTreeView.isNull());
1721
1722     PlatformContextSkia context(canvas);
1723
1724     // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
1725     GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
1726     int bitmapHeight = canvas->getDevice()->accessBitmap(false).height();
1727
1728     // Compute rect to sample from inverted GPU buffer.
1729     IntRect invertRect(rect.x(), bitmapHeight - rect.maxY(), rect.width(), rect.height());
1730
1731     OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(rect.size()));
1732     RefPtr<Uint8ClampedArray> pixelArray(Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4));
1733     if (imageBuffer && pixelArray) {
1734         m_layerTreeView.compositeAndReadback(pixelArray->data(), invertRect);
1735         imageBuffer->putByteArray(Premultiplied, pixelArray.get(), rect.size(), IntRect(IntPoint(), rect.size()), IntPoint());
1736         gc.save();
1737         gc.translate(IntSize(0, bitmapHeight));
1738         gc.scale(FloatSize(1.0f, -1.0f));
1739         // Use invertRect in next line, so that transform above inverts it back to
1740         // desired destination rect.
1741         gc.drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, invertRect.location());
1742         gc.restore();
1743     }
1744 }
1745 #endif
1746
1747 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions option)
1748 {
1749 #if !OS(ANDROID)
1750     // ReadbackFromCompositorIfAvailable is the only option available on non-Android.
1751     // Ideally, Android would always use ReadbackFromCompositorIfAvailable as well.
1752     ASSERT(option == ReadbackFromCompositorIfAvailable);
1753 #endif
1754
1755     if (option == ReadbackFromCompositorIfAvailable && isAcceleratedCompositingActive()) {
1756 #if USE(ACCELERATED_COMPOSITING)
1757         // If a canvas was passed in, we use it to grab a copy of the
1758         // freshly-rendered pixels.
1759         if (canvas) {
1760             // Clip rect to the confines of the rootLayerTexture.
1761             IntRect resizeRect(rect);
1762             resizeRect.intersect(IntRect(IntPoint(0, 0), m_layerTreeView.deviceViewportSize()));
1763             doPixelReadbackToCanvas(canvas, resizeRect);
1764         }
1765 #endif
1766     } else {
1767         FrameView* view = page()->mainFrame()->view();
1768         PaintBehavior oldPaintBehavior = view->paintBehavior();
1769         if (isAcceleratedCompositingActive()) {
1770             ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);            
1771             view->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers);
1772         }
1773
1774         double paintStart = currentTime();
1775         PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
1776         double paintEnd = currentTime();
1777         double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart);
1778         WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
1779         WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
1780
1781         if (isAcceleratedCompositingActive()) {
1782             ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);            
1783             view->setPaintBehavior(oldPaintBehavior);
1784         }
1785     }
1786 }
1787
1788 void WebViewImpl::themeChanged()
1789 {
1790     if (!page())
1791         return;
1792     FrameView* view = page()->mainFrame()->view();
1793
1794     WebRect damagedRect(0, 0, m_size.width, m_size.height);
1795     view->invalidateRect(damagedRect);
1796 }
1797
1798 void WebViewImpl::composite(bool)
1799 {
1800 #if USE(ACCELERATED_COMPOSITING)
1801     if (WebCompositor::threadingEnabled())
1802         m_layerTreeView.setNeedsRedraw();
1803     else {
1804         ASSERT(isAcceleratedCompositingActive());
1805         if (!page())
1806             return;
1807
1808         if (m_pageOverlays)
1809             m_pageOverlays->update();
1810
1811         m_layerTreeView.composite();
1812     }
1813 #endif
1814 }
1815
1816 void WebViewImpl::setNeedsRedraw()
1817 {
1818 #if USE(ACCELERATED_COMPOSITING)
1819     if (!m_layerTreeView.isNull() && isAcceleratedCompositingActive())
1820         m_layerTreeView.setNeedsRedraw();
1821 #endif
1822 }
1823
1824 bool WebViewImpl::isInputThrottled() const
1825 {
1826 #if USE(ACCELERATED_COMPOSITING)
1827     if (!m_layerTreeView.isNull() && isAcceleratedCompositingActive())
1828         return m_layerTreeView.commitRequested();
1829 #endif
1830     return false;
1831 }
1832
1833 void WebViewImpl::loseCompositorContext(int numTimes)
1834 {
1835 #if USE(ACCELERATED_COMPOSITING)
1836     if (!m_layerTreeView.isNull())
1837         m_layerTreeView.loseCompositorContext(numTimes);
1838 #endif
1839 }
1840
1841 void WebViewImpl::enterFullScreenForElement(WebCore::Element* element)
1842 {
1843     // We are already transitioning to fullscreen for a different element.
1844     if (m_provisionalFullScreenElement) {
1845         m_provisionalFullScreenElement = element;
1846         return;
1847     }
1848
1849     // We are already in fullscreen mode.
1850     if (m_fullScreenFrame) {
1851         m_provisionalFullScreenElement = element;
1852         willEnterFullScreen();
1853         didEnterFullScreen();
1854         return;
1855     }
1856
1857 #if USE(NATIVE_FULLSCREEN_VIDEO)
1858     if (element && element->isMediaElement()) {
1859         HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element);
1860         if (mediaElement->player() && mediaElement->player()->canEnterFullscreen()) {
1861             mediaElement->player()->enterFullscreen();
1862             m_provisionalFullScreenElement = element;
1863         }
1864         return;
1865     }
1866 #endif
1867
1868     // We need to transition to fullscreen mode.
1869     if (m_client && m_client->enterFullScreen())
1870         m_provisionalFullScreenElement = element;
1871 }
1872
1873 void WebViewImpl::exitFullScreenForElement(WebCore::Element* element)
1874 {
1875     // The client is exiting full screen, so don't send a notification.
1876     if (m_isCancelingFullScreen)
1877         return;
1878 #if USE(NATIVE_FULLSCREEN_VIDEO)
1879     if (element && element->isMediaElement()) {
1880         HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element);
1881         if (mediaElement->player())
1882             mediaElement->player()->exitFullscreen();
1883         return;
1884     }
1885 #endif
1886     if (m_client)
1887         m_client->exitFullScreen();
1888 }
1889
1890 bool WebViewImpl::hasHorizontalScrollbar()
1891 {
1892     return mainFrameImpl()->frameView()->horizontalScrollbar();
1893 }
1894
1895 bool WebViewImpl::hasVerticalScrollbar()
1896 {
1897     return mainFrameImpl()->frameView()->verticalScrollbar();
1898 }
1899
1900 const WebInputEvent* WebViewImpl::m_currentInputEvent = 0;
1901
1902 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
1903 {
1904     UserGestureIndicator gestureIndicator(WebInputEvent::isUserGestureEventType(inputEvent.type) ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
1905
1906     // If we've started a drag and drop operation, ignore input events until
1907     // we're done.
1908     if (m_doingDragAndDrop)
1909         return true;
1910
1911     // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
1912     if (m_ignoreInputEvents)
1913         return false;
1914
1915     TemporaryChange<const WebInputEvent*> currentEventChange(m_currentInputEvent, &inputEvent);
1916
1917 #if ENABLE(POINTER_LOCK)
1918     if (isPointerLocked() && WebInputEvent::isMouseEventType(inputEvent.type)) {
1919       pointerLockMouseEvent(inputEvent);
1920       return true;
1921     }
1922 #endif
1923
1924     if (m_mouseCaptureNode && WebInputEvent::isMouseEventType(inputEvent.type)) {
1925         // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
1926         RefPtr<Node> node = m_mouseCaptureNode;
1927
1928         // Not all platforms call mouseCaptureLost() directly.
1929         if (inputEvent.type == WebInputEvent::MouseUp)
1930             mouseCaptureLost();
1931
1932         AtomicString eventType;
1933         switch (inputEvent.type) {
1934         case WebInputEvent::MouseMove:
1935             eventType = eventNames().mousemoveEvent;
1936             break;
1937         case WebInputEvent::MouseLeave:
1938             eventType = eventNames().mouseoutEvent;
1939             break;
1940         case WebInputEvent::MouseDown:
1941             eventType = eventNames().mousedownEvent;
1942             break;
1943         case WebInputEvent::MouseUp:
1944             eventType = eventNames().mouseupEvent;
1945             break;
1946         default:
1947             ASSERT_NOT_REACHED();
1948         }
1949
1950         node->dispatchMouseEvent(
1951               PlatformMouseEventBuilder(mainFrameImpl()->frameView(), *static_cast<const WebMouseEvent*>(&inputEvent)),
1952               eventType, static_cast<const WebMouseEvent*>(&inputEvent)->clickCount);
1953         return true;
1954     }
1955
1956     bool handled = PageWidgetDelegate::handleInputEvent(m_page.get(), *this, inputEvent);
1957     return handled;
1958 }
1959
1960 void WebViewImpl::mouseCaptureLost()
1961 {
1962     m_mouseCaptureNode = 0;
1963 }
1964
1965 void WebViewImpl::setFocus(bool enable)
1966 {
1967     m_page->focusController()->setFocused(enable);
1968     if (enable) {
1969         m_page->focusController()->setActive(true);
1970         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
1971         if (focusedFrame) {
1972             Node* focusedNode = focusedFrame->document()->focusedNode();
1973             if (focusedNode && focusedNode->isElementNode()
1974                 && focusedFrame->selection()->selection().isNone()) {
1975                 // If the selection was cleared while the WebView was not
1976                 // focused, then the focus element shows with a focus ring but
1977                 // no caret and does respond to keyboard inputs.
1978                 Element* element = static_cast<Element*>(focusedNode);
1979                 if (element->isTextFormControl())
1980                     element->updateFocusAppearance(true);
1981                 else if (focusedNode->isContentEditable()) {
1982                     // updateFocusAppearance() selects all the text of
1983                     // contentseditable DIVs. So we set the selection explicitly
1984                     // instead. Note that this has the side effect of moving the
1985                     // caret back to the beginning of the text.
1986                     Position position(focusedNode, 0,
1987                                       Position::PositionIsOffsetInAnchor);
1988                     focusedFrame->selection()->setSelection(
1989                         VisibleSelection(position, SEL_DEFAULT_AFFINITY));
1990                 }
1991             }
1992         }
1993         m_imeAcceptEvents = true;
1994     } else {
1995         hidePopups();
1996
1997         // Clear focus on the currently focused frame if any.
1998         if (!m_page)
1999             return;
2000
2001         Frame* frame = m_page->mainFrame();
2002         if (!frame)
2003             return;
2004
2005         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
2006         if (focusedFrame) {
2007             // Finish an ongoing composition to delete the composition node.
2008             Editor* editor = focusedFrame->editor();
2009             if (editor && editor->hasComposition())
2010                 editor->confirmComposition();
2011             m_imeAcceptEvents = false;
2012         }
2013     }
2014 }
2015
2016 bool WebViewImpl::setComposition(
2017     const WebString& text,
2018     const WebVector<WebCompositionUnderline>& underlines,
2019     int selectionStart,
2020     int selectionEnd)
2021 {
2022     Frame* focused = focusedWebCoreFrame();
2023     if (!focused || !m_imeAcceptEvents)
2024         return false;
2025     Editor* editor = focused->editor();
2026     if (!editor)
2027         return false;
2028
2029     // The input focus has been moved to another WebWidget object.
2030     // We should use this |editor| object only to complete the ongoing
2031     // composition.
2032     if (!editor->canEdit() && !editor->hasComposition())
2033         return false;
2034
2035     // We should verify the parent node of this IME composition node are
2036     // editable because JavaScript may delete a parent node of the composition
2037     // node. In this case, WebKit crashes while deleting texts from the parent
2038     // node, which doesn't exist any longer.
2039     PassRefPtr<Range> range = editor->compositionRange();
2040     if (range) {
2041         Node* node = range->startContainer();
2042         if (!node || !node->isContentEditable())
2043             return false;
2044     }
2045
2046     // If we're not going to fire a keypress event, then the keydown event was
2047     // canceled.  In that case, cancel any existing composition.
2048     if (text.isEmpty() || m_suppressNextKeypressEvent) {
2049         // A browser process sent an IPC message which does not contain a valid
2050         // string, which means an ongoing composition has been canceled.
2051         // If the ongoing composition has been canceled, replace the ongoing
2052         // composition string with an empty string and complete it.
2053         String emptyString;
2054         Vector<CompositionUnderline> emptyUnderlines;
2055         editor->setComposition(emptyString, emptyUnderlines, 0, 0);
2056         return text.isEmpty();
2057     }
2058
2059     // When the range of composition underlines overlap with the range between
2060     // selectionStart and selectionEnd, WebKit somehow won't paint the selection
2061     // at all (see InlineTextBox::paint() function in InlineTextBox.cpp).
2062     // But the selection range actually takes effect.
2063     editor->setComposition(String(text),
2064                            CompositionUnderlineVectorBuilder(underlines),
2065                            selectionStart, selectionEnd);
2066
2067     return editor->hasComposition();
2068 }
2069
2070 bool WebViewImpl::confirmComposition()
2071 {
2072     return confirmComposition(WebString());
2073 }
2074
2075 bool WebViewImpl::confirmComposition(const WebString& text)
2076 {
2077     Frame* focused = focusedWebCoreFrame();
2078     if (!focused || !m_imeAcceptEvents)
2079         return false;
2080     Editor* editor = focused->editor();
2081     if (!editor || (!editor->hasComposition() && !text.length()))
2082         return false;
2083
2084     // We should verify the parent node of this IME composition node are
2085     // editable because JavaScript may delete a parent node of the composition
2086     // node. In this case, WebKit crashes while deleting texts from the parent
2087     // node, which doesn't exist any longer.
2088     PassRefPtr<Range> range = editor->compositionRange();
2089     if (range) {
2090         Node* node = range->startContainer();
2091         if (!node || !node->isContentEditable())
2092             return false;
2093     }
2094
2095     if (editor->hasComposition()) {
2096         if (text.length())
2097             editor->confirmComposition(String(text));
2098         else
2099             editor->confirmComposition();
2100     } else
2101         editor->insertText(String(text), 0);
2102
2103     return true;
2104 }
2105
2106 bool WebViewImpl::compositionRange(size_t* location, size_t* length)
2107 {
2108     Frame* focused = focusedWebCoreFrame();
2109     if (!focused || !focused->selection() || !m_imeAcceptEvents)
2110         return false;
2111     Editor* editor = focused->editor();
2112     if (!editor || !editor->hasComposition())
2113         return false;
2114
2115     RefPtr<Range> range = editor->compositionRange();
2116     if (!range)
2117         return false;
2118
2119     if (TextIterator::getLocationAndLengthFromRange(focused->selection()->rootEditableElementOrDocumentElement(), range.get(), *location, *length))
2120         return true;
2121     return false;
2122 }
2123
2124 WebTextInputInfo WebViewImpl::textInputInfo()
2125 {
2126     WebTextInputInfo info;
2127
2128     Frame* focused = focusedWebCoreFrame();
2129     if (!focused)
2130         return info;
2131
2132     Editor* editor = focused->editor();
2133     if (!editor || !editor->canEdit())
2134         return info;
2135
2136     FrameSelection* selection = focused->selection();
2137     if (!selection)
2138         return info;
2139
2140     Node* node = selection->selection().rootEditableElement();
2141     if (!node)
2142         return info;
2143
2144     info.type = textInputType();
2145     if (info.type == WebTextInputTypeNone)
2146         return info;
2147
2148     info.value = plainText(rangeOfContents(node).get());
2149
2150     if (info.value.isEmpty())
2151         return info;
2152
2153     size_t location;
2154     size_t length;
2155     RefPtr<Range> range = selection->selection().firstRange();
2156     if (range && TextIterator::getLocationAndLengthFromRange(selection->rootEditableElement(), range.get(), location, length)) {
2157         info.selectionStart = location;
2158         info.selectionEnd = location + length;
2159     }
2160     range = editor->compositionRange();
2161     if (range && TextIterator::getLocationAndLengthFromRange(selection->rootEditableElement(), range.get(), location, length)) {
2162         info.compositionStart = location;
2163         info.compositionEnd = location + length;
2164     }
2165
2166     return info;
2167 }
2168
2169 WebTextInputType WebViewImpl::textInputType()
2170 {
2171     Node* node = focusedWebCoreNode();
2172     if (!node)
2173         return WebTextInputTypeNone;
2174
2175     if (node->hasTagName(HTMLNames::inputTag)) {
2176         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
2177
2178         if (input->readOnly() || input->disabled())
2179             return WebTextInputTypeNone;
2180
2181         if (input->isPasswordField())
2182             return WebTextInputTypePassword;
2183         if (input->isSearchField())
2184             return WebTextInputTypeSearch;
2185         if (input->isEmailField())
2186             return WebTextInputTypeEmail;
2187         if (input->isNumberField())
2188             return WebTextInputTypeNumber;
2189         if (input->isTelephoneField())
2190             return WebTextInputTypeTelephone;
2191         if (input->isURLField())
2192             return WebTextInputTypeURL;
2193         if (input->isDateField())
2194             return WebTextInputTypeDate;
2195         if (input->isDateTimeField())
2196             return WebTextInputTypeDateTime;
2197         if (input->isDateTimeLocalField())
2198             return WebTextInputTypeDateTimeLocal;
2199         if (input->isMonthField())
2200             return WebTextInputTypeMonth;
2201         if (input->isTimeField())
2202             return WebTextInputTypeTime;
2203         if (input->isWeekField())
2204             return WebTextInputTypeWeek;
2205         if (input->isTextField())
2206             return WebTextInputTypeText;
2207
2208         return WebTextInputTypeNone;
2209     }
2210
2211     if (node->hasTagName(HTMLNames::textareaTag)) {
2212         HTMLTextAreaElement* textarea = static_cast<HTMLTextAreaElement*>(node);
2213
2214         if (textarea->readOnly() || textarea->disabled())
2215             return WebTextInputTypeNone;
2216
2217         return WebTextInputTypeTextArea;
2218     }
2219
2220     if (node->shouldUseInputMethod())
2221         return WebTextInputTypeContentEditable;
2222
2223     return WebTextInputTypeNone;
2224 }
2225
2226 bool WebViewImpl::selectionBounds(WebRect& start, WebRect& end) const
2227 {
2228     const Frame* frame = focusedWebCoreFrame();
2229     if (!frame)
2230         return false;
2231     FrameSelection* selection = frame->selection();
2232     if (!selection)
2233         return false;
2234
2235     if (selection->isCaret()) {
2236         start = end = frame->view()->contentsToWindow(selection->absoluteCaretBounds());
2237         return true;
2238     }
2239
2240     RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
2241     if (!selectedRange)
2242         return false;
2243
2244     RefPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
2245                                       selectedRange->startContainer(),
2246                                       selectedRange->startOffset(),
2247                                       selectedRange->startContainer(),
2248                                       selectedRange->startOffset()));
2249     start = frame->editor()->firstRectForRange(range.get());
2250
2251     range = Range::create(selectedRange->endContainer()->document(),
2252                           selectedRange->endContainer(),
2253                           selectedRange->endOffset(),
2254                           selectedRange->endContainer(),
2255                           selectedRange->endOffset());
2256     end = frame->editor()->firstRectForRange(range.get());
2257
2258     start = frame->view()->contentsToWindow(start);
2259     end = frame->view()->contentsToWindow(end);
2260
2261     if (!frame->selection()->selection().isBaseFirst())
2262         std::swap(start, end);
2263     return true;
2264 }
2265
2266 bool WebViewImpl::selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const
2267 {
2268     const Frame* frame = focusedWebCoreFrame();
2269     if (!frame)
2270         return false;
2271     FrameSelection* selection = frame->selection();
2272     if (!selection)
2273         return false;
2274     if (!selection->toNormalizedRange())
2275         return false;
2276     start = selection->start().primaryDirection() == RTL ? WebTextDirectionRightToLeft : WebTextDirectionLeftToRight;
2277     end = selection->end().primaryDirection() == RTL ? WebTextDirectionRightToLeft : WebTextDirectionLeftToRight;
2278     return true;
2279 }
2280
2281 bool WebViewImpl::setEditableSelectionOffsets(int start, int end)
2282 {
2283     const Frame* focused = focusedWebCoreFrame();
2284     if (!focused)
2285         return false;
2286
2287     Editor* editor = focused->editor();
2288     if (!editor || !editor->canEdit())
2289         return false;
2290
2291     return editor->setSelectionOffsets(start, end);
2292 }
2293
2294 bool WebViewImpl::setCompositionFromExistingText(int compositionStart, int compositionEnd, const WebVector<WebCompositionUnderline>& underlines)
2295 {
2296     const Frame* focused = focusedWebCoreFrame();
2297     if (!focused)
2298         return false;
2299
2300     Editor* editor = focused->editor();
2301     if (!editor || !editor->canEdit())
2302         return false;
2303
2304     editor->cancelComposition();
2305
2306     if (compositionStart == compositionEnd)
2307         return true;
2308
2309     size_t location;
2310     size_t length;
2311     caretOrSelectionRange(&location, &length);
2312     editor->setIgnoreCompositionSelectionChange(true);
2313     editor->setSelectionOffsets(compositionStart, compositionEnd);
2314     String text = editor->selectedText();
2315     focused->document()->execCommand("delete", true);
2316     editor->setComposition(text, CompositionUnderlineVectorBuilder(underlines), 0, 0);
2317     editor->setSelectionOffsets(location, location + length);
2318     editor->setIgnoreCompositionSelectionChange(false);
2319
2320     return true;
2321 }
2322
2323 void WebViewImpl::extendSelectionAndDelete(int before, int after)
2324 {
2325     const Frame* focused = focusedWebCoreFrame();
2326     if (!focused)
2327         return;
2328
2329     Editor* editor = focused->editor();
2330     if (!editor || !editor->canEdit())
2331         return;
2332
2333     FrameSelection* selection = focused->selection();
2334     if (!selection)
2335         return;
2336
2337     size_t location;
2338     size_t length;
2339     RefPtr<Range> range = selection->selection().firstRange();
2340     if (range && TextIterator::getLocationAndLengthFromRange(selection->rootEditableElement(), range.get(), location, length)) {
2341         editor->setSelectionOffsets(max(static_cast<int>(location) - before, 0), location + length + after);
2342         focused->document()->execCommand("delete", true);
2343     }
2344 }
2345
2346 bool WebViewImpl::isSelectionEditable() const
2347 {
2348     const Frame* frame = focusedWebCoreFrame();
2349     if (!frame)
2350         return false;
2351     return frame->selection()->isContentEditable();
2352 }
2353
2354 WebColor WebViewImpl::backgroundColor() const
2355 {
2356     if (!m_page)
2357         return Color::white;
2358     FrameView* view = m_page->mainFrame()->view();
2359     Color backgroundColor = view->documentBackgroundColor();
2360     if (!backgroundColor.isValid())
2361         return Color::white;
2362     return backgroundColor.rgb();
2363 }
2364
2365 bool WebViewImpl::caretOrSelectionRange(size_t* location, size_t* length)
2366 {
2367     const Frame* focused = focusedWebCoreFrame();
2368     if (!focused)
2369         return false;
2370
2371     FrameSelection* selection = focused->selection();
2372     if (!selection)
2373         return false;
2374
2375     RefPtr<Range> range = selection->selection().firstRange();
2376     if (!range)
2377         return false;
2378
2379     if (TextIterator::getLocationAndLengthFromRange(selection->rootEditableElementOrDocumentElement(), range.get(), *location, *length))
2380         return true;
2381     return false;
2382 }
2383
2384 void WebViewImpl::setTextDirection(WebTextDirection direction)
2385 {
2386     // The Editor::setBaseWritingDirection() function checks if we can change
2387     // the text direction of the selected node and updates its DOM "dir"
2388     // attribute and its CSS "direction" property.
2389     // So, we just call the function as Safari does.
2390     const Frame* focused = focusedWebCoreFrame();
2391     if (!focused)
2392         return;
2393
2394     Editor* editor = focused->editor();
2395     if (!editor || !editor->canEdit())
2396         return;
2397
2398     switch (direction) {
2399     case WebTextDirectionDefault:
2400         editor->setBaseWritingDirection(NaturalWritingDirection);
2401         break;
2402
2403     case WebTextDirectionLeftToRight:
2404         editor->setBaseWritingDirection(LeftToRightWritingDirection);
2405         break;
2406
2407     case WebTextDirectionRightToLeft:
2408         editor->setBaseWritingDirection(RightToLeftWritingDirection);
2409         break;
2410
2411     default:
2412         notImplemented();
2413         break;
2414     }
2415 }
2416
2417 bool WebViewImpl::isAcceleratedCompositingActive() const
2418 {
2419 #if USE(ACCELERATED_COMPOSITING)
2420     return m_isAcceleratedCompositingActive;
2421 #else
2422     return false;
2423 #endif
2424 }
2425
2426 void WebViewImpl::didAcquirePointerLock()
2427 {
2428 #if ENABLE(POINTER_LOCK)
2429     if (page())
2430         page()->pointerLockController()->didAcquirePointerLock();
2431 #endif
2432 }
2433
2434 void WebViewImpl::didNotAcquirePointerLock()
2435 {
2436 #if ENABLE(POINTER_LOCK)
2437     if (page())
2438         page()->pointerLockController()->didNotAcquirePointerLock();
2439 #endif
2440 }
2441
2442 void WebViewImpl::didLosePointerLock()
2443 {
2444 #if ENABLE(POINTER_LOCK)
2445     if (page())
2446         page()->pointerLockController()->didLosePointerLock();
2447 #endif
2448 }
2449
2450 void WebViewImpl::didChangeWindowResizerRect()
2451 {
2452     if (mainFrameImpl()->frameView())
2453         mainFrameImpl()->frameView()->windowResizerRectChanged();
2454 }
2455
2456 // WebView --------------------------------------------------------------------
2457
2458 WebSettingsImpl* WebViewImpl::settingsImpl()
2459 {
2460     if (!m_webSettings)
2461         m_webSettings = adoptPtr(new WebSettingsImpl(m_page->settings()));
2462     ASSERT(m_webSettings);
2463     return m_webSettings.get();
2464 }
2465
2466 WebSettings* WebViewImpl::settings()
2467 {
2468     return settingsImpl();
2469 }
2470
2471 WebString WebViewImpl::pageEncoding() const
2472 {
2473     if (!m_page)
2474         return WebString();
2475
2476     // FIXME: Is this check needed?
2477     if (!m_page->mainFrame()->document()->loader())
2478         return WebString();
2479
2480     return m_page->mainFrame()->document()->encoding();
2481 }
2482
2483 void WebViewImpl::setPageEncoding(const WebString& encodingName)
2484 {
2485     if (!m_page)
2486         return;
2487
2488     // Only change override encoding, don't change default encoding.
2489     // Note that the new encoding must be 0 if it isn't supposed to be set.
2490     String newEncodingName;
2491     if (!encodingName.isEmpty())
2492         newEncodingName = encodingName;
2493     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(newEncodingName);
2494 }
2495
2496 bool WebViewImpl::dispatchBeforeUnloadEvent()
2497 {
2498     // FIXME: This should really cause a recursive depth-first walk of all
2499     // frames in the tree, calling each frame's onbeforeunload.  At the moment,
2500     // we're consistent with Safari 3.1, not IE/FF.
2501     Frame* frame = m_page->mainFrame();
2502     if (!frame)
2503         return true;
2504
2505     return frame->loader()->shouldClose();
2506 }
2507
2508 void WebViewImpl::dispatchUnloadEvent()
2509 {
2510     // Run unload handlers.
2511     m_page->mainFrame()->loader()->closeURL();
2512 }
2513
2514 WebFrame* WebViewImpl::mainFrame()
2515 {
2516     return mainFrameImpl();
2517 }
2518
2519 WebFrame* WebViewImpl::findFrameByName(
2520     const WebString& name, WebFrame* relativeToFrame)
2521 {
2522     if (!relativeToFrame)
2523         relativeToFrame = mainFrame();
2524     Frame* frame = static_cast<WebFrameImpl*>(relativeToFrame)->frame();
2525     frame = frame->tree()->find(name);
2526     return WebFrameImpl::fromFrame(frame);
2527 }
2528
2529 WebFrame* WebViewImpl::focusedFrame()
2530 {
2531     return WebFrameImpl::fromFrame(focusedWebCoreFrame());
2532 }
2533
2534 void WebViewImpl::setFocusedFrame(WebFrame* frame)
2535 {
2536     if (!frame) {
2537         // Clears the focused frame if any.
2538         Frame* frame = focusedWebCoreFrame();
2539         if (frame)
2540             frame->selection()->setFocused(false);
2541         return;
2542     }
2543     WebFrameImpl* frameImpl = static_cast<WebFrameImpl*>(frame);
2544     Frame* webcoreFrame = frameImpl->frame();
2545     webcoreFrame->page()->focusController()->setFocusedFrame(webcoreFrame);
2546 }
2547
2548 void WebViewImpl::setInitialFocus(bool reverse)
2549 {
2550     if (!m_page)
2551         return;
2552
2553     // Since we don't have a keyboard event, we'll create one.
2554     WebKeyboardEvent keyboardEvent;
2555     keyboardEvent.type = WebInputEvent::RawKeyDown;
2556     if (reverse)
2557         keyboardEvent.modifiers = WebInputEvent::ShiftKey;
2558
2559     // VK_TAB which is only defined on Windows.
2560     keyboardEvent.windowsKeyCode = 0x09;
2561     PlatformKeyboardEventBuilder platformEvent(keyboardEvent);
2562     RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
2563
2564     Frame* frame = page()->focusController()->focusedOrMainFrame();
2565     if (Document* document = frame->document())
2566         document->setFocusedNode(0);
2567     page()->focusController()->setInitialFocus(
2568         reverse ? FocusDirectionBackward : FocusDirectionForward,
2569         webkitEvent.get());
2570 }
2571
2572 void WebViewImpl::clearFocusedNode()
2573 {
2574     RefPtr<Frame> frame = focusedWebCoreFrame();
2575     if (!frame)
2576         return;
2577
2578     RefPtr<Document> document = frame->document();
2579     if (!document)
2580         return;
2581
2582     RefPtr<Node> oldFocusedNode = document->focusedNode();
2583
2584     // Clear the focused node.
2585     document->setFocusedNode(0);
2586
2587     if (!oldFocusedNode)
2588         return;
2589
2590     // If a text field has focus, we need to make sure the selection controller
2591     // knows to remove selection from it. Otherwise, the text field is still
2592     // processing keyboard events even though focus has been moved to the page and
2593     // keystrokes get eaten as a result.
2594     if (oldFocusedNode->isContentEditable()
2595         || (oldFocusedNode->isElementNode()
2596             && static_cast<Element*>(oldFocusedNode.get())->isTextFormControl())) {
2597         frame->selection()->clear();
2598     }
2599 }
2600
2601 void WebViewImpl::scrollFocusedNodeIntoView()
2602 {
2603     Node* focusedNode = focusedWebCoreNode();
2604     if (focusedNode && focusedNode->isElementNode()) {
2605         Element* elementNode = static_cast<Element*>(focusedNode);
2606         elementNode->scrollIntoViewIfNeeded(true);
2607     }
2608 }
2609
2610 void WebViewImpl::scrollFocusedNodeIntoRect(const WebRect& rect)
2611 {
2612     Frame* frame = page()->mainFrame();
2613     Node* focusedNode = focusedWebCoreNode();
2614     if (!frame || !frame->view() || !focusedNode || !focusedNode->isElementNode())
2615         return;
2616     Element* elementNode = static_cast<Element*>(focusedNode);
2617     frame->view()->scrollElementToRect(elementNode, IntRect(rect.x, rect.y, rect.width, rect.height));
2618 }
2619
2620 void WebViewImpl::advanceFocus(bool reverse)
2621 {
2622     page()->focusController()->advanceFocus(reverse ? FocusDirectionBackward : FocusDirectionForward, 0);
2623 }
2624
2625 double WebViewImpl::zoomLevel()
2626 {
2627     return m_zoomLevel;
2628 }
2629
2630 double WebViewImpl::setZoomLevel(bool textOnly, double zoomLevel)
2631 {
2632     if (zoomLevel < m_minimumZoomLevel)
2633         m_zoomLevel = m_minimumZoomLevel;
2634     else if (zoomLevel > m_maximumZoomLevel)
2635         m_zoomLevel = m_maximumZoomLevel;
2636     else
2637         m_zoomLevel = zoomLevel;
2638
2639     Frame* frame = mainFrameImpl()->frame();
2640     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
2641     if (pluginContainer)
2642         pluginContainer->plugin()->setZoomLevel(m_zoomLevel, textOnly);
2643     else {
2644         float zoomFactor = static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel));
2645         if (textOnly)
2646             frame->setPageAndTextZoomFactors(1, zoomFactor * m_emulatedTextZoomFactor);
2647         else
2648             frame->setPageAndTextZoomFactors(zoomFactor, m_emulatedTextZoomFactor);
2649     }
2650     return m_zoomLevel;
2651 }
2652
2653 void WebViewImpl::zoomLimitsChanged(double minimumZoomLevel,
2654                                     double maximumZoomLevel)
2655 {
2656     m_minimumZoomLevel = minimumZoomLevel;
2657     m_maximumZoomLevel = maximumZoomLevel;
2658     m_client->zoomLimitsChanged(m_minimumZoomLevel, m_maximumZoomLevel);
2659 }
2660
2661 void WebViewImpl::fullFramePluginZoomLevelChanged(double zoomLevel)
2662 {
2663     if (zoomLevel == m_zoomLevel)
2664         return;
2665
2666     m_zoomLevel = max(min(zoomLevel, m_maximumZoomLevel), m_minimumZoomLevel);
2667     m_client->zoomLevelChanged();
2668 }
2669
2670 double WebView::zoomLevelToZoomFactor(double zoomLevel)
2671 {
2672     return pow(textSizeMultiplierRatio, zoomLevel);
2673 }
2674
2675 double WebView::zoomFactorToZoomLevel(double factor)
2676 {
2677     // Since factor = 1.2^level, level = log(factor) / log(1.2)
2678     return log(factor) / log(textSizeMultiplierRatio);
2679 }
2680
2681 float WebViewImpl::pageScaleFactor() const
2682 {
2683     if (!page())
2684         return 1;
2685
2686     return page()->pageScaleFactor();
2687 }
2688
2689 bool WebViewImpl::isPageScaleFactorSet() const
2690 {
2691     return m_pageScaleFactorIsSet;
2692 }
2693
2694 float WebViewImpl::clampPageScaleFactorToLimits(float scaleFactor)
2695 {
2696     return min(max(scaleFactor, m_minimumPageScaleFactor), m_maximumPageScaleFactor);
2697 }
2698
2699 WebPoint WebViewImpl::clampOffsetAtScale(const WebPoint& offset, float scale)
2700 {
2701     // This is the scaled content size. We need to convert it to the new scale factor.
2702     WebSize contentSize = mainFrame()->contentsSize();
2703     float deltaScale = scale / pageScaleFactor();
2704     int docWidthAtNewScale = contentSize.width * deltaScale;
2705     int docHeightAtNewScale = contentSize.height * deltaScale;
2706     int viewWidth = m_size.width;
2707     int viewHeight = m_size.height;
2708
2709     // Enforce the maximum and minimum scroll positions at the new scale.
2710     IntPoint clampedOffset = offset;
2711     clampedOffset = clampedOffset.shrunkTo(IntPoint(docWidthAtNewScale - viewWidth, docHeightAtNewScale - viewHeight));
2712     clampedOffset.clampNegativeToZero();
2713     return clampedOffset;
2714 }
2715
2716 void WebViewImpl::setPageScaleFactorPreservingScrollOffset(float scaleFactor)
2717 {
2718     // Pick a scale factor that is within the expected limits
2719     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
2720
2721     IntPoint scrollOffsetAtNewScale(mainFrame()->scrollOffset().width, mainFrame()->scrollOffset().height);
2722     float deltaScale = scaleFactor / pageScaleFactor();
2723     scrollOffsetAtNewScale.scale(deltaScale, deltaScale);
2724
2725     WebPoint clampedOffsetAtNewScale = clampOffsetAtScale(scrollOffsetAtNewScale, scaleFactor);
2726     setPageScaleFactor(scaleFactor, clampedOffsetAtNewScale);
2727 }
2728
2729 void WebViewImpl::setPageScaleFactor(float scaleFactor, const WebPoint& origin)
2730 {
2731     if (!page())
2732         return;
2733
2734     if (!scaleFactor)
2735         scaleFactor = 1;
2736
2737     if (m_deviceScaleInCompositor != 1) {
2738         // Don't allow page scaling when compositor scaling is being used,
2739         // as they are currently incompatible.
2740         ASSERT(scaleFactor == 1);
2741     }
2742
2743     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
2744     WebPoint clampedOrigin = clampOffsetAtScale(origin, scaleFactor);
2745     page()->setPageScaleFactor(scaleFactor, clampedOrigin);
2746     m_pageScaleFactorIsSet = true;
2747 }
2748
2749 float WebViewImpl::deviceScaleFactor() const
2750 {
2751     if (!page())
2752         return 1;
2753
2754     return page()->deviceScaleFactor();
2755 }
2756
2757 void WebViewImpl::setDeviceScaleFactor(float scaleFactor)
2758 {
2759     if (!page())
2760         return;
2761
2762     page()->setDeviceScaleFactor(scaleFactor);
2763
2764     if (!m_layerTreeView.isNull() && m_webSettings->applyDefaultDeviceScaleFactorInCompositor()) {
2765         m_deviceScaleInCompositor = page()->deviceScaleFactor();
2766         m_layerTreeView.setDeviceScaleFactor(m_deviceScaleInCompositor);
2767     }
2768     if (m_deviceScaleInCompositor != 1) {
2769         // Don't allow page scaling when compositor scaling is being used,
2770         // as they are currently incompatible. This means the deviceScale
2771         // needs to match the one in the compositor.
2772         ASSERT(scaleFactor == m_deviceScaleInCompositor);
2773     }
2774 }
2775
2776 bool WebViewImpl::isFixedLayoutModeEnabled() const
2777 {
2778     if (!page())
2779         return false;
2780
2781     Frame* frame = page()->mainFrame();
2782     if (!frame || !frame->view())
2783         return false;
2784
2785     return frame->view()->useFixedLayout();
2786 }
2787
2788 void WebViewImpl::enableFixedLayoutMode(bool enable)
2789 {
2790     if (!page())
2791         return;
2792
2793     Frame* frame = page()->mainFrame();
2794     if (!frame || !frame->view())
2795         return;
2796
2797     frame->view()->setUseFixedLayout(enable);
2798
2799 #if USE(ACCELERATED_COMPOSITING)
2800     // Also notify the base layer, which RenderLayerCompositor does not see.
2801     if (m_nonCompositedContentHost)
2802         updateLayerTreeViewport();
2803 #endif
2804 }
2805
2806
2807 void WebViewImpl::enableAutoResizeMode(const WebSize& minSize, const WebSize& maxSize)
2808 {
2809     m_shouldAutoResize = true;
2810     m_minAutoSize = minSize;
2811     m_maxAutoSize = maxSize;
2812     configureAutoResizeMode();
2813 }
2814
2815 void WebViewImpl::disableAutoResizeMode()
2816 {
2817     m_shouldAutoResize = false;
2818     configureAutoResizeMode();
2819 }
2820
2821 void WebViewImpl::setPageScaleFactorLimits(float minPageScale, float maxPageScale)
2822 {
2823     m_pageDefinedMinimumPageScaleFactor = minPageScale;
2824     m_pageDefinedMaximumPageScaleFactor = maxPageScale;
2825     computePageScaleFactorLimits();
2826 }
2827
2828 void WebViewImpl::setIgnoreViewportTagMaximumScale(bool flag)
2829 {
2830     m_ignoreViewportTagMaximumScale = flag;
2831
2832     if (!page() || !page()->mainFrame())
2833         return;
2834
2835     m_page->chrome()->client()->dispatchViewportPropertiesDidChange(page()->mainFrame()->document()->viewportArguments());
2836 }
2837
2838 bool WebViewImpl::computePageScaleFactorLimits()
2839 {
2840     if (m_pageDefinedMinimumPageScaleFactor == -1 || m_pageDefinedMaximumPageScaleFactor == -1)
2841         return false;
2842
2843     if (!mainFrame() || !page() || !page()->mainFrame() || !page()->mainFrame()->view())
2844         return false;
2845
2846     m_minimumPageScaleFactor = min(max(m_pageDefinedMinimumPageScaleFactor, minPageScaleFactor), maxPageScaleFactor) * (deviceScaleFactor() / m_deviceScaleInCompositor);
2847     m_maximumPageScaleFactor = max(min(m_pageDefinedMaximumPageScaleFactor, maxPageScaleFactor), minPageScaleFactor) * (deviceScaleFactor() / m_deviceScaleInCompositor);
2848
2849     int viewWidthNotIncludingScrollbars = page()->mainFrame()->view()->visibleContentRect(false).width();
2850     int contentsWidth = mainFrame()->contentsSize().width;
2851     if (viewWidthNotIncludingScrollbars && contentsWidth) {
2852         // Limit page scaling down to the document width.
2853         int unscaledContentWidth = contentsWidth / pageScaleFactor();
2854         m_minimumPageScaleFactor = max(m_minimumPageScaleFactor, static_cast<float>(viewWidthNotIncludingScrollbars) / unscaledContentWidth);
2855         m_maximumPageScaleFactor = max(m_minimumPageScaleFactor, m_maximumPageScaleFactor);
2856     }
2857     ASSERT(m_minimumPageScaleFactor <= m_maximumPageScaleFactor);
2858
2859     float clampedScale = clampPageScaleFactorToLimits(pageScaleFactor());
2860 #if USE(ACCELERATED_COMPOSITING)
2861     if (!m_layerTreeView.isNull())
2862         m_layerTreeView.setPageScaleFactorAndLimits(clampedScale, m_minimumPageScaleFactor, m_maximumPageScaleFactor);
2863 #endif
2864     if (clampedScale != pageScaleFactor()) {
2865         setPageScaleFactorPreservingScrollOffset(clampedScale);
2866         return true;
2867     }
2868
2869     return false;
2870 }
2871
2872 float WebViewImpl::minimumPageScaleFactor() const
2873 {
2874     return m_minimumPageScaleFactor;
2875 }
2876
2877 float WebViewImpl::maximumPageScaleFactor() const
2878 {
2879     return m_maximumPageScaleFactor;
2880 }
2881
2882 void WebViewImpl::saveScrollAndScaleState()
2883 {
2884     m_savedPageScaleFactor = pageScaleFactor();
2885     m_savedScrollOffset = mainFrame()->scrollOffset();
2886 }
2887
2888 void WebViewImpl::restoreScrollAndScaleState()
2889 {
2890     if (!m_savedPageScaleFactor)
2891         return;
2892
2893 #if ENABLE(GESTURE_EVENTS)
2894     startPageScaleAnimation(IntPoint(m_savedScrollOffset), false, m_savedPageScaleFactor, scrollAndScaleAnimationDurationInSeconds);
2895 #else
2896     setPageScaleFactor(m_savedPageScaleFactor, WebPoint());
2897     mainFrame()->setScrollOffset(m_savedScrollOffset);
2898 #endif
2899
2900     resetSavedScrollAndScaleState();
2901 }
2902
2903 void WebViewImpl::resetSavedScrollAndScaleState()
2904 {
2905     m_savedPageScaleFactor = 0;
2906     m_savedScrollOffset = IntSize();
2907 }
2908
2909 WebSize WebViewImpl::fixedLayoutSize() const
2910 {
2911     if (!page())
2912         return WebSize();
2913
2914     Frame* frame = page()->mainFrame();
2915     if (!frame || !frame->view())
2916         return WebSize();
2917
2918     return frame->view()->fixedLayoutSize();
2919 }
2920
2921 void WebViewImpl::setFixedLayoutSize(const WebSize& layoutSize)
2922 {
2923     if (!page())
2924         return;
2925
2926     Frame* frame = page()->mainFrame();
2927     if (!frame || !frame->view())
2928         return;
2929
2930     frame->view()->setFixedLayoutSize(layoutSize);
2931 }
2932
2933 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
2934                                            const WebPoint& location)
2935 {
2936     HitTestResult result = hitTestResultForWindowPos(location);
2937     RefPtr<Node> node = result.innerNonSharedNode();
2938     if (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))
2939         return;
2940
2941     RefPtr<HTMLMediaElement> mediaElement =
2942         static_pointer_cast<HTMLMediaElement>(node);
2943     switch (action.type) {
2944     case WebMediaPlayerAction::Play:
2945         if (action.enable)
2946             mediaElement->play();
2947         else
2948             mediaElement->pause();
2949         break;
2950     case WebMediaPlayerAction::Mute:
2951         mediaElement->setMuted(action.enable);
2952         break;
2953     case WebMediaPlayerAction::Loop:
2954         mediaElement->setLoop(action.enable);
2955         break;
2956     case WebMediaPlayerAction::Controls:
2957         mediaElement->setControls(action.enable);
2958         break;
2959     default:
2960         ASSERT_NOT_REACHED();
2961     }
2962 }
2963
2964 void WebViewImpl::performPluginAction(const WebPluginAction& action,
2965                                       const WebPoint& location)
2966 {
2967     HitTestResult result = hitTestResultForWindowPos(location);
2968     RefPtr<Node> node = result.innerNonSharedNode();
2969     if (!node->hasTagName(HTMLNames::objectTag) && !node->hasTagName(HTMLNames::embedTag))
2970         return;
2971
2972     RenderObject* object = node->renderer();
2973     if (object && object->isWidget()) {
2974         Widget* widget = toRenderWidget(object)->widget();
2975         if (widget && widget->isPluginContainer()) {
2976             WebPluginContainerImpl* plugin = static_cast<WebPluginContainerImpl*>(widget);
2977             switch (action.type) {
2978             case WebPluginAction::Rotate90Clockwise:
2979                 plugin->plugin()->rotateView(WebPlugin::RotationType90Clockwise);
2980                 break;
2981             case WebPluginAction::Rotate90Counterclockwise:
2982                 plugin->plugin()->rotateView(WebPlugin::RotationType90Counterclockwise);
2983                 break;
2984             default:
2985                 ASSERT_NOT_REACHED();
2986             }
2987         }
2988     }
2989 }
2990
2991 void WebViewImpl::copyImageAt(const WebPoint& point)
2992 {
2993     if (!m_page)
2994         return;
2995
2996     HitTestResult result = hitTestResultForWindowPos(point);
2997
2998     if (result.absoluteImageURL().isEmpty()) {
2999         // There isn't actually an image at these coordinates.  Might be because
3000         // the window scrolled while the context menu was open or because the page
3001         // changed itself between when we thought there was an image here and when
3002         // we actually tried to retreive the image.
3003         //
3004         // FIXME: implement a cache of the most recent HitTestResult to avoid having
3005         //        to do two hit tests.
3006         return;
3007     }
3008
3009     m_page->mainFrame()->editor()->copyImage(result);
3010 }
3011
3012 void WebViewImpl::dragSourceEndedAt(
3013     const WebPoint& clientPoint,
3014     const WebPoint& screenPoint,
3015     WebDragOperation operation)
3016 {
3017     PlatformMouseEvent pme(clientPoint,
3018                            screenPoint,
3019                            LeftButton, PlatformEvent::MouseMoved, 0, false, false, false,
3020                            false, 0);
3021     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(pme,
3022         static_cast<DragOperation>(operation));
3023     m_dragScrollTimer->stop();
3024 }
3025
3026 void WebViewImpl::dragSourceMovedTo(
3027     const WebPoint& clientPoint,
3028     const WebPoint& screenPoint,
3029     WebDragOperation operation)
3030 {
3031     m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
3032 }
3033
3034 void WebViewImpl::dragSourceSystemDragEnded()
3035 {
3036     // It's possible for us to get this callback while not doing a drag if
3037     // it's from a previous page that got unloaded.
3038     if (m_doingDragAndDrop) {
3039         m_page->dragController()->dragEnded();
3040         m_doingDragAndDrop = false;
3041     }
3042 }
3043
3044 WebDragOperation WebViewImpl::dragTargetDragEnter(
3045     const WebDragData& webDragData,
3046     const WebPoint& clientPoint,
3047     const WebPoint& screenPoint,
3048     WebDragOperationsMask operationsAllowed,
3049     int keyModifiers)
3050 {
3051     ASSERT(!m_currentDragData);
3052
3053     m_currentDragData = webDragData;
3054     m_operationsAllowed = operationsAllowed;
3055
3056     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragEnter, keyModifiers);
3057 }
3058
3059 WebDragOperation WebViewImpl::dragTargetDragOver(
3060     const WebPoint& clientPoint,
3061     const WebPoint& screenPoint,
3062     WebDragOperationsMask operationsAllowed,
3063     int keyModifiers)
3064 {
3065     m_operationsAllowed = operationsAllowed;
3066
3067     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragOver, keyModifiers);
3068 }
3069
3070 void WebViewImpl::dragTargetDragLeave()
3071 {
3072     ASSERT(m_currentDragData);
3073
3074     DragData dragData(
3075         m_currentDragData.get(),
3076         IntPoint(),
3077         IntPoint(),
3078         static_cast<DragOperation>(m_operationsAllowed));
3079
3080     m_page->dragController()->dragExited(&dragData);
3081
3082     // FIXME: why is the drag scroll timer not stopped here?
3083
3084     m_dragOperation = WebDragOperationNone;
3085     m_currentDragData = 0;
3086 }
3087
3088 void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
3089                                  const WebPoint& screenPoint,
3090                                  int keyModifiers)
3091 {
3092     ASSERT(m_currentDragData);
3093
3094     // If this webview transitions from the "drop accepting" state to the "not
3095     // accepting" state, then our IPC message reply indicating that may be in-
3096     // flight, or else delayed by javascript processing in this webview.  If a
3097     // drop happens before our IPC reply has reached the browser process, then
3098     // the browser forwards the drop to this webview.  So only allow a drop to
3099     // proceed if our webview m_dragOperation state is not DragOperationNone.
3100
3101     if (m_dragOperation == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop.
3102         dragTargetDragLeave();
3103         return;
3104     }
3105
3106     m_currentDragData->setModifierKeyState(webInputEventKeyStateToPlatformEventKeyState(keyModifiers));
3107     DragData dragData(
3108         m_currentDragData.get(),
3109         clientPoint,
3110         screenPoint,
3111         static_cast<DragOperation>(m_operationsAllowed));
3112
3113     m_page->dragController()->performDrag(&dragData);
3114
3115     m_dragOperation = WebDragOperationNone;
3116     m_currentDragData = 0;
3117
3118     m_dragScrollTimer->stop();
3119 }
3120
3121 WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPoint, const WebPoint& screenPoint, DragAction dragAction, int keyModifiers)
3122 {
3123     ASSERT(m_currentDragData);
3124
3125     m_currentDragData->setModifierKeyState(webInputEventKeyStateToPlatformEventKeyState(keyModifiers));
3126     DragData dragData(
3127         m_currentDragData.get(),
3128         clientPoint,
3129         screenPoint,
3130         static_cast<DragOperation>(m_operationsAllowed));
3131
3132     DragSession dragSession;
3133     if (dragAction == DragEnter)
3134         dragSession = m_page->dragController()->dragEntered(&dragData);
3135     else
3136         dragSession = m_page->dragController()->dragUpdated(&dragData);
3137
3138     DragOperation dropEffect = dragSession.operation;
3139
3140     // Mask the drop effect operation against the drag source's allowed operations.
3141     if (!(dropEffect & dragData.draggingSourceOperationMask()))
3142         dropEffect = DragOperationNone;
3143
3144      m_dragOperation = static_cast<WebDragOperation>(dropEffect);
3145
3146     if (dragAction == DragOver)
3147         m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
3148     else
3149         m_dragScrollTimer->stop();
3150
3151     return m_dragOperation;
3152 }
3153
3154 void WebViewImpl::sendResizeEventAndRepaint()
3155 {
3156     if (mainFrameImpl()->frameView()) {
3157         // Enqueues the resize event.
3158         mainFrameImpl()->frame()->eventHandler()->sendResizeEvent();
3159     }
3160
3161     if (m_client) {
3162         if (isAcceleratedCompositingActive()) {
3163 #if USE(ACCELERATED_COMPOSITING)
3164             updateLayerTreeViewport();
3165 #endif
3166         } else {
3167             WebRect damagedRect(0, 0, m_size.width, m_size.height);
3168             m_client->didInvalidateRect(damagedRect);
3169         }
3170     }
3171 }
3172
3173 void WebViewImpl::configureAutoResizeMode()
3174 {
3175     if (!mainFrameImpl() || !mainFrameImpl()->frame() || !mainFrameImpl()->frame()->view())
3176         return;
3177
3178     mainFrameImpl()->frame()->view()->enableAutoSizeMode(m_shouldAutoResize, m_minAutoSize, m_maxAutoSize);
3179 }
3180
3181 unsigned long WebViewImpl::createUniqueIdentifierForRequest()
3182 {
3183     if (m_page)
3184         return m_page->progress()->createUniqueIdentifier();
3185     return 0;
3186 }
3187
3188 void WebViewImpl::inspectElementAt(const WebPoint& point)
3189 {
3190     if (!m_page)
3191         return;
3192
3193     if (point.x == -1 || point.y == -1)
3194         m_page->inspectorController()->inspect(0);
3195     else {
3196         HitTestResult result = hitTestResultForWindowPos(point);
3197
3198         if (!result.innerNonSharedNode())
3199             return;
3200
3201         m_page->inspectorController()->inspect(result.innerNonSharedNode());
3202     }
3203 }
3204
3205 WebString WebViewImpl::inspectorSettings() const
3206 {
3207     return m_inspectorSettings;
3208 }
3209
3210 void WebViewImpl::setInspectorSettings(const WebString& settings)
3211 {
3212     m_inspectorSettings = settings;
3213 }
3214
3215 bool WebViewImpl::inspectorSetting(const WebString& key, WebString* value) const
3216 {
3217     if (!m_inspectorSettingsMap->contains(key))
3218         return false;
3219     *value = m_inspectorSettingsMap->get(key);
3220     return true;
3221 }
3222
3223 void WebViewImpl::setInspectorSetting(const WebString& key,
3224                                       const WebString& value)
3225 {
3226     m_inspectorSettingsMap->set(key, value);
3227     client()->didUpdateInspectorSetting(key, value);
3228 }
3229
3230 WebDevToolsAgent* WebViewImpl::devToolsAgent()
3231 {
3232     return m_devToolsAgent.get();
3233 }
3234
3235 WebAccessibilityObject WebViewImpl::accessibilityObject()
3236 {
3237     if (!mainFrameImpl())
3238         return WebAccessibilityObject();
3239
3240     Document* document = mainFrameImpl()->frame()->document();
3241     return WebAccessibilityObject(
3242         document->axObjectCache()->getOrCreate(document->renderer()));
3243 }
3244
3245 void WebViewImpl::applyAutofillSuggestions(
3246     const WebNode& node,
3247     const WebVector<WebString>& names,
3248     const WebVector<WebString>& labels,
3249     const WebVector<WebString>& icons,
3250     const WebVector<int>& itemIDs,
3251     int separatorIndex)
3252 {
3253     ASSERT(names.size() == labels.size());
3254     ASSERT(names.size() == itemIDs.size());
3255
3256     if (names.isEmpty()) {
3257         hideAutofillPopup();
3258         return;
3259     }
3260
3261     RefPtr<Node> focusedNode = focusedWebCoreNode();
3262     // If the node for which we queried the Autofill suggestions is not the
3263     // focused node, then we have nothing to do.  FIXME: also check the
3264     // caret is at the end and that the text has not changed.
3265     if (!focusedNode || focusedNode != PassRefPtr<Node>(node)) {
3266         hideAutofillPopup();
3267         return;
3268     }
3269
3270     HTMLInputElement* inputElem = focusedNode->toInputElement();
3271     ASSERT(inputElem);
3272
3273     // The first time the Autofill popup is shown we'll create the client and
3274     // the popup.
3275     if (!m_autofillPopupClient)
3276         m_autofillPopupClient = adoptPtr(new AutofillPopupMenuClient);
3277
3278     m_autofillPopupClient->initialize(
3279         inputElem, names, labels, icons, itemIDs, separatorIndex);
3280
3281     if (!m_autofillPopup) {
3282         PopupContainerSettings popupSettings = autofillPopupSettings;
3283         popupSettings.deviceSupportsTouch = settingsImpl()->deviceSupportsTouch();
3284         m_autofillPopup = PopupContainer::create(m_autofillPopupClient.get(),
3285                                                  PopupContainer::Suggestion,
3286                                                  popupSettings);
3287     }
3288
3289     if (m_autofillPopupShowing) {
3290         refreshAutofillPopup();
3291     } else {
3292         m_autofillPopupShowing = true;
3293         m_autofillPopup->showInRect(focusedNode->getPixelSnappedRect(), focusedNode->ownerDocument()->view(), 0);
3294     }
3295 }
3296
3297 void WebViewImpl::hidePopups()
3298 {
3299     hideSelectPopup();
3300     hideAutofillPopup();
3301 #if ENABLE(PAGE_POPUP)
3302     if (m_pagePopup)
3303         closePagePopup(m_pagePopup.get());
3304 #endif
3305 }
3306
3307 void WebViewImpl::performCustomContextMenuAction(unsigned action)
3308 {
3309     if (!m_page)
3310         return;
3311     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
3312     if (!menu)
3313         return;
3314     ContextMenuItem* item = menu->itemWithAction(static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + action));
3315     if (item)
3316         m_page->contextMenuController()->contextMenuItemSelected(item);
3317     m_page->contextMenuController()->clearContextMenu();
3318 }
3319
3320 // WebView --------------------------------------------------------------------
3321
3322 void WebViewImpl::setIsTransparent(bool isTransparent)
3323 {
3324     // Set any existing frames to be transparent.
3325     Frame* frame = m_page->mainFrame();
3326     while (frame) {
3327         frame->view()->setTransparent(isTransparent);
3328         frame = frame->tree()->traverseNext();
3329     }
3330
3331     // Future frames check this to know whether to be transparent.
3332     m_isTransparent = isTransparent;
3333
3334     if (m_nonCompositedContentHost)
3335         m_nonCompositedContentHost->setOpaque(!isTransparent);
3336
3337     if (!m_layerTreeView.isNull())
3338         m_layerTreeView.setHasTransparentBackground(isTransparent);
3339 }
3340
3341 bool WebViewImpl::isTransparent() const
3342 {
3343     return m_isTransparent;
3344 }
3345
3346 void WebViewImpl::setIsActive(bool active)
3347 {
3348     if (page() && page()->focusController())
3349         page()->focusController()->setActive(active);
3350 }
3351
3352 bool WebViewImpl::isActive() const
3353 {
3354     return (page() && page()->focusController()) ? page()->focusController()->isActive() : false;
3355 }
3356
3357 void WebViewImpl::setDomainRelaxationForbidden(bool forbidden, const WebString& scheme)
3358 {
3359     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme));
3360 }
3361
3362 void WebViewImpl::setScrollbarColors(unsigned inactiveColor,
3363                                      unsigned activeColor,
3364                                      unsigned trackColor) {
3365 #if OS(UNIX) && !OS(DARWIN) && !OS(ANDROID)
3366     PlatformThemeChromiumLinux::setScrollbarColors(inactiveColor, activeColor, trackColor);
3367 #endif
3368 }
3369
3370 void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor,
3371                                      unsigned activeForegroundColor,
3372                                      unsigned inactiveBackgroundColor,
3373                                      unsigned inactiveForegroundColor) {
3374 #if OS(UNIX) && !OS(DARWIN) && !OS(ANDROID)
3375     RenderThemeChromiumLinux::setSelectionColors(activeBackgroundColor,
3376                                                  activeForegroundColor,
3377                                                  inactiveBackgroundColor,
3378                                                  inactiveForegroundColor);
3379     theme()->platformColorsDidChange();
3380 #endif
3381 }
3382
3383 void WebView::addUserScript(const WebString& sourceCode,
3384                             const WebVector<WebString>& patternsIn,
3385                             WebView::UserScriptInjectAt injectAt,
3386                             WebView::UserContentInjectIn injectIn)
3387 {
3388     OwnPtr<Vector<String> > patterns = adoptPtr(new Vector<String>);
3389     for (size_t i = 0; i < patternsIn.size(); ++i)
3390         patterns->append(patternsIn[i]);
3391
3392     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
3393     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::create());
3394     pageGroup->addUserScriptToWorld(world.get(), sourceCode, WebURL(), patterns.release(), nullptr,
3395                                     static_cast<UserScriptInjectionTime>(injectAt),
3396                                     static_cast<UserContentInjectedFrames>(injectIn));
3397 }
3398
3399 void WebView::addUserStyleSheet(const WebString& sourceCode,
3400                                 const WebVector<WebString>& patternsIn,
3401                                 WebView::UserContentInjectIn injectIn,
3402                                 WebView::UserStyleInjectionTime injectionTime)
3403 {
3404     OwnPtr<Vector<String> > patterns = adoptPtr(new Vector<String>);
3405     for (size_t i = 0; i < patternsIn.size(); ++i)
3406         patterns->append(patternsIn[i]);
3407
3408     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
3409     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::create());
3410
3411     // FIXME: Current callers always want the level to be "author". It probably makes sense to let
3412     // callers specify this though, since in other cases the caller will probably want "user" level.
3413     //
3414     // FIXME: It would be nice to populate the URL correctly, instead of passing an empty URL.
3415     pageGroup->addUserStyleSheetToWorld(world.get(), sourceCode, WebURL(), patterns.release(), nullptr,
3416                                         static_cast<UserContentInjectedFrames>(injectIn),
3417                                         UserStyleAuthorLevel,
3418                                         static_cast<WebCore::UserStyleInjectionTime>(injectionTime));
3419 }
3420
3421 void WebView::removeAllUserContent()
3422 {
3423     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
3424     pageGroup->removeAllUserContent();
3425 }
3426
3427 void WebViewImpl::didCommitLoad(bool* isNewNavigation, bool isNavigationWithinPage)
3428 {
3429     if (isNewNavigation)
3430         *isNewNavigation = m_observedNewNavigation;
3431
3432 #ifndef NDEBUG
3433     ASSERT(!m_observedNewNavigation
3434         || m_page->mainFrame()->loader()->documentLoader() == m_newNavigationLoader);
3435     m_newNavigationLoader = 0;
3436 #endif
3437     m_observedNewNavigation = false;
3438     if (*isNewNavigation && !isNavigationWithinPage)
3439         m_pageScaleFactorIsSet = false;
3440
3441     m_gestureAnimation.clear();
3442     resetSavedScrollAndScaleState();
3443 }
3444
3445 void WebViewImpl::layoutUpdated(WebFrameImpl* webframe)
3446 {
3447     if (!m_client || webframe != mainFrameImpl())
3448         return;
3449
3450     if (m_shouldAutoResize && mainFrameImpl()->frame() && mainFrameImpl()->frame()->view()) {
3451         WebSize frameSize = mainFrameImpl()->frame()->view()->frameRect().size();
3452         if (frameSize != m_size) {
3453             m_size = frameSize;
3454             m_client->didAutoResize(m_size);
3455             sendResizeEventAndRepaint();
3456         }
3457     }
3458
3459     m_client->didUpdateLayout();
3460 }
3461
3462 void WebViewImpl::didChangeContentsSize()
3463 {
3464 #if ENABLE(VIEWPORT)
3465     if (!settings()->viewportEnabled())
3466         return;
3467
3468     bool didChangeScale = false;
3469     if (!isPageScaleFactorSet()) {
3470         // If the viewport tag failed to be processed earlier, we need
3471         // to recompute it now.
3472         ViewportArguments viewportArguments = mainFrameImpl()->frame()->document()->viewportArguments();
3473         m_page->chrome()->client()->dispatchViewportPropertiesDidChange(viewportArguments);
3474         didChangeScale = true;
3475     } else
3476         didChangeScale = computePageScaleFactorLimits();
3477
3478     if (!didChangeScale)
3479         return;
3480
3481     if (!mainFrameImpl())
3482         return;
3483
3484     FrameView* view = mainFrameImpl()->frameView();
3485     if (view && view->needsLayout())
3486         view->layout();
3487 #endif
3488 }
3489
3490 bool WebViewImpl::useExternalPopupMenus()
3491 {
3492     return shouldUseExternalPopupMenus;
3493 }
3494
3495 void WebViewImpl::setEmulatedTextZoomFactor(float textZoomFactor)
3496 {
3497     m_emulatedTextZoomFactor = textZoomFactor;
3498