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