Home | History | Annotate | Download | only in web
      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 "web/WebViewImpl.h"
     33 
     34 #include "core/CSSValueKeywords.h"
     35 #include "core/HTMLNames.h"
     36 #include "core/InputTypeNames.h"
     37 #include "core/accessibility/AXObjectCache.h"
     38 #include "core/clipboard/DataObject.h"
     39 #include "core/dom/Document.h"
     40 #include "core/dom/DocumentMarkerController.h"
     41 #include "core/dom/NodeRenderingTraversal.h"
     42 #include "core/dom/Text.h"
     43 #include "core/editing/Editor.h"
     44 #include "core/editing/FrameSelection.h"
     45 #include "core/editing/HTMLInterchange.h"
     46 #include "core/editing/InputMethodController.h"
     47 #include "core/editing/TextIterator.h"
     48 #include "core/editing/markup.h"
     49 #include "core/events/KeyboardEvent.h"
     50 #include "core/events/WheelEvent.h"
     51 #include "core/frame/EventHandlerRegistry.h"
     52 #include "core/frame/FrameHost.h"
     53 #include "core/frame/FrameView.h"
     54 #include "core/frame/LocalFrame.h"
     55 #include "core/frame/PinchViewport.h"
     56 #include "core/frame/RemoteFrame.h"
     57 #include "core/frame/Settings.h"
     58 #include "core/frame/SmartClip.h"
     59 #include "core/html/HTMLInputElement.h"
     60 #include "core/html/HTMLMediaElement.h"
     61 #include "core/html/HTMLPlugInElement.h"
     62 #include "core/html/HTMLTextAreaElement.h"
     63 #include "core/html/ime/InputMethodContext.h"
     64 #include "core/inspector/InspectorController.h"
     65 #include "core/loader/DocumentLoader.h"
     66 #include "core/loader/FrameLoader.h"
     67 #include "core/loader/UniqueIdentifier.h"
     68 #include "core/page/Chrome.h"
     69 #include "core/page/ContextMenuController.h"
     70 #include "core/page/ContextMenuProvider.h"
     71 #include "core/page/DragController.h"
     72 #include "core/page/DragData.h"
     73 #include "core/page/DragSession.h"
     74 #include "core/page/EventHandler.h"
     75 #include "core/page/FocusController.h"
     76 #include "core/page/FrameTree.h"
     77 #include "core/page/InjectedStyleSheets.h"
     78 #include "core/page/Page.h"
     79 #include "core/page/PagePopupClient.h"
     80 #include "core/page/PointerLockController.h"
     81 #include "core/page/ScopedPageLoadDeferrer.h"
     82 #include "core/page/TouchDisambiguation.h"
     83 #include "core/rendering/RenderView.h"
     84 #include "core/rendering/RenderWidget.h"
     85 #include "core/rendering/TextAutosizer.h"
     86 #include "core/rendering/compositing/RenderLayerCompositor.h"
     87 #include "modules/credentialmanager/CredentialManagerClient.h"
     88 #include "modules/device_orientation/DeviceOrientationInspectorAgent.h"
     89 #include "modules/encryptedmedia/MediaKeysController.h"
     90 #include "modules/filesystem/InspectorFileSystemAgent.h"
     91 #include "modules/indexeddb/InspectorIndexedDBAgent.h"
     92 #include "modules/push_messaging/PushController.h"
     93 #include "platform/ContextMenu.h"
     94 #include "platform/ContextMenuItem.h"
     95 #include "platform/Cursor.h"
     96 #include "platform/KeyboardCodes.h"
     97 #include "platform/Logging.h"
     98 #include "platform/NotImplemented.h"
     99 #include "platform/OverscrollTheme.h"
    100 #include "platform/PlatformGestureEvent.h"
    101 #include "platform/PlatformKeyboardEvent.h"
    102 #include "platform/PlatformMouseEvent.h"
    103 #include "platform/PlatformWheelEvent.h"
    104 #include "platform/PopupMenuClient.h"
    105 #include "platform/RuntimeEnabledFeatures.h"
    106 #include "platform/TraceEvent.h"
    107 #include "platform/UserGestureIndicator.h"
    108 #include "platform/exported/WebActiveGestureAnimation.h"
    109 #include "platform/fonts/FontCache.h"
    110 #include "platform/graphics/Color.h"
    111 #include "platform/graphics/FirstPaintInvalidationTracking.h"
    112 #include "platform/graphics/Image.h"
    113 #include "platform/graphics/ImageBuffer.h"
    114 #include "platform/scheduler/Scheduler.h"
    115 #include "platform/scroll/ScrollbarTheme.h"
    116 #include "platform/weborigin/SchemeRegistry.h"
    117 #include "public/platform/Platform.h"
    118 #include "public/platform/WebCompositeAndReadbackAsyncCallback.h"
    119 #include "public/platform/WebDragData.h"
    120 #include "public/platform/WebFloatPoint.h"
    121 #include "public/platform/WebGestureCurve.h"
    122 #include "public/platform/WebImage.h"
    123 #include "public/platform/WebLayerTreeView.h"
    124 #include "public/platform/WebURLRequest.h"
    125 #include "public/platform/WebVector.h"
    126 #include "public/web/WebAXObject.h"
    127 #include "public/web/WebActiveWheelFlingParameters.h"
    128 #include "public/web/WebAutofillClient.h"
    129 #include "public/web/WebBeginFrameArgs.h"
    130 #include "public/web/WebFrameClient.h"
    131 #include "public/web/WebHitTestResult.h"
    132 #include "public/web/WebInputElement.h"
    133 #include "public/web/WebMediaPlayerAction.h"
    134 #include "public/web/WebNode.h"
    135 #include "public/web/WebPlugin.h"
    136 #include "public/web/WebPluginAction.h"
    137 #include "public/web/WebRange.h"
    138 #include "public/web/WebTextInputInfo.h"
    139 #include "public/web/WebViewClient.h"
    140 #include "public/web/WebWindowFeatures.h"
    141 #include "web/CompositionUnderlineVectorBuilder.h"
    142 #include "web/ContextFeaturesClientImpl.h"
    143 #include "web/DatabaseClientImpl.h"
    144 #include "web/FullscreenController.h"
    145 #include "web/GraphicsLayerFactoryChromium.h"
    146 #include "web/LinkHighlight.h"
    147 #include "web/NavigatorContentUtilsClientImpl.h"
    148 #include "web/PopupContainer.h"
    149 #include "web/PrerendererClientImpl.h"
    150 #include "web/SpeechRecognitionClientProxy.h"
    151 #include "web/StorageQuotaClientImpl.h"
    152 #include "web/ValidationMessageClientImpl.h"
    153 #include "web/ViewportAnchor.h"
    154 #include "web/WebDevToolsAgentImpl.h"
    155 #include "web/WebDevToolsAgentPrivate.h"
    156 #include "web/WebInputEventConversion.h"
    157 #include "web/WebLocalFrameImpl.h"
    158 #include "web/WebPagePopupImpl.h"
    159 #include "web/WebPluginContainerImpl.h"
    160 #include "web/WebPopupMenuImpl.h"
    161 #include "web/WebRemoteFrameImpl.h"
    162 #include "web/WebSettingsImpl.h"
    163 #include "web/WorkerGlobalScopeProxyProviderImpl.h"
    164 #include "web/painting/ContinuousPainter.h"
    165 #include "wtf/CurrentTime.h"
    166 #include "wtf/RefPtr.h"
    167 #include "wtf/TemporaryChange.h"
    168 
    169 #if USE(DEFAULT_RENDER_THEME)
    170 #include "core/rendering/RenderThemeChromiumDefault.h"
    171 #endif
    172 
    173 // Get rid of WTF's pow define so we can use std::pow.
    174 #undef pow
    175 #include <cmath> // for std::pow
    176 
    177 // The following constants control parameters for automated scaling of webpages
    178 // (such as due to a double tap gesture or find in page etc.). These are
    179 // experimentally determined.
    180 static const int touchPointPadding = 32;
    181 static const int nonUserInitiatedPointPadding = 11;
    182 static const float minScaleDifference = 0.01f;
    183 static const float doubleTapZoomContentDefaultMargin = 5;
    184 static const float doubleTapZoomContentMinimumMargin = 2;
    185 static const double doubleTapZoomAnimationDurationInSeconds = 0.25;
    186 static const float doubleTapZoomAlreadyLegibleRatio = 1.2f;
    187 
    188 static const double multipleTargetsZoomAnimationDurationInSeconds = 0.25;
    189 static const double findInPageAnimationDurationInSeconds = 0;
    190 
    191 // Constants for viewport anchoring on resize.
    192 static const float viewportAnchorXCoord = 0.5f;
    193 static const float viewportAnchorYCoord = 0;
    194 
    195 // Constants for zooming in on a focused text field.
    196 static const double scrollAndScaleAnimationDurationInSeconds = 0.2;
    197 static const int minReadableCaretHeight = 18;
    198 static const float minScaleChangeToTriggerZoom = 1.05f;
    199 static const float leftBoxRatio = 0.3f;
    200 static const int caretPadding = 10;
    201 
    202 namespace blink {
    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 
    212 // Used to defer all page activity in cases where the embedder wishes to run
    213 // a nested event loop. Using a stack enables nesting of message loop invocations.
    214 static WillBeHeapVector<RawPtrWillBeMember<ScopedPageLoadDeferrer> >& pageLoadDeferrerStack()
    215 {
    216     DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WillBeHeapVector<RawPtrWillBeMember<ScopedPageLoadDeferrer> > >, deferrerStack, (adoptPtrWillBeNoop(new WillBeHeapVector<RawPtrWillBeMember<ScopedPageLoadDeferrer> > ())));
    217     return *deferrerStack;
    218 }
    219 
    220 // Ensure that the WebDragOperation enum values stay in sync with the original
    221 // DragOperation constants.
    222 #define COMPILE_ASSERT_MATCHING_ENUM(coreName) \
    223     COMPILE_ASSERT(int(coreName) == int(Web##coreName), dummy##coreName)
    224 COMPILE_ASSERT_MATCHING_ENUM(DragOperationNone);
    225 COMPILE_ASSERT_MATCHING_ENUM(DragOperationCopy);
    226 COMPILE_ASSERT_MATCHING_ENUM(DragOperationLink);
    227 COMPILE_ASSERT_MATCHING_ENUM(DragOperationGeneric);
    228 COMPILE_ASSERT_MATCHING_ENUM(DragOperationPrivate);
    229 COMPILE_ASSERT_MATCHING_ENUM(DragOperationMove);
    230 COMPILE_ASSERT_MATCHING_ENUM(DragOperationDelete);
    231 COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery);
    232 
    233 static bool shouldUseExternalPopupMenus = false;
    234 
    235 static int webInputEventKeyStateToPlatformEventKeyState(int webInputEventKeyState)
    236 {
    237     int platformEventKeyState = 0;
    238     if (webInputEventKeyState & WebInputEvent::ShiftKey)
    239         platformEventKeyState = platformEventKeyState | PlatformEvent::ShiftKey;
    240     if (webInputEventKeyState & WebInputEvent::ControlKey)
    241         platformEventKeyState = platformEventKeyState | PlatformEvent::CtrlKey;
    242     if (webInputEventKeyState & WebInputEvent::AltKey)
    243         platformEventKeyState = platformEventKeyState | PlatformEvent::AltKey;
    244     if (webInputEventKeyState & WebInputEvent::MetaKey)
    245         platformEventKeyState = platformEventKeyState | PlatformEvent::MetaKey;
    246     return platformEventKeyState;
    247 }
    248 
    249 namespace {
    250 
    251 class UserGestureNotifier {
    252 public:
    253     // If a UserGestureIndicator is created for a user gesture since the last
    254     // page load and *userGestureObserved is false, the UserGestureNotifier
    255     // will notify the client and set *userGestureObserved to true.
    256     UserGestureNotifier(WebAutofillClient*, bool* userGestureObserved);
    257     ~UserGestureNotifier();
    258 
    259 private:
    260     WebAutofillClient* const m_client;
    261     bool* const m_userGestureObserved;
    262 };
    263 
    264 UserGestureNotifier::UserGestureNotifier(WebAutofillClient* client, bool* userGestureObserved)
    265     : m_client(client)
    266     , m_userGestureObserved(userGestureObserved)
    267 {
    268     ASSERT(m_userGestureObserved);
    269 }
    270 
    271 UserGestureNotifier::~UserGestureNotifier()
    272 {
    273     if (!*m_userGestureObserved && UserGestureIndicator::processedUserGestureSinceLoad()) {
    274         *m_userGestureObserved = true;
    275         if (m_client)
    276             m_client->firstUserGestureObserved();
    277     }
    278 }
    279 
    280 } // namespace
    281 
    282 // WebView ----------------------------------------------------------------
    283 
    284 WebView* WebView::create(WebViewClient* client)
    285 {
    286     // Pass the WebViewImpl's self-reference to the caller.
    287     return WebViewImpl::create(client);
    288 }
    289 
    290 WebViewImpl* WebViewImpl::create(WebViewClient* client)
    291 {
    292     // Pass the WebViewImpl's self-reference to the caller.
    293     return adoptRef(new WebViewImpl(client)).leakRef();
    294 }
    295 
    296 void WebView::setUseExternalPopupMenus(bool useExternalPopupMenus)
    297 {
    298     shouldUseExternalPopupMenus = useExternalPopupMenus;
    299 }
    300 
    301 void WebView::updateVisitedLinkState(unsigned long long linkHash)
    302 {
    303     Page::visitedStateChanged(linkHash);
    304 }
    305 
    306 void WebView::resetVisitedLinkState()
    307 {
    308     Page::allVisitedStateChanged();
    309 }
    310 
    311 void WebView::willEnterModalLoop()
    312 {
    313     pageLoadDeferrerStack().append(new ScopedPageLoadDeferrer());
    314 }
    315 
    316 void WebView::didExitModalLoop()
    317 {
    318     ASSERT(pageLoadDeferrerStack().size());
    319 
    320     ScopedPageLoadDeferrer* deferrer = pageLoadDeferrerStack().last();
    321 #if ENABLE(OILPAN)
    322     deferrer->dispose();
    323 #else
    324     delete deferrer;
    325 #endif
    326     pageLoadDeferrerStack().removeLast();
    327 }
    328 
    329 void WebViewImpl::setMainFrame(WebFrame* frame)
    330 {
    331     if (frame->isWebLocalFrame())
    332         toWebLocalFrameImpl(frame)->initializeCoreFrame(&page()->frameHost(), 0, nullAtom, nullAtom);
    333     else
    334         toWebRemoteFrameImpl(frame)->initializeCoreFrame(&page()->frameHost(), 0, nullAtom);
    335 }
    336 
    337 void WebViewImpl::setAutofillClient(WebAutofillClient* autofillClient)
    338 {
    339     m_autofillClient = autofillClient;
    340 }
    341 
    342 void WebViewImpl::setCredentialManagerClient(WebCredentialManagerClient* webCredentialManagerClient)
    343 {
    344     ASSERT(m_page);
    345     provideCredentialManagerClientTo(*m_page, new CredentialManagerClient(webCredentialManagerClient));
    346 }
    347 
    348 void WebViewImpl::setDevToolsAgentClient(WebDevToolsAgentClient* devToolsClient)
    349 {
    350     if (devToolsClient)
    351         m_devToolsAgent = adoptPtr(new WebDevToolsAgentImpl(this, devToolsClient));
    352     else
    353         m_devToolsAgent.clear();
    354 }
    355 
    356 void WebViewImpl::setPrerendererClient(WebPrerendererClient* prerendererClient)
    357 {
    358     ASSERT(m_page);
    359     providePrerendererClientTo(*m_page, new PrerendererClientImpl(prerendererClient));
    360 }
    361 
    362 void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient)
    363 {
    364     m_spellCheckClient = spellCheckClient;
    365 }
    366 
    367 WebViewImpl::WebViewImpl(WebViewClient* client)
    368     : m_client(client)
    369     , m_autofillClient(0)
    370     , m_spellCheckClient(0)
    371     , m_chromeClientImpl(this)
    372     , m_contextMenuClientImpl(this)
    373     , m_dragClientImpl(this)
    374     , m_editorClientImpl(this)
    375     , m_inspectorClientImpl(this)
    376     , m_backForwardClientImpl(this)
    377     , m_spellCheckerClientImpl(this)
    378     , m_storageClientImpl(this)
    379     , m_shouldAutoResize(false)
    380     , m_zoomLevel(0)
    381     , m_minimumZoomLevel(zoomFactorToZoomLevel(minTextSizeMultiplier))
    382     , m_maximumZoomLevel(zoomFactorToZoomLevel(maxTextSizeMultiplier))
    383     , m_doubleTapZoomPageScaleFactor(0)
    384     , m_doubleTapZoomPending(false)
    385     , m_enableFakePageScaleAnimationForTesting(false)
    386     , m_fakePageScaleAnimationPageScaleFactor(0)
    387     , m_fakePageScaleAnimationUseAnchor(false)
    388     , m_contextMenuAllowed(false)
    389     , m_doingDragAndDrop(false)
    390     , m_ignoreInputEvents(false)
    391     , m_compositorDeviceScaleFactorOverride(0)
    392     , m_rootLayerScale(1)
    393     , m_suppressNextKeypressEvent(false)
    394     , m_imeAcceptEvents(true)
    395     , m_operationsAllowed(WebDragOperationNone)
    396     , m_dragOperation(WebDragOperationNone)
    397     , m_isTransparent(false)
    398     , m_tabsToLinks(false)
    399     , m_layerTreeView(0)
    400     , m_rootLayer(0)
    401     , m_rootGraphicsLayer(0)
    402     , m_rootTransformLayer(0)
    403     , m_graphicsLayerFactory(adoptPtr(new GraphicsLayerFactoryChromium(this)))
    404     , m_isAcceleratedCompositingActive(false)
    405     , m_layerTreeViewCommitsDeferred(false)
    406     , m_layerTreeViewClosed(false)
    407     , m_matchesHeuristicsForGpuRasterization(false)
    408     , m_recreatingGraphicsContext(false)
    409     , m_flingModifier(0)
    410     , m_flingSourceDevice(false)
    411     , m_fullscreenController(FullscreenController::create(this))
    412     , m_showFPSCounter(false)
    413     , m_showPaintRects(false)
    414     , m_showDebugBorders(false)
    415     , m_continuousPaintingEnabled(false)
    416     , m_showScrollBottleneckRects(false)
    417     , m_baseBackgroundColor(Color::white)
    418     , m_backgroundColorOverride(Color::transparent)
    419     , m_zoomFactorOverride(0)
    420     , m_userGestureObserved(false)
    421     , m_topControlsContentOffset(0)
    422     , m_topControlsLayoutHeight(0)
    423 {
    424     Page::PageClients pageClients;
    425     pageClients.chromeClient = &m_chromeClientImpl;
    426     pageClients.contextMenuClient = &m_contextMenuClientImpl;
    427     pageClients.editorClient = &m_editorClientImpl;
    428     pageClients.dragClient = &m_dragClientImpl;
    429     pageClients.inspectorClient = &m_inspectorClientImpl;
    430     pageClients.backForwardClient = &m_backForwardClientImpl;
    431     pageClients.spellCheckerClient = &m_spellCheckerClientImpl;
    432     pageClients.storageClient = &m_storageClientImpl;
    433 
    434     m_page = adoptPtrWillBeNoop(new Page(pageClients));
    435     MediaKeysController::provideMediaKeysTo(*m_page, &m_mediaKeysClientImpl);
    436     provideSpeechRecognitionTo(*m_page, SpeechRecognitionClientProxy::create(client ? client->speechRecognizer() : 0));
    437     provideNavigatorContentUtilsTo(*m_page, NavigatorContentUtilsClientImpl::create(this));
    438 
    439     provideContextFeaturesTo(*m_page, ContextFeaturesClientImpl::create());
    440     DeviceOrientationInspectorAgent::provideTo(*m_page);
    441 
    442     m_page->inspectorController().registerModuleAgent(InspectorFileSystemAgent::create(m_page.get()));
    443     provideDatabaseClientTo(*m_page, DatabaseClientImpl::create());
    444     InspectorIndexedDBAgent::provideTo(m_page.get());
    445     provideStorageQuotaClientTo(*m_page, StorageQuotaClientImpl::create());
    446     m_page->setValidationMessageClient(ValidationMessageClientImpl::create(*this));
    447     provideWorkerGlobalScopeProxyProviderTo(*m_page, WorkerGlobalScopeProxyProviderImpl::create());
    448 
    449     m_page->makeOrdinary();
    450 
    451     if (m_client) {
    452         providePushControllerTo(*m_page, m_client->webPushClient());
    453         setDeviceScaleFactor(m_client->screenInfo().deviceScaleFactor);
    454         setVisibilityState(m_client->visibilityState(), true);
    455     }
    456 
    457     initializeLayerTreeView();
    458 }
    459 
    460 WebViewImpl::~WebViewImpl()
    461 {
    462     ASSERT(!m_page);
    463 }
    464 
    465 WebLocalFrameImpl* WebViewImpl::mainFrameImpl()
    466 {
    467     return m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() ? WebLocalFrameImpl::fromFrame(m_page->deprecatedLocalMainFrame()) : 0;
    468 }
    469 
    470 bool WebViewImpl::tabKeyCyclesThroughElements() const
    471 {
    472     ASSERT(m_page);
    473     return m_page->tabKeyCyclesThroughElements();
    474 }
    475 
    476 void WebViewImpl::setTabKeyCyclesThroughElements(bool value)
    477 {
    478     if (m_page)
    479         m_page->setTabKeyCyclesThroughElements(value);
    480 }
    481 
    482 void WebViewImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseEvent& event)
    483 {
    484     m_client->setMouseOverURL(WebURL());
    485     PageWidgetEventHandler::handleMouseLeave(mainFrame, event);
    486 }
    487 
    488 void WebViewImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEvent& event)
    489 {
    490     // If there is a popup open, close it as the user is clicking on the page (outside of the
    491     // popup). We also save it so we can prevent a click on an element from immediately
    492     // reopening the same popup.
    493     RefPtr<PopupContainer> selectPopup;
    494     RefPtr<WebPagePopupImpl> pagePopup;
    495     if (event.button == WebMouseEvent::ButtonLeft) {
    496         selectPopup = m_selectPopup;
    497         pagePopup = m_pagePopup;
    498         hidePopups();
    499         ASSERT(!m_selectPopup);
    500         ASSERT(!m_pagePopup);
    501     }
    502 
    503     m_lastMouseDownPoint = WebPoint(event.x, event.y);
    504 
    505     // Take capture on a mouse down on a plugin so we can send it mouse events.
    506     // If the hit node is a plugin but a scrollbar is over it don't start mouse
    507     // capture because it will interfere with the scrollbar receiving events.
    508     IntPoint point(event.x, event.y);
    509     if (event.button == WebMouseEvent::ButtonLeft && m_page->mainFrame()->isLocalFrame()) {
    510         point = m_page->deprecatedLocalMainFrame()->view()->windowToContents(point);
    511         HitTestResult result(m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(point));
    512         result.setToShadowHostIfInUserAgentShadowRoot();
    513         Node* hitNode = result.innerNonSharedNode();
    514 
    515         if (!result.scrollbar() && hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject()) {
    516             m_mouseCaptureNode = hitNode;
    517             TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
    518         }
    519     }
    520 
    521     PageWidgetEventHandler::handleMouseDown(mainFrame, event);
    522 
    523     if (event.button == WebMouseEvent::ButtonLeft && m_mouseCaptureNode)
    524         m_mouseCaptureGestureToken = mainFrame.eventHandler().takeLastMouseDownGestureToken();
    525 
    526     if (m_selectPopup && m_selectPopup == selectPopup) {
    527         // That click triggered a select popup which is the same as the one that
    528         // was showing before the click.  It means the user clicked the select
    529         // while the popup was showing, and as a result we first closed then
    530         // immediately reopened the select popup.  It needs to be closed.
    531         hideSelectPopup();
    532     }
    533 
    534     if (m_pagePopup && pagePopup && m_pagePopup->hasSamePopupClient(pagePopup.get())) {
    535         // That click triggered a page popup that is the same as the one we just closed.
    536         // It needs to be closed.
    537         closePagePopup(m_pagePopup.get());
    538     }
    539 
    540     // Dispatch the contextmenu event regardless of if the click was swallowed.
    541 #if OS(WIN)
    542     // On Windows, we handle it on mouse up, not down.
    543 #elif OS(MACOSX)
    544     if (event.button == WebMouseEvent::ButtonRight
    545         || (event.button == WebMouseEvent::ButtonLeft
    546             && event.modifiers & WebMouseEvent::ControlKey))
    547         mouseContextMenu(event);
    548 #else
    549     if (event.button == WebMouseEvent::ButtonRight)
    550         mouseContextMenu(event);
    551 #endif
    552 }
    553 
    554 void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
    555 {
    556     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    557         return;
    558 
    559     m_page->contextMenuController().clearContextMenu();
    560 
    561     PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), event);
    562 
    563     // Find the right target frame. See issue 1186900.
    564     HitTestResult result = hitTestResultForWindowPos(pme.position());
    565     Frame* targetFrame;
    566     if (result.innerNonSharedNode())
    567         targetFrame = result.innerNonSharedNode()->document().frame();
    568     else
    569         targetFrame = m_page->focusController().focusedOrMainFrame();
    570 
    571     if (!targetFrame->isLocalFrame())
    572         return;
    573 
    574     LocalFrame* targetLocalFrame = toLocalFrame(targetFrame);
    575 
    576 #if OS(WIN)
    577     targetLocalFrame->view()->setCursor(pointerCursor());
    578 #endif
    579 
    580     m_contextMenuAllowed = true;
    581     targetLocalFrame->eventHandler().sendContextMenuEvent(pme);
    582     m_contextMenuAllowed = false;
    583     // Actually showing the context menu is handled by the ContextMenuClient
    584     // implementation...
    585 }
    586 
    587 void WebViewImpl::handleMouseUp(LocalFrame& mainFrame, const WebMouseEvent& event)
    588 {
    589     PageWidgetEventHandler::handleMouseUp(mainFrame, event);
    590 
    591 #if OS(WIN)
    592     // Dispatch the contextmenu event regardless of if the click was swallowed.
    593     // On Mac/Linux, we handle it on mouse down, not up.
    594     if (event.button == WebMouseEvent::ButtonRight)
    595         mouseContextMenu(event);
    596 #endif
    597 }
    598 
    599 bool WebViewImpl::handleMouseWheel(LocalFrame& mainFrame, const WebMouseWheelEvent& event)
    600 {
    601     hidePopups();
    602     return PageWidgetEventHandler::handleMouseWheel(mainFrame, event);
    603 }
    604 
    605 bool WebViewImpl::scrollBy(const WebFloatSize& delta, const WebFloatSize& velocity)
    606 {
    607     if (m_flingSourceDevice == WebGestureDeviceTouchpad) {
    608         WebMouseWheelEvent syntheticWheel;
    609         const float tickDivisor = WheelEvent::TickMultiplier;
    610 
    611         syntheticWheel.deltaX = delta.width;
    612         syntheticWheel.deltaY = delta.height;
    613         syntheticWheel.wheelTicksX = delta.width / tickDivisor;
    614         syntheticWheel.wheelTicksY = delta.height / tickDivisor;
    615         syntheticWheel.hasPreciseScrollingDeltas = true;
    616         syntheticWheel.x = m_positionOnFlingStart.x;
    617         syntheticWheel.y = m_positionOnFlingStart.y;
    618         syntheticWheel.globalX = m_globalPositionOnFlingStart.x;
    619         syntheticWheel.globalY = m_globalPositionOnFlingStart.y;
    620         syntheticWheel.modifiers = m_flingModifier;
    621 
    622         if (m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() && m_page->deprecatedLocalMainFrame()->view())
    623             return handleMouseWheel(*m_page->deprecatedLocalMainFrame(), syntheticWheel);
    624     } else {
    625         WebGestureEvent syntheticGestureEvent;
    626 
    627         syntheticGestureEvent.type = WebInputEvent::GestureScrollUpdateWithoutPropagation;
    628         syntheticGestureEvent.data.scrollUpdate.deltaX = delta.width;
    629         syntheticGestureEvent.data.scrollUpdate.deltaY = delta.height;
    630         syntheticGestureEvent.x = m_positionOnFlingStart.x;
    631         syntheticGestureEvent.y = m_positionOnFlingStart.y;
    632         syntheticGestureEvent.globalX = m_globalPositionOnFlingStart.x;
    633         syntheticGestureEvent.globalY = m_globalPositionOnFlingStart.y;
    634         syntheticGestureEvent.modifiers = m_flingModifier;
    635         syntheticGestureEvent.sourceDevice = WebGestureDeviceTouchscreen;
    636 
    637         if (m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() && m_page->deprecatedLocalMainFrame()->view())
    638             return handleGestureEvent(syntheticGestureEvent);
    639     }
    640     return false;
    641 }
    642 
    643 bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event)
    644 {
    645     bool eventSwallowed = false;
    646     bool eventCancelled = false; // for disambiguation
    647 
    648     // Special handling for slow-path fling gestures.
    649     switch (event.type) {
    650     case WebInputEvent::GestureFlingStart: {
    651         if (mainFrameImpl()->frame()->eventHandler().isScrollbarHandlingGestures())
    652             break;
    653         m_client->cancelScheduledContentIntents();
    654         m_positionOnFlingStart = WebPoint(event.x / pageScaleFactor(), event.y / pageScaleFactor());
    655         m_globalPositionOnFlingStart = WebPoint(event.globalX, event.globalY);
    656         m_flingModifier = event.modifiers;
    657         m_flingSourceDevice = event.sourceDevice;
    658         OwnPtr<WebGestureCurve> flingCurve = adoptPtr(Platform::current()->createFlingAnimationCurve(event.sourceDevice, WebFloatPoint(event.data.flingStart.velocityX, event.data.flingStart.velocityY), WebSize()));
    659         ASSERT(flingCurve);
    660         m_gestureAnimation = WebActiveGestureAnimation::createAtAnimationStart(flingCurve.release(), this);
    661         scheduleAnimation();
    662         eventSwallowed = true;
    663 
    664         m_client->didHandleGestureEvent(event, eventCancelled);
    665         return eventSwallowed;
    666     }
    667     case WebInputEvent::GestureFlingCancel:
    668         if (endActiveFlingAnimation())
    669             eventSwallowed = true;
    670 
    671         m_client->didHandleGestureEvent(event, eventCancelled);
    672         return eventSwallowed;
    673     default:
    674         break;
    675     }
    676 
    677     PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
    678 
    679     // Special handling for double tap and scroll events as we don't want to
    680     // hit test for them.
    681     switch (event.type) {
    682     case WebInputEvent::GestureDoubleTap:
    683         if (m_webSettings->doubleTapToZoomEnabled() && minimumPageScaleFactor() != maximumPageScaleFactor()) {
    684             m_client->cancelScheduledContentIntents();
    685             animateDoubleTapZoom(platformEvent.position());
    686         }
    687         // GestureDoubleTap is currently only used by Android for zooming. For WebCore,
    688         // GestureTap with tap count = 2 is used instead. So we drop GestureDoubleTap here.
    689         eventSwallowed = true;
    690         m_client->didHandleGestureEvent(event, eventCancelled);
    691         return eventSwallowed;
    692     case WebInputEvent::GestureScrollBegin:
    693     case WebInputEvent::GesturePinchBegin:
    694         m_client->cancelScheduledContentIntents();
    695     case WebInputEvent::GestureScrollEnd:
    696     case WebInputEvent::GestureScrollUpdate:
    697     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
    698     case WebInputEvent::GesturePinchEnd:
    699     case WebInputEvent::GesturePinchUpdate:
    700     case WebInputEvent::GestureFlingStart:
    701         // Scrolling-related gesture events invoke EventHandler recursively for each frame down
    702         // the chain, doing a single-frame hit-test per frame. This matches handleWheelEvent.
    703         // Perhaps we could simplify things by rewriting scroll handling to work inner frame
    704         // out, and then unify with other gesture events.
    705         eventSwallowed = mainFrameImpl()->frame()->eventHandler().handleGestureScrollEvent(platformEvent);
    706         m_client->didHandleGestureEvent(event, eventCancelled);
    707         return eventSwallowed;
    708     default:
    709         break;
    710     }
    711 
    712     // Hit test across all frames and do touch adjustment as necessary for the event type.
    713     GestureEventWithHitTestResults targetedEvent =
    714         m_page->deprecatedLocalMainFrame()->eventHandler().targetGestureEvent(platformEvent);
    715 
    716     // Handle link highlighting outside the main switch to avoid getting lost in the
    717     // complicated set of cases handled below.
    718     switch (event.type) {
    719     case WebInputEvent::GestureShowPress:
    720         // Queue a highlight animation, then hand off to regular handler.
    721         enableTapHighlightAtPoint(targetedEvent);
    722         break;
    723     case WebInputEvent::GestureTapCancel:
    724     case WebInputEvent::GestureTap:
    725     case WebInputEvent::GestureLongPress:
    726         for (size_t i = 0; i < m_linkHighlights.size(); ++i)
    727             m_linkHighlights[i]->startHighlightAnimationIfNeeded();
    728         break;
    729     default:
    730         break;
    731     }
    732 
    733     switch (event.type) {
    734     case WebInputEvent::GestureTap: {
    735         m_client->cancelScheduledContentIntents();
    736         // FIXME: Use targeted event here and save another hit test.
    737         // FIXME: Content intent should be generated using same node that was highlighted. crbug.com/416746
    738         if (detectContentOnTouch(platformEvent.position())) {
    739             eventSwallowed = true;
    740             break;
    741         }
    742 
    743         RefPtr<PopupContainer> selectPopup;
    744         selectPopup = m_selectPopup;
    745         hideSelectPopup();
    746         ASSERT(!m_selectPopup);
    747 
    748         // Don't trigger a disambiguation popup on sites designed for mobile devices.
    749         // Instead, assume that the page has been designed with big enough buttons and links.
    750         // Don't trigger a disambiguation popup when screencasting, since it's implemented outside of
    751         // compositor pipeline and is not being screencasted itself. This leads to bad user experience.
    752         if (event.data.tap.width > 0 && !shouldDisableDesktopWorkarounds() && !page()->inspectorController().screencastEnabled()) {
    753             WebGestureEvent scaledEvent = event;
    754             scaledEvent.x = event.x / pageScaleFactor();
    755             scaledEvent.y = event.y / pageScaleFactor();
    756             scaledEvent.data.tap.width = event.data.tap.width / pageScaleFactor();
    757             scaledEvent.data.tap.height = event.data.tap.height / pageScaleFactor();
    758             IntRect boundingBox(
    759                 scaledEvent.x - scaledEvent.data.tap.width / 2,
    760                 scaledEvent.y - scaledEvent.data.tap.height / 2,
    761                 scaledEvent.data.tap.width,
    762                 scaledEvent.data.tap.height);
    763 
    764             WebSize pinchViewportOffset = pinchVirtualViewportEnabled() ?
    765                 flooredIntSize(page()->frameHost().pinchViewport().location()) : IntSize();
    766 
    767             // Keep bounding box relative to the main frame.
    768             boundingBox.move(pinchViewportOffset);
    769 
    770             Vector<IntRect> goodTargets;
    771             WillBeHeapVector<RawPtrWillBeMember<Node> > highlightNodes;
    772             findGoodTouchTargets(boundingBox, mainFrameImpl()->frame(), goodTargets, highlightNodes);
    773             // FIXME: replace touch adjustment code when numberOfGoodTargets == 1?
    774             // Single candidate case is currently handled by: https://bugs.webkit.org/show_bug.cgi?id=85101
    775             if (goodTargets.size() >= 2 && m_client
    776                 && m_client->didTapMultipleTargets(pinchViewportOffset, boundingBox, goodTargets)) {
    777 
    778                 enableTapHighlights(highlightNodes);
    779                 for (size_t i = 0; i < m_linkHighlights.size(); ++i)
    780                     m_linkHighlights[i]->startHighlightAnimationIfNeeded();
    781                 eventSwallowed = true;
    782                 eventCancelled = true;
    783                 break;
    784             }
    785         }
    786 
    787         eventSwallowed = mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent);
    788 
    789         if (m_selectPopup && m_selectPopup == selectPopup) {
    790             // That tap triggered a select popup which is the same as the one that
    791             // was showing before the tap. It means the user tapped the select
    792             // while the popup was showing, and as a result we first closed then
    793             // immediately reopened the select popup. It needs to be closed.
    794             hideSelectPopup();
    795         }
    796 
    797         break;
    798     }
    799     case WebInputEvent::GestureTwoFingerTap:
    800     case WebInputEvent::GestureLongPress:
    801     case WebInputEvent::GestureLongTap: {
    802         if (!mainFrameImpl() || !mainFrameImpl()->frameView())
    803             break;
    804 
    805         m_client->cancelScheduledContentIntents();
    806         m_page->contextMenuController().clearContextMenu();
    807         m_contextMenuAllowed = true;
    808         eventSwallowed = mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent);
    809         m_contextMenuAllowed = false;
    810 
    811         break;
    812     }
    813     case WebInputEvent::GestureShowPress:
    814         m_client->cancelScheduledContentIntents();
    815     case WebInputEvent::GestureTapDown:
    816     case WebInputEvent::GestureTapCancel:
    817     case WebInputEvent::GestureTapUnconfirmed: {
    818         eventSwallowed = mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent);
    819         break;
    820     }
    821     default:
    822         ASSERT_NOT_REACHED();
    823     }
    824     m_client->didHandleGestureEvent(event, eventCancelled);
    825     return eventSwallowed;
    826 }
    827 
    828 void WebViewImpl::transferActiveWheelFlingAnimation(const WebActiveWheelFlingParameters& parameters)
    829 {
    830     TRACE_EVENT0("blink", "WebViewImpl::transferActiveWheelFlingAnimation");
    831     ASSERT(!m_gestureAnimation);
    832     m_positionOnFlingStart = parameters.point;
    833     m_globalPositionOnFlingStart = parameters.globalPoint;
    834     m_flingModifier = parameters.modifiers;
    835     OwnPtr<WebGestureCurve> curve = adoptPtr(Platform::current()->createFlingAnimationCurve(parameters.sourceDevice, WebFloatPoint(parameters.delta), parameters.cumulativeScroll));
    836     ASSERT(curve);
    837     m_gestureAnimation = WebActiveGestureAnimation::createWithTimeOffset(curve.release(), this, parameters.startTime);
    838     scheduleAnimation();
    839 }
    840 
    841 bool WebViewImpl::endActiveFlingAnimation()
    842 {
    843     if (m_gestureAnimation) {
    844         m_gestureAnimation.clear();
    845         if (m_layerTreeView)
    846             m_layerTreeView->didStopFlinging();
    847         return true;
    848     }
    849     return false;
    850 }
    851 
    852 bool WebViewImpl::startPageScaleAnimation(const IntPoint& targetPosition, bool useAnchor, float newScale, double durationInSeconds)
    853 {
    854     WebPoint clampedPoint = targetPosition;
    855     if (!useAnchor) {
    856         clampedPoint = clampOffsetAtScale(targetPosition, newScale);
    857         if (!durationInSeconds) {
    858             setPageScaleFactor(newScale, clampedPoint);
    859             return false;
    860         }
    861     }
    862     if (useAnchor && newScale == pageScaleFactor())
    863         return false;
    864 
    865     if (m_enableFakePageScaleAnimationForTesting) {
    866         m_fakePageScaleAnimationTargetPosition = targetPosition;
    867         m_fakePageScaleAnimationUseAnchor = useAnchor;
    868         m_fakePageScaleAnimationPageScaleFactor = newScale;
    869     } else {
    870         if (!m_layerTreeView)
    871             return false;
    872         m_layerTreeView->startPageScaleAnimation(targetPosition, useAnchor, newScale, durationInSeconds);
    873     }
    874     return true;
    875 }
    876 
    877 void WebViewImpl::enableFakePageScaleAnimationForTesting(bool enable)
    878 {
    879     m_enableFakePageScaleAnimationForTesting = enable;
    880 }
    881 
    882 void WebViewImpl::setShowFPSCounter(bool show)
    883 {
    884     if (m_layerTreeView) {
    885         TRACE_EVENT0("blink", "WebViewImpl::setShowFPSCounter");
    886         m_layerTreeView->setShowFPSCounter(show);
    887     }
    888     m_showFPSCounter = show;
    889 }
    890 
    891 void WebViewImpl::setShowPaintRects(bool show)
    892 {
    893     if (m_layerTreeView) {
    894         TRACE_EVENT0("blink", "WebViewImpl::setShowPaintRects");
    895         m_layerTreeView->setShowPaintRects(show);
    896     }
    897     m_showPaintRects = show;
    898     setFirstPaintInvalidationTrackingEnabledForShowPaintRects(show);
    899 }
    900 
    901 void WebViewImpl::setShowDebugBorders(bool show)
    902 {
    903     if (m_layerTreeView)
    904         m_layerTreeView->setShowDebugBorders(show);
    905     m_showDebugBorders = show;
    906 }
    907 
    908 void WebViewImpl::setContinuousPaintingEnabled(bool enabled)
    909 {
    910     if (m_layerTreeView) {
    911         TRACE_EVENT0("blink", "WebViewImpl::setContinuousPaintingEnabled");
    912         m_layerTreeView->setContinuousPaintingEnabled(enabled);
    913     }
    914     m_continuousPaintingEnabled = enabled;
    915     if (m_client)
    916         m_client->scheduleAnimation();
    917 }
    918 
    919 void WebViewImpl::setShowScrollBottleneckRects(bool show)
    920 {
    921     if (m_layerTreeView)
    922         m_layerTreeView->setShowScrollBottleneckRects(show);
    923     m_showScrollBottleneckRects = show;
    924 }
    925 
    926 void WebViewImpl::getSelectionRootBounds(WebRect& bounds) const
    927 {
    928     const Frame* frame = focusedCoreFrame();
    929     if (!frame || !frame->isLocalFrame())
    930         return;
    931 
    932     Element* root = toLocalFrame(frame)->selection().rootEditableElementOrDocumentElement();
    933     if (!root)
    934         return;
    935 
    936     // If the selection is inside a form control, the root will be a <div> that
    937     // behaves as the editor but we want to return the actual element's bounds.
    938     // In practice, that means <textarea> and <input> controls that behave like
    939     // a text field.
    940     Element* shadowHost = root->shadowHost();
    941     if (shadowHost
    942         && (isHTMLTextAreaElement(*shadowHost)
    943             || (isHTMLInputElement(*shadowHost) && toHTMLInputElement(*shadowHost).isTextField())))
    944         root = shadowHost;
    945 
    946     IntRect boundingBox = isHTMLHtmlElement(root)
    947         ? IntRect(IntPoint(0, 0), root->document().frame()->view()->contentsSize())
    948         : root->pixelSnappedBoundingBox();
    949 
    950     boundingBox = root->document().frame()->view()->contentsToWindow(boundingBox);
    951     boundingBox.scale(pageScaleFactor());
    952     bounds = boundingBox;
    953 }
    954 
    955 void WebViewImpl::acceptLanguagesChanged()
    956 {
    957     if (!page())
    958         return;
    959 
    960     page()->acceptLanguagesChanged();
    961 }
    962 
    963 bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
    964 {
    965     ASSERT((event.type == WebInputEvent::RawKeyDown)
    966         || (event.type == WebInputEvent::KeyDown)
    967         || (event.type == WebInputEvent::KeyUp));
    968 
    969     // Halt an in-progress fling on a key event.
    970     endActiveFlingAnimation();
    971 
    972     // Please refer to the comments explaining the m_suppressNextKeypressEvent
    973     // member.
    974     // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
    975     // Webkit. A keyDown event is typically associated with a keyPress(char)
    976     // event and a keyUp event. We reset this flag here as this is a new keyDown
    977     // event.
    978     m_suppressNextKeypressEvent = false;
    979 
    980     // If there is a select popup, it should be the one processing the event,
    981     // not the page.
    982     if (m_selectPopup)
    983         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
    984     if (m_pagePopup) {
    985         m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
    986         // We need to ignore the next Char event after this otherwise pressing
    987         // enter when selecting an item in the popup will go to the page.
    988         if (WebInputEvent::RawKeyDown == event.type)
    989             m_suppressNextKeypressEvent = true;
    990         return true;
    991     }
    992 
    993     RefPtrWillBeRawPtr<Frame> focusedFrame = focusedCoreFrame();
    994     if (focusedFrame && focusedFrame->isRemoteFrameTemporary()) {
    995         WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(toLocalFrameTemporary(focusedFrame.get()));
    996         webFrame->client()->forwardInputEvent(&event);
    997         return true;
    998     }
    999 
   1000     if (!focusedFrame || !focusedFrame->isLocalFrame())
   1001         return false;
   1002 
   1003     LocalFrame* frame = toLocalFrame(focusedFrame.get());
   1004 
   1005     PlatformKeyboardEventBuilder evt(event);
   1006 
   1007     if (frame->eventHandler().keyEvent(evt)) {
   1008         if (WebInputEvent::RawKeyDown == event.type) {
   1009             // Suppress the next keypress event unless the focused node is a plug-in node.
   1010             // (Flash needs these keypress events to handle non-US keyboards.)
   1011             Element* element = focusedElement();
   1012             if (!element || !element->renderer() || !element->renderer()->isEmbeddedObject())
   1013                 m_suppressNextKeypressEvent = true;
   1014         }
   1015         return true;
   1016     }
   1017 
   1018 #if !OS(MACOSX)
   1019     const WebInputEvent::Type contextMenuTriggeringEventType =
   1020 #if OS(WIN)
   1021         WebInputEvent::KeyUp;
   1022 #else
   1023         WebInputEvent::RawKeyDown;
   1024 #endif
   1025 
   1026     bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS;
   1027     bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10;
   1028     if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) {
   1029         sendContextMenuEvent(event);
   1030         return true;
   1031     }
   1032 #endif // !OS(MACOSX)
   1033 
   1034     return keyEventDefault(event);
   1035 }
   1036 
   1037 bool WebViewImpl::handleCharEvent(const WebKeyboardEvent& event)
   1038 {
   1039     ASSERT(event.type == WebInputEvent::Char);
   1040 
   1041     // Please refer to the comments explaining the m_suppressNextKeypressEvent
   1042     // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
   1043     // handled by Webkit. A keyDown event is typically associated with a
   1044     // keyPress(char) event and a keyUp event. We reset this flag here as it
   1045     // only applies to the current keyPress event.
   1046     bool suppress = m_suppressNextKeypressEvent;
   1047     m_suppressNextKeypressEvent = false;
   1048 
   1049     // If there is a select popup, it should be the one processing the event,
   1050     // not the page.
   1051     if (m_selectPopup)
   1052         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
   1053     if (m_pagePopup)
   1054         return m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
   1055 
   1056     LocalFrame* frame = toLocalFrame(focusedCoreFrame());
   1057     if (!frame)
   1058         return suppress;
   1059 
   1060     EventHandler& handler = frame->eventHandler();
   1061 
   1062     PlatformKeyboardEventBuilder evt(event);
   1063     if (!evt.isCharacterKey())
   1064         return true;
   1065 
   1066     // Accesskeys are triggered by char events and can't be suppressed.
   1067     if (handler.handleAccessKey(evt))
   1068         return true;
   1069 
   1070     // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
   1071     // the eventHandler::keyEvent. We mimic this behavior on all platforms since
   1072     // for now we are converting other platform's key events to windows key
   1073     // events.
   1074     if (evt.isSystemKey())
   1075         return false;
   1076 
   1077     if (!suppress && !handler.keyEvent(evt))
   1078         return keyEventDefault(event);
   1079 
   1080     return true;
   1081 }
   1082 
   1083 WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, bool ignoreClipping)
   1084 {
   1085     if (!mainFrameImpl())
   1086         return WebRect();
   1087 
   1088     // Use the rect-based hit test to find the node.
   1089     IntPoint point = mainFrameImpl()->frameView()->windowToContents(IntPoint(rect.x, rect.y));
   1090     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | (ignoreClipping ? HitTestRequest::IgnoreClipping : 0);
   1091     HitTestResult result = mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(point, hitType, IntSize(rect.width, rect.height));
   1092     result.setToShadowHostIfInUserAgentShadowRoot();
   1093 
   1094     Node* node = result.innerNonSharedNode();
   1095     if (!node)
   1096         return WebRect();
   1097 
   1098     // Find the block type node based on the hit node.
   1099     // FIXME: This wants to walk composed tree with NodeRenderingTraversal::parent().
   1100     while (node && (!node->renderer() || node->renderer()->isInline()))
   1101         node = NodeRenderingTraversal::parent(node);
   1102 
   1103     // Return the bounding box in the window coordinate system.
   1104     if (node) {
   1105         IntRect rect = node->Node::pixelSnappedBoundingBox();
   1106         LocalFrame* frame = node->document().frame();
   1107         return frame->view()->contentsToWindow(rect);
   1108     }
   1109     return WebRect();
   1110 }
   1111 
   1112 WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int targetMargin, int minimumMargin)
   1113 {
   1114     WebSize maxSize;
   1115     if (mainFrame())
   1116         maxSize = mainFrame()->contentsSize();
   1117     IntSize scrollOffset;
   1118     if (mainFrame())
   1119         scrollOffset = mainFrame()->scrollOffset();
   1120     int leftMargin = targetMargin;
   1121     int rightMargin = targetMargin;
   1122 
   1123     const int absoluteSourceX = source.x + scrollOffset.width();
   1124     if (leftMargin > absoluteSourceX) {
   1125         leftMargin = absoluteSourceX;
   1126         rightMargin = std::max(leftMargin, minimumMargin);
   1127     }
   1128 
   1129     const int maximumRightMargin = maxSize.width - (source.width + absoluteSourceX);
   1130     if (rightMargin > maximumRightMargin) {
   1131         rightMargin = maximumRightMargin;
   1132         leftMargin = std::min(leftMargin, std::max(rightMargin, minimumMargin));
   1133     }
   1134 
   1135     const int newWidth = source.width + leftMargin + rightMargin;
   1136     const int newX = source.x - leftMargin;
   1137 
   1138     ASSERT(newWidth >= 0);
   1139     ASSERT(scrollOffset.width() + newX + newWidth <= maxSize.width);
   1140 
   1141     return WebRect(newX, source.y, newWidth, source.height);
   1142 }
   1143 
   1144 float WebViewImpl::legibleScale() const
   1145 {
   1146     // Pages should be as legible as on desktop when at dpi scale, so no
   1147     // need to zoom in further when automatically determining zoom level
   1148     // (after double tap, find in page, etc), though the user should still
   1149     // be allowed to manually pinch zoom in further if they desire.
   1150     float legibleScale = 1;
   1151     if (page())
   1152         legibleScale *= page()->settings().accessibilityFontScaleFactor();
   1153     return legibleScale;
   1154 }
   1155 
   1156 void WebViewImpl::computeScaleAndScrollForBlockRect(const WebPoint& hitPoint, const WebRect& blockRect, float padding, float defaultScaleWhenAlreadyLegible, float& scale, WebPoint& scroll)
   1157 {
   1158     scale = pageScaleFactor();
   1159     scroll.x = scroll.y = 0;
   1160 
   1161     WebRect rect = blockRect;
   1162 
   1163     if (!rect.isEmpty()) {
   1164         float defaultMargin = doubleTapZoomContentDefaultMargin;
   1165         float minimumMargin = doubleTapZoomContentMinimumMargin;
   1166         // We want the margins to have the same physical size, which means we
   1167         // need to express them in post-scale size. To do that we'd need to know
   1168         // the scale we're scaling to, but that depends on the margins. Instead
   1169         // we express them as a fraction of the target rectangle: this will be
   1170         // correct if we end up fully zooming to it, and won't matter if we
   1171         // don't.
   1172         rect = widenRectWithinPageBounds(rect,
   1173                 static_cast<int>(defaultMargin * rect.width / m_size.width),
   1174                 static_cast<int>(minimumMargin * rect.width / m_size.width));
   1175         // Fit block to screen, respecting limits.
   1176         scale = static_cast<float>(m_size.width) / rect.width;
   1177         scale = std::min(scale, legibleScale());
   1178         if (pageScaleFactor() < defaultScaleWhenAlreadyLegible)
   1179             scale = std::max(scale, defaultScaleWhenAlreadyLegible);
   1180         scale = clampPageScaleFactorToLimits(scale);
   1181     }
   1182 
   1183     // FIXME: If this is being called for auto zoom during find in page,
   1184     // then if the user manually zooms in it'd be nice to preserve the
   1185     // relative increase in zoom they caused (if they zoom out then it's ok
   1186     // to zoom them back in again). This isn't compatible with our current
   1187     // double-tap zoom strategy (fitting the containing block to the screen)
   1188     // though.
   1189 
   1190     float screenWidth = m_size.width / scale;
   1191     float screenHeight = m_size.height / scale;
   1192 
   1193     // Scroll to vertically align the block.
   1194     if (rect.height < screenHeight) {
   1195         // Vertically center short blocks.
   1196         rect.y -= 0.5 * (screenHeight - rect.height);
   1197     } else {
   1198         // Ensure position we're zooming to (+ padding) isn't off the bottom of
   1199         // the screen.
   1200         rect.y = std::max<float>(rect.y, hitPoint.y + padding - screenHeight);
   1201     } // Otherwise top align the block.
   1202 
   1203     // Do the same thing for horizontal alignment.
   1204     if (rect.width < screenWidth)
   1205         rect.x -= 0.5 * (screenWidth - rect.width);
   1206     else
   1207         rect.x = std::max<float>(rect.x, hitPoint.x + padding - screenWidth);
   1208     scroll.x = rect.x;
   1209     scroll.y = rect.y;
   1210 
   1211     scale = clampPageScaleFactorToLimits(scale);
   1212     scroll = mainFrameImpl()->frameView()->windowToContents(scroll);
   1213     scroll = clampOffsetAtScale(scroll, scale);
   1214 }
   1215 
   1216 static Node* findCursorDefiningAncestor(Node* node, LocalFrame* frame)
   1217 {
   1218     // Go up the tree to find the node that defines a mouse cursor style
   1219     while (node) {
   1220         if (node->renderer()) {
   1221             ECursor cursor = node->renderer()->style()->cursor();
   1222             if (cursor != CURSOR_AUTO || frame->eventHandler().useHandCursor(node, node->isLink()))
   1223                 break;
   1224         }
   1225         node = NodeRenderingTraversal::parent(node);
   1226     }
   1227 
   1228     return node;
   1229 }
   1230 
   1231 static bool showsHandCursor(Node* node, LocalFrame* frame)
   1232 {
   1233     if (!node || !node->renderer())
   1234         return false;
   1235 
   1236     ECursor cursor = node->renderer()->style()->cursor();
   1237     return cursor == CURSOR_POINTER
   1238         || (cursor == CURSOR_AUTO && frame->eventHandler().useHandCursor(node, node->isLink()));
   1239 }
   1240 
   1241 Node* WebViewImpl::bestTapNode(const GestureEventWithHitTestResults& targetedTapEvent)
   1242 {
   1243     TRACE_EVENT0("input", "WebViewImpl::bestTapNode");
   1244 
   1245     if (!m_page || !m_page->mainFrame())
   1246         return 0;
   1247 
   1248     Node* bestTouchNode = targetedTapEvent.hitTestResult().innerNode();
   1249 
   1250     // We might hit something like an image map that has no renderer on it
   1251     // Walk up the tree until we have a node with an attached renderer
   1252     // FIXME: This wants to walk composed tree with NodeRenderingTraversal::parent().
   1253     while (bestTouchNode && !bestTouchNode->renderer())
   1254         bestTouchNode = NodeRenderingTraversal::parent(bestTouchNode);
   1255 
   1256     Node* cursorDefiningAncestor =
   1257         findCursorDefiningAncestor(bestTouchNode, m_page->deprecatedLocalMainFrame());
   1258     // We show a highlight on tap only when the current node shows a hand cursor
   1259     if (!cursorDefiningAncestor || !showsHandCursor(cursorDefiningAncestor, m_page->deprecatedLocalMainFrame())) {
   1260         return 0;
   1261     }
   1262 
   1263     // We should pick the largest enclosing node with hand cursor set. We do this by first jumping
   1264     // up to cursorDefiningAncestor (which is already known to have hand cursor set). Then we locate
   1265     // the next cursor-defining ancestor up in the the tree and repeat the jumps as long as the node
   1266     // has hand cursor set.
   1267     do {
   1268         bestTouchNode = cursorDefiningAncestor;
   1269         cursorDefiningAncestor = findCursorDefiningAncestor(NodeRenderingTraversal::parent(bestTouchNode),
   1270             m_page->deprecatedLocalMainFrame());
   1271     } while (cursorDefiningAncestor && showsHandCursor(cursorDefiningAncestor, m_page->deprecatedLocalMainFrame()));
   1272 
   1273     return bestTouchNode;
   1274 }
   1275 
   1276 void WebViewImpl::enableTapHighlightAtPoint(const GestureEventWithHitTestResults& targetedTapEvent)
   1277 {
   1278     Node* touchNode = bestTapNode(targetedTapEvent);
   1279 
   1280     WillBeHeapVector<RawPtrWillBeMember<Node> > highlightNodes;
   1281     highlightNodes.append(touchNode);
   1282 
   1283     enableTapHighlights(highlightNodes);
   1284 }
   1285 
   1286 void WebViewImpl::enableTapHighlights(WillBeHeapVector<RawPtrWillBeMember<Node> >& highlightNodes)
   1287 {
   1288     if (highlightNodes.isEmpty())
   1289         return;
   1290 
   1291     // Always clear any existing highlight when this is invoked, even if we
   1292     // don't get a new target to highlight.
   1293     m_linkHighlights.clear();
   1294 
   1295     // LinkHighlight reads out layout and compositing state, so we need to make sure that's all up to date.
   1296     layout();
   1297 
   1298     for (size_t i = 0; i < highlightNodes.size(); ++i) {
   1299         Node* node = highlightNodes[i];
   1300 
   1301         if (!node || !node->renderer())
   1302             continue;
   1303 
   1304         Color highlightColor = node->renderer()->style()->tapHighlightColor();
   1305         // Safari documentation for -webkit-tap-highlight-color says if the specified color has 0 alpha,
   1306         // then tap highlighting is disabled.
   1307         // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
   1308         if (!highlightColor.alpha())
   1309             continue;
   1310 
   1311         m_linkHighlights.append(LinkHighlight::create(node, this));
   1312     }
   1313 }
   1314 
   1315 void WebViewImpl::animateDoubleTapZoom(const IntPoint& point)
   1316 {
   1317     if (!mainFrameImpl())
   1318         return;
   1319 
   1320     WebRect rect(point.x(), point.y(), touchPointPadding, touchPointPadding);
   1321     WebRect blockBounds = computeBlockBounds(rect, false);
   1322 
   1323     float scale;
   1324     WebPoint scroll;
   1325 
   1326     computeScaleAndScrollForBlockRect(point, blockBounds, touchPointPadding, minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio, scale, scroll);
   1327 
   1328     bool stillAtPreviousDoubleTapScale = (pageScaleFactor() == m_doubleTapZoomPageScaleFactor
   1329         && m_doubleTapZoomPageScaleFactor != minimumPageScaleFactor())
   1330         || m_doubleTapZoomPending;
   1331 
   1332     bool scaleUnchanged = fabs(pageScaleFactor() - scale) < minScaleDifference;
   1333     bool shouldZoomOut = blockBounds.isEmpty() || scaleUnchanged || stillAtPreviousDoubleTapScale;
   1334 
   1335     bool isAnimating;
   1336 
   1337     if (shouldZoomOut) {
   1338         scale = minimumPageScaleFactor();
   1339         isAnimating = startPageScaleAnimation(mainFrameImpl()->frameView()->windowToContents(point), true, scale, doubleTapZoomAnimationDurationInSeconds);
   1340     } else {
   1341         isAnimating = startPageScaleAnimation(scroll, false, scale, doubleTapZoomAnimationDurationInSeconds);
   1342     }
   1343 
   1344     if (isAnimating) {
   1345         m_doubleTapZoomPageScaleFactor = scale;
   1346         m_doubleTapZoomPending = true;
   1347     }
   1348 }
   1349 
   1350 void WebViewImpl::zoomToFindInPageRect(const WebRect& rect)
   1351 {
   1352     if (!mainFrameImpl())
   1353         return;
   1354 
   1355     WebRect blockBounds = computeBlockBounds(rect, true);
   1356 
   1357     if (blockBounds.isEmpty()) {
   1358         // Keep current scale (no need to scroll as x,y will normally already
   1359         // be visible). FIXME: Revisit this if it isn't always true.
   1360         return;
   1361     }
   1362 
   1363     float scale;
   1364     WebPoint scroll;
   1365 
   1366     computeScaleAndScrollForBlockRect(WebPoint(rect.x, rect.y), blockBounds, nonUserInitiatedPointPadding, minimumPageScaleFactor(), scale, scroll);
   1367 
   1368     startPageScaleAnimation(scroll, false, scale, findInPageAnimationDurationInSeconds);
   1369 }
   1370 
   1371 bool WebViewImpl::zoomToMultipleTargetsRect(const WebRect& rect)
   1372 {
   1373     if (!mainFrameImpl())
   1374         return false;
   1375 
   1376     float scale;
   1377     WebPoint scroll;
   1378 
   1379     computeScaleAndScrollForBlockRect(WebPoint(rect.x, rect.y), rect, nonUserInitiatedPointPadding, minimumPageScaleFactor(), scale, scroll);
   1380 
   1381     if (scale <= pageScaleFactor())
   1382         return false;
   1383 
   1384     startPageScaleAnimation(scroll, false, scale, multipleTargetsZoomAnimationDurationInSeconds);
   1385     return true;
   1386 }
   1387 
   1388 void WebViewImpl::hasTouchEventHandlers(bool hasTouchHandlers)
   1389 {
   1390     if (m_client)
   1391         m_client->hasTouchEventHandlers(hasTouchHandlers);
   1392 }
   1393 
   1394 bool WebViewImpl::hasTouchEventHandlersAt(const WebPoint& point)
   1395 {
   1396     // FIXME: Implement this. Note that the point must be divided by pageScaleFactor.
   1397     return true;
   1398 }
   1399 
   1400 #if !OS(MACOSX)
   1401 // Mac has no way to open a context menu based on a keyboard event.
   1402 bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
   1403 {
   1404     // The contextMenuController() holds onto the last context menu that was
   1405     // popped up on the page until a new one is created. We need to clear
   1406     // this menu before propagating the event through the DOM so that we can
   1407     // detect if we create a new menu for this event, since we won't create
   1408     // a new menu if the DOM swallows the event and the defaultEventHandler does
   1409     // not run.
   1410     page()->contextMenuController().clearContextMenu();
   1411 
   1412     m_contextMenuAllowed = true;
   1413     Frame* focusedFrame = page()->focusController().focusedOrMainFrame();
   1414     if (!focusedFrame->isLocalFrame())
   1415         return false;
   1416     bool handled = toLocalFrame(focusedFrame)->eventHandler().sendContextMenuEventForKey();
   1417     m_contextMenuAllowed = false;
   1418     return handled;
   1419 }
   1420 #endif
   1421 
   1422 void WebViewImpl::showContextMenuAtPoint(float x, float y, PassRefPtr<ContextMenuProvider> menuProvider)
   1423 {
   1424     if (!page()->mainFrame()->isLocalFrame())
   1425         return;
   1426     m_contextMenuAllowed = true;
   1427     page()->contextMenuController().clearContextMenu();
   1428     page()->contextMenuController().showContextMenuAtPoint(page()->deprecatedLocalMainFrame(), x, y, menuProvider);
   1429     m_contextMenuAllowed = false;
   1430 }
   1431 
   1432 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
   1433 {
   1434     LocalFrame* frame = toLocalFrame(focusedCoreFrame());
   1435     if (!frame)
   1436         return false;
   1437 
   1438     switch (event.type) {
   1439     case WebInputEvent::Char:
   1440         if (event.windowsKeyCode == VKEY_SPACE) {
   1441             int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
   1442             return scrollViewWithKeyboard(keyCode, event.modifiers);
   1443         }
   1444         break;
   1445     case WebInputEvent::RawKeyDown:
   1446         if (event.modifiers == WebInputEvent::ControlKey) {
   1447             switch (event.windowsKeyCode) {
   1448 #if !OS(MACOSX)
   1449             case 'A':
   1450                 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
   1451                 return true;
   1452             case VKEY_INSERT:
   1453             case 'C':
   1454                 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
   1455                 return true;
   1456 #endif
   1457             // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
   1458             // key combinations which affect scrolling. Safari is buggy in the
   1459             // sense that it scrolls the page for all Ctrl+scrolling key
   1460             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
   1461             case VKEY_HOME:
   1462             case VKEY_END:
   1463                 break;
   1464             default:
   1465                 return false;
   1466             }
   1467         }
   1468         if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
   1469             return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
   1470         break;
   1471     default:
   1472         break;
   1473     }
   1474     return false;
   1475 }
   1476 
   1477 bool WebViewImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
   1478 {
   1479     ScrollDirection scrollDirection;
   1480     ScrollGranularity scrollGranularity;
   1481 #if OS(MACOSX)
   1482     // Control-Up/Down should be PageUp/Down on Mac.
   1483     if (modifiers & WebMouseEvent::ControlKey) {
   1484       if (keyCode == VKEY_UP)
   1485         keyCode = VKEY_PRIOR;
   1486       else if (keyCode == VKEY_DOWN)
   1487         keyCode = VKEY_NEXT;
   1488     }
   1489 #endif
   1490     if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
   1491         return false;
   1492 
   1493     if (LocalFrame* frame = toLocalFrame(focusedCoreFrame()))
   1494         return frame->eventHandler().bubblingScroll(scrollDirection, scrollGranularity);
   1495     return false;
   1496 }
   1497 
   1498 bool WebViewImpl::mapKeyCodeForScroll(
   1499     int keyCode,
   1500     ScrollDirection* scrollDirection,
   1501     ScrollGranularity* scrollGranularity)
   1502 {
   1503     switch (keyCode) {
   1504     case VKEY_LEFT:
   1505         *scrollDirection = ScrollLeft;
   1506         *scrollGranularity = ScrollByLine;
   1507         break;
   1508     case VKEY_RIGHT:
   1509         *scrollDirection = ScrollRight;
   1510         *scrollGranularity = ScrollByLine;
   1511         break;
   1512     case VKEY_UP:
   1513         *scrollDirection = ScrollUp;
   1514         *scrollGranularity = ScrollByLine;
   1515         break;
   1516     case VKEY_DOWN:
   1517         *scrollDirection = ScrollDown;
   1518         *scrollGranularity = ScrollByLine;
   1519         break;
   1520     case VKEY_HOME:
   1521         *scrollDirection = ScrollUp;
   1522         *scrollGranularity = ScrollByDocument;
   1523         break;
   1524     case VKEY_END:
   1525         *scrollDirection = ScrollDown;
   1526         *scrollGranularity = ScrollByDocument;
   1527         break;
   1528     case VKEY_PRIOR:  // page up
   1529         *scrollDirection = ScrollUp;
   1530         *scrollGranularity = ScrollByPage;
   1531         break;
   1532     case VKEY_NEXT:  // page down
   1533         *scrollDirection = ScrollDown;
   1534         *scrollGranularity = ScrollByPage;
   1535         break;
   1536     default:
   1537         return false;
   1538     }
   1539 
   1540     return true;
   1541 }
   1542 
   1543 void WebViewImpl::hideSelectPopup()
   1544 {
   1545     if (m_selectPopup)
   1546         m_selectPopup->hidePopup();
   1547 }
   1548 
   1549 void WebViewImpl::popupOpened(PopupContainer* popupContainer)
   1550 {
   1551     ASSERT(!m_selectPopup);
   1552     m_selectPopup = popupContainer;
   1553     ASSERT(mainFrameImpl()->frame()->document());
   1554     Document& document = *mainFrameImpl()->frame()->document();
   1555     page()->frameHost().eventHandlerRegistry().didAddEventHandler(document, EventHandlerRegistry::WheelEvent);
   1556 }
   1557 
   1558 void WebViewImpl::popupClosed(PopupContainer* popupContainer)
   1559 {
   1560     ASSERT(m_selectPopup);
   1561     m_selectPopup = nullptr;
   1562     ASSERT(mainFrameImpl()->frame()->document());
   1563     Document& document = *mainFrameImpl()->frame()->document();
   1564     // Remove the handler we added in |popupOpened| conditionally, because the
   1565     // Document may have already removed it, for instance, due to a navigation.
   1566     EventHandlerRegistry* registry = &document.frameHost()->eventHandlerRegistry();
   1567     if (registry->eventHandlerTargets(EventHandlerRegistry::WheelEvent)->contains(&document))
   1568         registry->didRemoveEventHandler(document, EventHandlerRegistry::WheelEvent);
   1569 }
   1570 
   1571 PagePopup* WebViewImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
   1572 {
   1573     ASSERT(client);
   1574     if (hasOpenedPopup())
   1575         hidePopups();
   1576     ASSERT(!m_pagePopup);
   1577 
   1578     WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypePage);
   1579     ASSERT(popupWidget);
   1580     m_pagePopup = toWebPagePopupImpl(popupWidget);
   1581     if (!m_pagePopup->initialize(this, client, originBoundsInRootView)) {
   1582         m_pagePopup->closePopup();
   1583         m_pagePopup = nullptr;
   1584     }
   1585     return m_pagePopup.get();
   1586 }
   1587 
   1588 void WebViewImpl::closePagePopup(PagePopup* popup)
   1589 {
   1590     ASSERT(popup);
   1591     WebPagePopupImpl* popupImpl = toWebPagePopupImpl(popup);
   1592     ASSERT(m_pagePopup.get() == popupImpl);
   1593     if (m_pagePopup.get() != popupImpl)
   1594         return;
   1595     m_pagePopup->closePopup();
   1596     m_pagePopup = nullptr;
   1597 }
   1598 
   1599 Frame* WebViewImpl::focusedCoreFrame() const
   1600 {
   1601     return m_page ? m_page->focusController().focusedOrMainFrame() : 0;
   1602 }
   1603 
   1604 WebViewImpl* WebViewImpl::fromPage(Page* page)
   1605 {
   1606     if (!page)
   1607         return 0;
   1608     return static_cast<WebViewImpl*>(page->chrome().client().webView());
   1609 }
   1610 
   1611 // WebWidget ------------------------------------------------------------------
   1612 
   1613 void WebViewImpl::close()
   1614 {
   1615     if (m_page) {
   1616         // Initiate shutdown for the entire frameset.  This will cause a lot of
   1617         // notifications to be sent.
   1618         m_page->willBeDestroyed();
   1619         m_page.clear();
   1620     }
   1621 
   1622     // Should happen after m_page.clear().
   1623     if (m_devToolsAgent)
   1624         m_devToolsAgent.clear();
   1625 
   1626     // Reset the delegate to prevent notifications being sent as we're being
   1627     // deleted.
   1628     m_client = 0;
   1629 
   1630     deref();  // Balances ref() acquired in WebView::create
   1631 }
   1632 
   1633 void WebViewImpl::willStartLiveResize()
   1634 {
   1635     if (mainFrameImpl() && mainFrameImpl()->frameView())
   1636         mainFrameImpl()->frameView()->willStartLiveResize();
   1637 
   1638     LocalFrame* frame = mainFrameImpl()->frame();
   1639     WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
   1640     if (pluginContainer)
   1641         pluginContainer->willStartLiveResize();
   1642 }
   1643 
   1644 WebSize WebViewImpl::size()
   1645 {
   1646     return m_size;
   1647 }
   1648 
   1649 void WebViewImpl::resizePinchViewport(const WebSize& newSize)
   1650 {
   1651     if (!pinchVirtualViewportEnabled())
   1652         return;
   1653 
   1654     page()->frameHost().pinchViewport().setSize(newSize);
   1655 }
   1656 
   1657 WebLocalFrameImpl* WebViewImpl::localFrameRootTemporary() const
   1658 {
   1659     // FIXME: This is a temporary method that finds the first localFrame in a traversal.
   1660     // This is equivalent to mainFrame() if the mainFrame is in-process. We need to create
   1661     // separate WebWidgets to be created by RenderWidgets, which are associated with *all*
   1662     // local frame roots, not just the first one in the tree. Until then, this limits us
   1663     // to having only one functioning connected LocalFrame subtree per process.
   1664     for (Frame* frame = page()->mainFrame(); frame; frame = frame->tree().traverseNext()) {
   1665         if (frame->isLocalRoot())
   1666             return WebLocalFrameImpl::fromFrame(toLocalFrame(frame));
   1667     }
   1668     return 0;
   1669 }
   1670 
   1671 void WebViewImpl::performResize()
   1672 {
   1673     m_pageScaleConstraintsSet.didChangeViewSize(m_size);
   1674 
   1675     updatePageDefinedViewportConstraints(localFrameRootTemporary()->frame()->document()->viewportDescription());
   1676     updateMainFrameLayoutSize();
   1677 
   1678     // If the virtual viewport pinch mode is enabled, the main frame will be resized
   1679     // after layout so it can be sized to the contentsSize.
   1680     if (!pinchVirtualViewportEnabled() && localFrameRootTemporary()->frameView())
   1681         localFrameRootTemporary()->frameView()->resize(m_size);
   1682 
   1683     if (pinchVirtualViewportEnabled())
   1684         page()->frameHost().pinchViewport().setSize(m_size);
   1685 
   1686     // When device emulation is enabled, device size values may change - they are
   1687     // usually set equal to the view size. These values are not considered viewport-dependent
   1688     // (see MediaQueryExp::isViewportDependent), since they are only viewport-dependent in emulation mode,
   1689     // and thus will not be invalidated in |FrameView::performPreLayoutTasks|.
   1690     // Therefore we should force explicit media queries invalidation here.
   1691     if (page()->inspectorController().deviceEmulationEnabled()) {
   1692         if (Document* document = localFrameRootTemporary()->frame()->document())
   1693             document->mediaQueryAffectingValueChanged();
   1694     }
   1695 }
   1696 
   1697 void WebViewImpl::setTopControlsContentOffset(float offset)
   1698 {
   1699     m_topControlsContentOffset = offset;
   1700     m_layerTreeView->setTopControlsContentOffset(offset);
   1701     didUpdateTopControls();
   1702 }
   1703 
   1704 void WebViewImpl::setTopControlsLayoutHeight(float height)
   1705 {
   1706     m_topControlsLayoutHeight = height;
   1707     didUpdateTopControls();
   1708 }
   1709 
   1710 void WebViewImpl::didUpdateTopControls()
   1711 {
   1712     FrameView* view = localFrameRootTemporary()->frameView();
   1713     if (!view)
   1714         return;
   1715 
   1716     // The viewport bounds were adjusted on the compositor by this much due to top controls. Tell
   1717     // the FrameView about it so it can make correct scroll offset clamping decisions during compositor
   1718     // commits.
   1719     // FIXME(bokan) Reenable once Chromium side lands.
   1720     // float topControlsViewportAdjustment = m_topControlsContentOffset - m_topControlsLayoutHeight;
   1721     // view->setTopControlsViewportAdjustment(topControlsViewportAdjustment);
   1722 }
   1723 
   1724 void WebViewImpl::resize(const WebSize& newSize)
   1725 {
   1726     if (m_shouldAutoResize || m_size == newSize)
   1727         return;
   1728 
   1729     FrameView* view = localFrameRootTemporary()->frameView();
   1730     if (!view)
   1731         return;
   1732 
   1733     bool shouldAnchorAndRescaleViewport = settings()->mainFrameResizesAreOrientationChanges()
   1734         && m_size.width && contentsSize().width() && newSize.width != m_size.width && !m_fullscreenController->isFullscreen();
   1735     float oldPageScaleFactor = pageScaleFactor();
   1736     float oldMinimumPageScaleFactor = minimumPageScaleFactor();
   1737 
   1738     m_size = newSize;
   1739 
   1740     ViewportAnchor viewportAnchor(&localFrameRootTemporary()->frame()->eventHandler());
   1741     if (shouldAnchorAndRescaleViewport) {
   1742         viewportAnchor.setAnchor(
   1743             view->visibleContentRect(),
   1744             visibleRectInDocument(),
   1745             FloatSize(viewportAnchorXCoord, viewportAnchorYCoord));
   1746     }
   1747 
   1748     // FIXME: TextAutosizer does not yet support out-of-process frames.
   1749     if (mainFrameImpl() && mainFrameImpl()->frame()->isLocalFrame())
   1750     {
   1751         // Avoids unnecessary invalidations while various bits of state in TextAutosizer are updated.
   1752         TextAutosizer::DeferUpdatePageInfo deferUpdatePageInfo(page());
   1753         performResize();
   1754     } else {
   1755         performResize();
   1756     }
   1757 
   1758     if (settings()->viewportEnabled()) {
   1759         // Relayout immediately to recalculate the minimum scale limit.
   1760         if (view->needsLayout())
   1761             view->layout();
   1762 
   1763         if (shouldAnchorAndRescaleViewport) {
   1764             float newPageScaleFactor = oldPageScaleFactor / oldMinimumPageScaleFactor * minimumPageScaleFactor();
   1765             newPageScaleFactor = clampPageScaleFactorToLimits(newPageScaleFactor);
   1766 
   1767             FloatSize pinchViewportSize = FloatSize(newSize);
   1768             pinchViewportSize.scale(1 / newPageScaleFactor);
   1769 
   1770             IntPoint mainFrameOrigin;
   1771             FloatPoint pinchViewportOrigin;
   1772             viewportAnchor.computeOrigins(*view, pinchViewportSize,
   1773                 mainFrameOrigin, pinchViewportOrigin);
   1774             scrollAndRescaleViewports(newPageScaleFactor, mainFrameOrigin, pinchViewportOrigin);
   1775         }
   1776     }
   1777 
   1778     sendResizeEventAndRepaint();
   1779 }
   1780 
   1781 IntRect WebViewImpl::visibleRectInDocument() const
   1782 {
   1783     if (pinchVirtualViewportEnabled()) {
   1784         // Inner viewport in the document coordinates
   1785         return enclosedIntRect(page()->frameHost().pinchViewport().visibleRectInDocument());
   1786     }
   1787 
   1788     // Outer viewport in the document coordinates
   1789     return localFrameRootTemporary()->frameView()->visibleContentRect();
   1790 }
   1791 
   1792 void WebViewImpl::willEndLiveResize()
   1793 {
   1794     if (mainFrameImpl() && mainFrameImpl()->frameView())
   1795         mainFrameImpl()->frameView()->willEndLiveResize();
   1796 
   1797     LocalFrame* frame = mainFrameImpl()->frame();
   1798     WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
   1799     if (pluginContainer)
   1800         pluginContainer->willEndLiveResize();
   1801 }
   1802 
   1803 void WebViewImpl::didEnterFullScreen()
   1804 {
   1805     m_fullscreenController->didEnterFullScreen();
   1806 }
   1807 
   1808 void WebViewImpl::didExitFullScreen()
   1809 {
   1810     m_fullscreenController->didExitFullScreen();
   1811 }
   1812 
   1813 void WebViewImpl::beginFrame(const WebBeginFrameArgs& frameTime)
   1814 {
   1815     TRACE_EVENT0("blink", "WebViewImpl::beginFrame");
   1816 
   1817     WebBeginFrameArgs validFrameTime(frameTime);
   1818     if (!validFrameTime.lastFrameTimeMonotonic)
   1819         validFrameTime.lastFrameTimeMonotonic = monotonicallyIncreasingTime();
   1820 
   1821     Scheduler::shared()->willBeginFrame(validFrameTime);
   1822 
   1823     // Create synthetic wheel events as necessary for fling.
   1824     if (m_gestureAnimation) {
   1825         if (m_gestureAnimation->animate(validFrameTime.lastFrameTimeMonotonic))
   1826             scheduleAnimation();
   1827         else {
   1828             endActiveFlingAnimation();
   1829 
   1830             PlatformGestureEvent endScrollEvent(PlatformEvent::GestureScrollEnd,
   1831                 m_positionOnFlingStart, m_globalPositionOnFlingStart,
   1832                 IntSize(), 0, false, false, false, false,
   1833                 0, 0, 0, 0);
   1834 
   1835             mainFrameImpl()->frame()->eventHandler().handleGestureScrollEnd(endScrollEvent);
   1836         }
   1837     }
   1838 
   1839     if (!m_page)
   1840         return;
   1841 
   1842     PageWidgetDelegate::animate(m_page.get(), validFrameTime.lastFrameTimeMonotonic);
   1843 
   1844     if (m_continuousPaintingEnabled) {
   1845         ContinuousPainter::setNeedsDisplayRecursive(m_rootGraphicsLayer, m_pageOverlays.get());
   1846         m_client->scheduleAnimation();
   1847     }
   1848 }
   1849 
   1850 void WebViewImpl::didCommitFrameToCompositor()
   1851 {
   1852     Scheduler::shared()->didCommitFrameToCompositor();
   1853 }
   1854 
   1855 void WebViewImpl::layout()
   1856 {
   1857     TRACE_EVENT0("blink", "WebViewImpl::layout");
   1858     if (!localFrameRootTemporary())
   1859         return;
   1860 
   1861     PageWidgetDelegate::layout(m_page.get(), localFrameRootTemporary()->frame());
   1862     updateLayerTreeBackgroundColor();
   1863 
   1864     for (size_t i = 0; i < m_linkHighlights.size(); ++i)
   1865         m_linkHighlights[i]->updateGeometry();
   1866 
   1867     if (m_devToolsAgent)
   1868         m_devToolsAgent->didLayout();
   1869 }
   1870 
   1871 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
   1872 {
   1873     // This should only be used when compositing is not being used for this
   1874     // WebView, and it is painting into the recording of its parent.
   1875     ASSERT(!isAcceleratedCompositingActive());
   1876 
   1877     double paintStart = currentTime();
   1878     PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
   1879     double paintEnd = currentTime();
   1880     double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart);
   1881     Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
   1882     Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
   1883 }
   1884 
   1885 #if OS(ANDROID)
   1886 void WebViewImpl::paintCompositedDeprecated(WebCanvas* canvas, const WebRect& rect)
   1887 {
   1888     // Note: This method exists on OS(ANDROID) and will hopefully be
   1889     //       removed once the link disambiguation feature renders using
   1890     //       the compositor.
   1891     ASSERT(isAcceleratedCompositingActive());
   1892 
   1893     FrameView* view = page()->deprecatedLocalMainFrame()->view();
   1894     PaintBehavior oldPaintBehavior = view->paintBehavior();
   1895     view->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers);
   1896 
   1897     PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
   1898 
   1899     view->setPaintBehavior(oldPaintBehavior);
   1900 }
   1901 #endif
   1902 
   1903 void WebViewImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
   1904 {
   1905     ASSERT(isAcceleratedCompositingActive());
   1906     m_layerTreeView->compositeAndReadbackAsync(callback);
   1907 }
   1908 
   1909 bool WebViewImpl::isTrackingRepaints() const
   1910 {
   1911     if (!page())
   1912         return false;
   1913     if (!page()->mainFrame()->isLocalFrame())
   1914         return false;
   1915     FrameView* view = page()->deprecatedLocalMainFrame()->view();
   1916     return view->isTrackingPaintInvalidations();
   1917 }
   1918 
   1919 void WebViewImpl::themeChanged()
   1920 {
   1921     if (!page())
   1922         return;
   1923     if (!page()->mainFrame()->isLocalFrame())
   1924         return;
   1925     FrameView* view = page()->deprecatedLocalMainFrame()->view();
   1926 
   1927     WebRect damagedRect(0, 0, m_size.width, m_size.height);
   1928     view->invalidateRect(damagedRect);
   1929 }
   1930 
   1931 void WebViewImpl::enterFullScreenForElement(Element* element)
   1932 {
   1933     m_fullscreenController->enterFullScreenForElement(element);
   1934 }
   1935 
   1936 void WebViewImpl::exitFullScreenForElement(Element* element)
   1937 {
   1938     m_fullscreenController->exitFullScreenForElement(element);
   1939 }
   1940 
   1941 void WebViewImpl::clearCompositedSelectionBounds()
   1942 {
   1943     if (m_layerTreeView)
   1944         m_layerTreeView->clearSelection();
   1945 }
   1946 
   1947 void WebViewImpl::updateCompositedSelectionBounds(const WebSelectionBound& anchor, const WebSelectionBound& focus)
   1948 {
   1949     if (m_layerTreeView)
   1950         m_layerTreeView->registerSelection(anchor, focus);
   1951 }
   1952 
   1953 bool WebViewImpl::hasHorizontalScrollbar()
   1954 {
   1955     return mainFrameImpl()->frameView()->horizontalScrollbar();
   1956 }
   1957 
   1958 bool WebViewImpl::hasVerticalScrollbar()
   1959 {
   1960     return mainFrameImpl()->frameView()->verticalScrollbar();
   1961 }
   1962 
   1963 const WebInputEvent* WebViewImpl::m_currentInputEvent = 0;
   1964 
   1965 // FIXME: autogenerate this kind of code, and use it throughout Blink rather than
   1966 // the one-offs for subsets of these values.
   1967 static String inputTypeToName(WebInputEvent::Type type)
   1968 {
   1969     switch (type) {
   1970     case WebInputEvent::MouseDown:
   1971         return EventTypeNames::mousedown;
   1972     case WebInputEvent::MouseUp:
   1973         return EventTypeNames::mouseup;
   1974     case WebInputEvent::MouseMove:
   1975         return EventTypeNames::mousemove;
   1976     case WebInputEvent::MouseEnter:
   1977         return EventTypeNames::mouseenter;
   1978     case WebInputEvent::MouseLeave:
   1979         return EventTypeNames::mouseleave;
   1980     case WebInputEvent::ContextMenu:
   1981         return EventTypeNames::contextmenu;
   1982     case WebInputEvent::MouseWheel:
   1983         return EventTypeNames::mousewheel;
   1984     case WebInputEvent::KeyDown:
   1985         return EventTypeNames::keydown;
   1986     case WebInputEvent::KeyUp:
   1987         return EventTypeNames::keyup;
   1988     case WebInputEvent::GestureScrollBegin:
   1989         return EventTypeNames::gesturescrollstart;
   1990     case WebInputEvent::GestureScrollEnd:
   1991         return EventTypeNames::gesturescrollend;
   1992     case WebInputEvent::GestureScrollUpdate:
   1993         return EventTypeNames::gesturescrollupdate;
   1994     case WebInputEvent::GestureTapDown:
   1995         return EventTypeNames::gesturetapdown;
   1996     case WebInputEvent::GestureShowPress:
   1997         return EventTypeNames::gestureshowpress;
   1998     case WebInputEvent::GestureTap:
   1999         return EventTypeNames::gesturetap;
   2000     case WebInputEvent::GestureTapUnconfirmed:
   2001         return EventTypeNames::gesturetapunconfirmed;
   2002     case WebInputEvent::TouchStart:
   2003         return EventTypeNames::touchstart;
   2004     case WebInputEvent::TouchMove:
   2005         return EventTypeNames::touchmove;
   2006     case WebInputEvent::TouchEnd:
   2007         return EventTypeNames::touchend;
   2008     case WebInputEvent::TouchCancel:
   2009         return EventTypeNames::touchcancel;
   2010     default:
   2011         return String("unknown");
   2012     }
   2013 }
   2014 
   2015 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
   2016 {
   2017     UserGestureNotifier notifier(m_autofillClient, &m_userGestureObserved);
   2018     // On the first input event since page load, |notifier| instructs the
   2019     // autofill client to unblock values of password input fields of any forms
   2020     // on the page. There is a single input event, GestureTap, which can both
   2021     // be the first event after page load, and cause a form submission. In that
   2022     // case, the form submission happens before the autofill client is told
   2023     // to unblock the password values, and so the password values are not
   2024     // submitted. To avoid that, GestureTap is handled explicitly:
   2025     if (inputEvent.type == WebInputEvent::GestureTap && m_autofillClient) {
   2026         m_userGestureObserved = true;
   2027         m_autofillClient->firstUserGestureObserved();
   2028     }
   2029 
   2030     TRACE_EVENT1("input", "WebViewImpl::handleInputEvent", "type", inputTypeToName(inputEvent.type).ascii());
   2031     // If we've started a drag and drop operation, ignore input events until
   2032     // we're done.
   2033     if (m_doingDragAndDrop)
   2034         return true;
   2035 
   2036     if (m_devToolsAgent && m_devToolsAgent->handleInputEvent(m_page.get(), inputEvent))
   2037         return true;
   2038 
   2039     // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
   2040     if (m_ignoreInputEvents)
   2041         return false;
   2042 
   2043     TemporaryChange<const WebInputEvent*> currentEventChange(m_currentInputEvent, &inputEvent);
   2044 
   2045     if (isPointerLocked() && WebInputEvent::isMouseEventType(inputEvent.type)) {
   2046       pointerLockMouseEvent(inputEvent);
   2047       return true;
   2048     }
   2049 
   2050     if (m_mouseCaptureNode && WebInputEvent::isMouseEventType(inputEvent.type)) {
   2051         TRACE_EVENT1("input", "captured mouse event", "type", inputEvent.type);
   2052         // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
   2053         RefPtrWillBeRawPtr<Node> node = m_mouseCaptureNode;
   2054 
   2055         // Not all platforms call mouseCaptureLost() directly.
   2056         if (inputEvent.type == WebInputEvent::MouseUp)
   2057             mouseCaptureLost();
   2058 
   2059         OwnPtr<UserGestureIndicator> gestureIndicator;
   2060 
   2061         AtomicString eventType;
   2062         switch (inputEvent.type) {
   2063         case WebInputEvent::MouseMove:
   2064             eventType = EventTypeNames::mousemove;
   2065             break;
   2066         case WebInputEvent::MouseLeave:
   2067             eventType = EventTypeNames::mouseout;
   2068             break;
   2069         case WebInputEvent::MouseDown:
   2070             eventType = EventTypeNames::mousedown;
   2071             gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture));
   2072             m_mouseCaptureGestureToken = gestureIndicator->currentToken();
   2073             break;
   2074         case WebInputEvent::MouseUp:
   2075             eventType = EventTypeNames::mouseup;
   2076             gestureIndicator = adoptPtr(new UserGestureIndicator(m_mouseCaptureGestureToken.release()));
   2077             break;
   2078         default:
   2079             ASSERT_NOT_REACHED();
   2080         }
   2081 
   2082         node->dispatchMouseEvent(
   2083             PlatformMouseEventBuilder(mainFrameImpl()->frameView(), static_cast<const WebMouseEvent&>(inputEvent)),
   2084             eventType, static_cast<const WebMouseEvent&>(inputEvent).clickCount);
   2085         return true;
   2086     }
   2087 
   2088     return PageWidgetDelegate::handleInputEvent(m_page.get(), *this, inputEvent);
   2089 }
   2090 
   2091 void WebViewImpl::setCursorVisibilityState(bool isVisible)
   2092 {
   2093     if (m_page)
   2094         m_page->setIsCursorVisible(isVisible);
   2095 }
   2096 
   2097 void WebViewImpl::mouseCaptureLost()
   2098 {
   2099     TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
   2100     m_mouseCaptureNode = nullptr;
   2101 }
   2102 
   2103 void WebViewImpl::setFocus(bool enable)
   2104 {
   2105     m_page->focusController().setFocused(enable);
   2106     if (enable) {
   2107         m_page->focusController().setActive(true);
   2108         RefPtrWillBeRawPtr<Frame> focusedFrame = m_page->focusController().focusedFrame();
   2109         if (focusedFrame && focusedFrame->isLocalFrame()) {
   2110             LocalFrame* localFrame = toLocalFrame(focusedFrame.get());
   2111             Element* element = localFrame->document()->focusedElement();
   2112             if (element && localFrame->selection().selection().isNone()) {
   2113                 // If the selection was cleared while the WebView was not
   2114                 // focused, then the focus element shows with a focus ring but
   2115                 // no caret and does respond to keyboard inputs.
   2116                 if (element->isTextFormControl()) {
   2117                     element->updateFocusAppearance(true);
   2118                 } else if (element->isContentEditable()) {
   2119                     // updateFocusAppearance() selects all the text of
   2120                     // contentseditable DIVs. So we set the selection explicitly
   2121                     // instead. Note that this has the side effect of moving the
   2122                     // caret back to the beginning of the text.
   2123                     Position position(element, 0, Position::PositionIsOffsetInAnchor);
   2124                     localFrame->selection().setSelection(VisibleSelection(position, SEL_DEFAULT_AFFINITY));
   2125                 }
   2126             }
   2127         }
   2128         m_imeAcceptEvents = true;
   2129     } else {
   2130         hidePopups();
   2131 
   2132         // Clear focus on the currently focused frame if any.
   2133         if (!m_page)
   2134             return;
   2135 
   2136         LocalFrame* frame = m_page->mainFrame() && m_page->mainFrame()->isLocalFrame()
   2137             ? m_page->deprecatedLocalMainFrame() : 0;
   2138         if (!frame)
   2139             return;
   2140 
   2141         RefPtrWillBeRawPtr<Frame> focusedFrame = m_page->focusController().focusedFrame();
   2142         if (focusedFrame && focusedFrame->isLocalFrame()) {
   2143             // Finish an ongoing composition to delete the composition node.
   2144             if (toLocalFrame(focusedFrame.get())->inputMethodController().hasComposition()) {
   2145                 if (m_autofillClient)
   2146                     m_autofillClient->setIgnoreTextChanges(true);
   2147 
   2148                 toLocalFrame(focusedFrame.get())->inputMethodController().confirmComposition();
   2149 
   2150                 if (m_autofillClient)
   2151                     m_autofillClient->setIgnoreTextChanges(false);
   2152             }
   2153             m_imeAcceptEvents = false;
   2154         }
   2155     }
   2156 }
   2157 
   2158 bool WebViewImpl::setComposition(
   2159     const WebString& text,
   2160     const WebVector<WebCompositionUnderline>& underlines,
   2161     int selectionStart,
   2162     int selectionEnd)
   2163 {
   2164     LocalFrame* focused = toLocalFrame(focusedCoreFrame());
   2165     if (!focused || !m_imeAcceptEvents)
   2166         return false;
   2167 
   2168     if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused))
   2169         return plugin->setComposition(text, underlines, selectionStart, selectionEnd);
   2170 
   2171     // The input focus has been moved to another WebWidget object.
   2172     // We should use this |editor| object only to complete the ongoing
   2173     // composition.
   2174     InputMethodController& inputMethodController = focused->inputMethodController();
   2175     if (!focused->editor().canEdit() && !inputMethodController.hasComposition())
   2176         return false;
   2177 
   2178     // We should verify the parent node of this IME composition node are
   2179     // editable because JavaScript may delete a parent node of the composition
   2180     // node. In this case, WebKit crashes while deleting texts from the parent
   2181     // node, which doesn't exist any longer.
   2182     RefPtrWillBeRawPtr<Range> range = inputMethodController.compositionRange();
   2183     if (range) {
   2184         Node* node = range->startContainer();
   2185         if (!node || !node->isContentEditable())
   2186             return false;
   2187     }
   2188 
   2189     // If we're not going to fire a keypress event, then the keydown event was
   2190     // canceled.  In that case, cancel any existing composition.
   2191     if (text.isEmpty() || m_suppressNextKeypressEvent) {
   2192         // A browser process sent an IPC message which does not contain a valid
   2193         // string, which means an ongoing composition has been canceled.
   2194         // If the ongoing composition has been canceled, replace the ongoing
   2195         // composition string with an empty string and complete it.
   2196         String emptyString;
   2197         Vector<CompositionUnderline> emptyUnderlines;
   2198         inputMethodController.setComposition(emptyString, emptyUnderlines, 0, 0);
   2199         return text.isEmpty();
   2200     }
   2201 
   2202     // When the range of composition underlines overlap with the range between
   2203     // selectionStart and selectionEnd, WebKit somehow won't paint the selection
   2204     // at all (see InlineTextBox::paint() function in InlineTextBox.cpp).
   2205     // But the selection range actually takes effect.
   2206     inputMethodController.setComposition(String(text),
   2207                            CompositionUnderlineVectorBuilder(underlines),
   2208                            selectionStart, selectionEnd);
   2209 
   2210     return inputMethodController.hasComposition();
   2211 }
   2212 
   2213 bool WebViewImpl::confirmComposition()
   2214 {
   2215     return confirmComposition(DoNotKeepSelection);
   2216 }
   2217 
   2218 bool WebViewImpl::confirmComposition(ConfirmCompositionBehavior selectionBehavior)
   2219 {
   2220     return confirmComposition(WebString(), selectionBehavior);
   2221 }
   2222 
   2223 bool WebViewImpl::confirmComposition(const WebString& text)
   2224 {
   2225     return confirmComposition(text, DoNotKeepSelection);
   2226 }
   2227 
   2228 bool WebViewImpl::confirmComposition(const WebString& text, ConfirmCompositionBehavior selectionBehavior)
   2229 {
   2230     LocalFrame* focused = toLocalFrame(focusedCoreFrame());
   2231     if (!focused || !m_imeAcceptEvents)
   2232         return false;
   2233 
   2234     if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused))
   2235         return plugin->confirmComposition(text, selectionBehavior);
   2236 
   2237     return focused->inputMethodController().confirmCompositionOrInsertText(text, selectionBehavior == KeepSelection ? InputMethodController::KeepSelection : InputMethodController::DoNotKeepSelection);
   2238 }
   2239 
   2240 bool WebViewImpl::compositionRange(size_t* location, size_t* length)
   2241 {
   2242     LocalFrame* focused = toLocalFrame(focusedCoreFrame());
   2243     if (!focused || !m_imeAcceptEvents)
   2244         return false;
   2245 
   2246     RefPtrWillBeRawPtr<Range> range = focused->inputMethodController().compositionRange();
   2247     if (!range)
   2248         return false;
   2249 
   2250     Element* editable = focused->selection().rootEditableElementOrDocumentElement();
   2251     ASSERT(editable);
   2252     PlainTextRange plainTextRange(PlainTextRange::create(*editable, *range.get()));
   2253     if (plainTextRange.isNull())
   2254         return false;
   2255     *location = plainTextRange.start();
   2256     *length = plainTextRange.length();
   2257     return true;
   2258 }
   2259 
   2260 WebTextInputInfo WebViewImpl::textInputInfo()
   2261 {
   2262     WebTextInputInfo info;
   2263 
   2264     Frame* focusedFrame = focusedCoreFrame();
   2265     if (!focusedFrame->isLocalFrame())
   2266         return info;
   2267 
   2268     LocalFrame* focused = toLocalFrame(focusedFrame);
   2269     if (!focused)
   2270         return info;
   2271 
   2272     FrameSelection& selection = focused->selection();
   2273     Element* element = selection.selection().rootEditableElement();
   2274     if (!element)
   2275         return info;
   2276 
   2277     info.inputMode = inputModeOfFocusedElement();
   2278 
   2279     info.type = textInputType();
   2280     info.flags = textInputFlags();
   2281     if (info.type == WebTextInputTypeNone)
   2282         return info;
   2283 
   2284     if (!focused->editor().canEdit())
   2285         return info;
   2286 
   2287     // Emits an object replacement character for each replaced element so that
   2288     // it is exposed to IME and thus could be deleted by IME on android.
   2289     info.value = plainText(rangeOfContents(element).get(), TextIteratorEmitsObjectReplacementCharacter);
   2290 
   2291     if (info.value.isEmpty())
   2292         return info;
   2293 
   2294     if (RefPtrWillBeRawPtr<Range> range = selection.selection().firstRange()) {
   2295         PlainTextRange plainTextRange(PlainTextRange::create(*element, *range.get()));
   2296         if (plainTextRange.isNotNull()) {
   2297             info.selectionStart = plainTextRange.start();
   2298             info.selectionEnd = plainTextRange.end();
   2299         }
   2300     }
   2301 
   2302     if (RefPtrWillBeRawPtr<Range> range = focused->inputMethodController().compositionRange()) {
   2303         PlainTextRange plainTextRange(PlainTextRange::create(*element, *range.get()));
   2304         if (plainTextRange.isNotNull()) {
   2305             info.compositionStart = plainTextRange.start();
   2306             info.compositionEnd = plainTextRange.end();
   2307         }
   2308     }
   2309 
   2310     return info;
   2311 }
   2312 
   2313 WebTextInputType WebViewImpl::textInputType()
   2314 {
   2315     Element* element = focusedElement();
   2316     if (!element)
   2317         return WebTextInputTypeNone;
   2318 
   2319     if (isHTMLInputElement(*element)) {
   2320         HTMLInputElement& input = toHTMLInputElement(*element);
   2321         const AtomicString& type = input.type();
   2322 
   2323         if (input.isDisabledOrReadOnly())
   2324             return WebTextInputTypeNone;
   2325 
   2326         if (type == InputTypeNames::password)
   2327             return WebTextInputTypePassword;
   2328         if (type == InputTypeNames::search)
   2329             return WebTextInputTypeSearch;
   2330         if (type == InputTypeNames::email)
   2331             return WebTextInputTypeEmail;
   2332         if (type == InputTypeNames::number)
   2333             return WebTextInputTypeNumber;
   2334         if (type == InputTypeNames::tel)
   2335             return WebTextInputTypeTelephone;
   2336         if (type == InputTypeNames::url)
   2337             return WebTextInputTypeURL;
   2338         if (type == InputTypeNames::date)
   2339             return WebTextInputTypeDate;
   2340         if (type == InputTypeNames::datetime_local)
   2341             return WebTextInputTypeDateTimeLocal;
   2342         if (type == InputTypeNames::month)
   2343             return WebTextInputTypeMonth;
   2344         if (type == InputTypeNames::time)
   2345             return WebTextInputTypeTime;
   2346         if (type == InputTypeNames::week)
   2347             return WebTextInputTypeWeek;
   2348         if (type == InputTypeNames::text)
   2349             return WebTextInputTypeText;
   2350 
   2351         return WebTextInputTypeNone;
   2352     }
   2353 
   2354     if (isHTMLTextAreaElement(*element)) {
   2355         if (toHTMLTextAreaElement(*element).isDisabledOrReadOnly())
   2356             return WebTextInputTypeNone;
   2357         return WebTextInputTypeTextArea;
   2358     }
   2359 
   2360 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
   2361     if (element->isHTMLElement()) {
   2362         if (toHTMLElement(element)->isDateTimeFieldElement())
   2363             return WebTextInputTypeDateTimeField;
   2364     }
   2365 #endif
   2366 
   2367     if (element->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable))
   2368         return WebTextInputTypeContentEditable;
   2369 
   2370     return WebTextInputTypeNone;
   2371 }
   2372 
   2373 int WebViewImpl::textInputFlags()
   2374 {
   2375     Element* element = focusedElement();
   2376     if (!element)
   2377         return WebTextInputFlagNone;
   2378 
   2379     DEFINE_STATIC_LOCAL(AtomicString, autocompleteString, ("autocomplete", AtomicString::ConstructFromLiteral));
   2380     DEFINE_STATIC_LOCAL(AtomicString, autocorrectString, ("autocorrect", AtomicString::ConstructFromLiteral));
   2381     DEFINE_STATIC_LOCAL(AtomicString, spellcheckString, ("spellcheck", AtomicString::ConstructFromLiteral));
   2382     int flags = 0;
   2383 
   2384     const AtomicString& autocomplete = element->getAttribute(autocompleteString);
   2385     if (autocomplete == "on")
   2386         flags |= WebTextInputFlagAutocompleteOn;
   2387     else if (autocomplete == "off")
   2388         flags |= WebTextInputFlagAutocompleteOff;
   2389 
   2390     const AtomicString& autocorrect = element->getAttribute(autocorrectString);
   2391     if (autocorrect == "on")
   2392         flags |= WebTextInputFlagAutocorrectOn;
   2393     else if (autocorrect == "off")
   2394         flags |= WebTextInputFlagAutocorrectOff;
   2395 
   2396     const AtomicString& spellcheck = element->getAttribute(spellcheckString);
   2397     if (spellcheck == "on")
   2398         flags |= WebTextInputFlagSpellcheckOn;
   2399     else if (spellcheck == "off")
   2400         flags |= WebTextInputFlagSpellcheckOff;
   2401 
   2402     return flags;
   2403 }
   2404 
   2405 WebString WebViewImpl::inputModeOfFocusedElement()
   2406 {
   2407     if (!RuntimeEnabledFeatures::inputModeAttributeEnabled())
   2408         return WebString();
   2409 
   2410     Element* element = focusedElement();
   2411     if (!element)
   2412         return WebString();
   2413 
   2414     if (isHTMLInputElement(*element)) {
   2415         const HTMLInputElement& input = toHTMLInputElement(*element);
   2416         if (input.supportsInputModeAttribute())
   2417             return input.fastGetAttribute(HTMLNames::inputmodeAttr).lower();
   2418         return WebString();
   2419     }
   2420     if (isHTMLTextAreaElement(*element)) {
   2421         const HTMLTextAreaElement& textarea = toHTMLTextAreaElement(*element);
   2422         return textarea.fastGetAttribute(HTMLNames::inputmodeAttr).lower();
   2423     }
   2424 
   2425     return WebString();
   2426 }
   2427 
   2428 bool WebViewImpl::selectionBounds(WebRect& anchor, WebRect& focus) const
   2429 {
   2430     const Frame* frame = focusedCoreFrame();
   2431     if (!frame || !frame->isLocalFrame())
   2432         return false;
   2433 
   2434     const LocalFrame* localFrame = toLocalFrame(frame);
   2435     if (!localFrame)
   2436         return false;
   2437     FrameSelection& selection = localFrame->selection();
   2438 
   2439     if (selection.isCaret()) {
   2440         anchor = focus = selection.absoluteCaretBounds();
   2441     } else {
   2442         RefPtrWillBeRawPtr<Range> selectedRange = selection.toNormalizedRange();
   2443         if (!selectedRange)
   2444             return false;
   2445 
   2446         RefPtrWillBeRawPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
   2447             selectedRange->startContainer(),
   2448             selectedRange->startOffset(),
   2449             selectedRange->startContainer(),
   2450             selectedRange->startOffset()));
   2451         anchor = localFrame->editor().firstRectForRange(range.get());
   2452 
   2453         range = Range::create(selectedRange->endContainer()->document(),
   2454             selectedRange->endContainer(),
   2455             selectedRange->endOffset(),
   2456             selectedRange->endContainer(),
   2457             selectedRange->endOffset());
   2458         focus = localFrame->editor().firstRectForRange(range.get());
   2459     }
   2460 
   2461     IntRect scaledAnchor(localFrame->view()->contentsToWindow(anchor));
   2462     IntRect scaledFocus(localFrame->view()->contentsToWindow(focus));
   2463 
   2464     if (pinchVirtualViewportEnabled()) {
   2465         // FIXME(http://crbug.com/371902) - We shouldn't have to do this
   2466         // manually, the contentsToWindow methods above should be fixed to do
   2467         // this.
   2468         IntPoint pinchViewportOffset =
   2469             roundedIntPoint(page()->frameHost().pinchViewport().visibleRect().location());
   2470         scaledAnchor.moveBy(-pinchViewportOffset);
   2471         scaledFocus.moveBy(-pinchViewportOffset);
   2472     }
   2473 
   2474     scaledAnchor.scale(pageScaleFactor());
   2475     scaledFocus.scale(pageScaleFactor());
   2476     anchor = scaledAnchor;
   2477     focus = scaledFocus;
   2478 
   2479     if (!selection.selection().isBaseFirst())
   2480         std::swap(anchor, focus);
   2481     return true;
   2482 }
   2483 
   2484 InputMethodContext* WebViewImpl::inputMethodContext()
   2485 {
   2486     if (!m_imeAcceptEvents)
   2487         return 0;
   2488 
   2489     LocalFrame* focusedFrame = toLocalFrame(focusedCoreFrame());
   2490     if (!focusedFrame)
   2491         return 0;
   2492 
   2493     Element* target = focusedFrame->document()->focusedElement();
   2494     if (target && target->hasInputMethodContext())
   2495         return &target->inputMethodContext();
   2496 
   2497     return 0;
   2498 }
   2499 
   2500 WebPlugin* WebViewImpl::focusedPluginIfInputMethodSupported(LocalFrame* frame)
   2501 {
   2502     WebPluginContainerImpl* container = WebLocalFrameImpl::pluginContainerFromNode(frame, WebNode(focusedElement()));
   2503     if (container && container->supportsInputMethod())
   2504         return container->plugin();
   2505     return 0;
   2506 }
   2507 
   2508 void WebViewImpl::didShowCandidateWindow()
   2509 {
   2510     if (InputMethodContext* context = inputMethodContext())
   2511         context->dispatchCandidateWindowShowEvent();
   2512 }
   2513 
   2514 void WebViewImpl::didUpdateCandidateWindow()
   2515 {
   2516     if (InputMethodContext* context = inputMethodContext())
   2517         context->dispatchCandidateWindowUpdateEvent();
   2518 }
   2519 
   2520 void WebViewImpl::didHideCandidateWindow()
   2521 {
   2522     if (InputMethodContext* context = inputMethodContext())
   2523         context->dispatchCandidateWindowHideEvent();
   2524 }
   2525 
   2526 bool WebViewImpl::selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const
   2527 {
   2528     const LocalFrame* frame = toLocalFrame(focusedCoreFrame());
   2529     if (!frame)
   2530         return false;
   2531     FrameSelection& selection = frame->selection();
   2532     if (!selection.toNormalizedRange())
   2533         return false;
   2534     start = toWebTextDirection(selection.start().primaryDirection());
   2535     end = toWebTextDirection(selection.end().primaryDirection());
   2536     return true;
   2537 }
   2538 
   2539 bool WebViewImpl::isSelectionAnchorFirst() const
   2540 {
   2541     if (const LocalFrame* frame = toLocalFrame(focusedCoreFrame()))
   2542         return frame->selection().selection().isBaseFirst();
   2543     return false;
   2544 }
   2545 
   2546 WebVector<WebCompositionUnderline> WebViewImpl::compositionUnderlines() const
   2547 {
   2548     const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
   2549     if (!focused)
   2550         return WebVector<WebCompositionUnderline>();
   2551     const Vector<CompositionUnderline>& underlines = focused->inputMethodController().customCompositionUnderlines();
   2552     WebVector<WebCompositionUnderline> results(underlines.size());
   2553     for (size_t index = 0; index < underlines.size(); ++index) {
   2554         CompositionUnderline underline = underlines[index];
   2555         results[index] = WebCompositionUnderline(underline.startOffset, underline.endOffset, static_cast<WebColor>(underline.color.rgb()), underline.thick, static_cast<WebColor>(underline.backgroundColor.rgb()));
   2556     }
   2557     return results;
   2558 }
   2559 
   2560 WebColor WebViewImpl::backgroundColor() const
   2561 {
   2562     if (isTransparent())
   2563         return Color::transparent;
   2564     if (!m_page)
   2565         return m_baseBackgroundColor;
   2566     if (!m_page->mainFrame())
   2567         return m_baseBackgroundColor;
   2568     if (!m_page->mainFrame()->isLocalFrame())
   2569         return m_baseBackgroundColor;
   2570     FrameView* view = m_page->deprecatedLocalMainFrame()->view();
   2571     return view->documentBackgroundColor().rgb();
   2572 }
   2573 
   2574 WebPagePopup* WebViewImpl::pagePopup() const
   2575 {
   2576     return m_pagePopup.get();
   2577 }
   2578 
   2579 bool WebViewImpl::caretOrSelectionRange(size_t* location, size_t* length)
   2580 {
   2581     const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
   2582     if (!focused)
   2583         return false;
   2584 
   2585     PlainTextRange selectionOffsets = focused->inputMethodController().getSelectionOffsets();
   2586     if (selectionOffsets.isNull())
   2587         return false;
   2588 
   2589     *location = selectionOffsets.start();
   2590     *length = selectionOffsets.length();
   2591     return true;
   2592 }
   2593 
   2594 void WebViewImpl::setTextDirection(WebTextDirection direction)
   2595 {
   2596     // The Editor::setBaseWritingDirection() function checks if we can change
   2597     // the text direction of the selected node and updates its DOM "dir"
   2598     // attribute and its CSS "direction" property.
   2599     // So, we just call the function as Safari does.
   2600     const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
   2601     if (!focused)
   2602         return;
   2603 
   2604     Editor& editor = focused->editor();
   2605     if (!editor.canEdit())
   2606         return;
   2607 
   2608     switch (direction) {
   2609     case WebTextDirectionDefault:
   2610         editor.setBaseWritingDirection(NaturalWritingDirection);
   2611         break;
   2612 
   2613     case WebTextDirectionLeftToRight:
   2614         editor.setBaseWritingDirection(LeftToRightWritingDirection);
   2615         break;
   2616 
   2617     case WebTextDirectionRightToLeft:
   2618         editor.setBaseWritingDirection(RightToLeftWritingDirection);
   2619         break;
   2620 
   2621     default:
   2622         notImplemented();
   2623         break;
   2624     }
   2625 }
   2626 
   2627 bool WebViewImpl::isAcceleratedCompositingActive() const
   2628 {
   2629     return m_isAcceleratedCompositingActive;
   2630 }
   2631 
   2632 void WebViewImpl::willCloseLayerTreeView()
   2633 {
   2634     setIsAcceleratedCompositingActive(false);
   2635     m_layerTreeView = 0;
   2636     m_layerTreeViewClosed = true;
   2637 }
   2638 
   2639 void WebViewImpl::didAcquirePointerLock()
   2640 {
   2641     if (page())
   2642         page()->pointerLockController().didAcquirePointerLock();
   2643 }
   2644 
   2645 void WebViewImpl::didNotAcquirePointerLock()
   2646 {
   2647     if (page())
   2648         page()->pointerLockController().didNotAcquirePointerLock();
   2649 }
   2650 
   2651 void WebViewImpl::didLosePointerLock()
   2652 {
   2653     m_pointerLockGestureToken.clear();
   2654     if (page())
   2655         page()->pointerLockController().didLosePointerLock();
   2656 }
   2657 
   2658 void WebViewImpl::didChangeWindowResizerRect()
   2659 {
   2660     if (mainFrameImpl()->frameView())
   2661         mainFrameImpl()->frameView()->windowResizerRectChanged();
   2662 }
   2663 
   2664 // WebView --------------------------------------------------------------------
   2665 
   2666 WebSettingsImpl* WebViewImpl::settingsImpl()
   2667 {
   2668     if (!m_webSettings)
   2669         m_webSettings = adoptPtr(new WebSettingsImpl(&m_page->settings(), &m_page->inspectorController()));
   2670     ASSERT(m_webSettings);
   2671     return m_webSettings.get();
   2672 }
   2673 
   2674 WebSettings* WebViewImpl::settings()
   2675 {
   2676     return settingsImpl();
   2677 }
   2678 
   2679 WebString WebViewImpl::pageEncoding() const
   2680 {
   2681     if (!m_page)
   2682         return WebString();
   2683 
   2684     if (!m_page->mainFrame()->isLocalFrame())
   2685         return WebString();
   2686 
   2687     // FIXME: Is this check needed?
   2688     if (!m_page->deprecatedLocalMainFrame()->document()->loader())
   2689         return WebString();
   2690 
   2691     return m_page->deprecatedLocalMainFrame()->document()->encodingName();
   2692 }
   2693 
   2694 void WebViewImpl::setPageEncoding(const WebString& encodingName)
   2695 {
   2696     if (!m_page)
   2697         return;
   2698 
   2699     if (!m_page->mainFrame()->isLocalFrame())
   2700         return;
   2701 
   2702     // Only change override encoding, don't change default encoding.
   2703     // Note that the new encoding must be 0 if it isn't supposed to be set.
   2704     AtomicString newEncodingName;
   2705     if (!encodingName.isEmpty())
   2706         newEncodingName = encodingName;
   2707     m_page->deprecatedLocalMainFrame()->loader().reload(NormalReload, KURL(), newEncodingName);
   2708 }
   2709 
   2710 WebFrame* WebViewImpl::mainFrame()
   2711 {
   2712     return WebFrame::fromFrame(m_page ? m_page->mainFrame() : 0);
   2713 }
   2714 
   2715 WebFrame* WebViewImpl::findFrameByName(
   2716     const WebString& name, WebFrame* relativeToFrame)
   2717 {
   2718     // FIXME: Either this should only deal with WebLocalFrames or it should move to WebFrame.
   2719     if (!relativeToFrame)
   2720         relativeToFrame = mainFrame();
   2721     Frame* frame = toWebLocalFrameImpl(relativeToFrame)->frame();
   2722     frame = frame->tree().find(name);
   2723     if (!frame || !frame->isLocalFrame())
   2724         return 0;
   2725     return WebLocalFrameImpl::fromFrame(toLocalFrame(frame));
   2726 }
   2727 
   2728 WebFrame* WebViewImpl::focusedFrame()
   2729 {
   2730     return WebFrame::fromFrame(focusedCoreFrame());
   2731 }
   2732 
   2733 void WebViewImpl::setFocusedFrame(WebFrame* frame)
   2734 {
   2735     if (!frame) {
   2736         // Clears the focused frame if any.
   2737         Frame* focusedFrame = focusedCoreFrame();
   2738         if (focusedFrame && focusedFrame->isLocalFrame())
   2739             toLocalFrame(focusedFrame)->selection().setFocused(false);
   2740         return;
   2741     }
   2742     LocalFrame* coreFrame = toWebLocalFrameImpl(frame)->frame();
   2743     coreFrame->page()->focusController().setFocusedFrame(coreFrame);
   2744 }
   2745 
   2746 void WebViewImpl::setInitialFocus(bool reverse)
   2747 {
   2748     if (!m_page)
   2749         return;
   2750     Frame* frame = page()->focusController().focusedOrMainFrame();
   2751     if (frame->isLocalFrame()) {
   2752         if (Document* document = toLocalFrame(frame)->document())
   2753             document->setFocusedElement(nullptr);
   2754     }
   2755     page()->focusController().setInitialFocus(reverse ? FocusTypeBackward : FocusTypeForward);
   2756 }
   2757 
   2758 void WebViewImpl::clearFocusedElement()
   2759 {
   2760     RefPtrWillBeRawPtr<Frame> frame = focusedCoreFrame();
   2761     if (!frame || !frame->isLocalFrame())
   2762         return;
   2763 
   2764     LocalFrame* localFrame = toLocalFrame(frame.get());
   2765 
   2766     RefPtrWillBeRawPtr<Document> document = localFrame->document();
   2767     if (!document)
   2768         return;
   2769 
   2770     RefPtrWillBeRawPtr<Element> oldFocusedElement = document->focusedElement();
   2771 
   2772     // Clear the focused node.
   2773     document->setFocusedElement(nullptr);
   2774 
   2775     if (!oldFocusedElement)
   2776         return;
   2777 
   2778     // If a text field has focus, we need to make sure the selection controller
   2779     // knows to remove selection from it. Otherwise, the text field is still
   2780     // processing keyboard events even though focus has been moved to the page and
   2781     // keystrokes get eaten as a result.
   2782     if (oldFocusedElement->isContentEditable() || oldFocusedElement->isTextFormControl())
   2783         localFrame->selection().clear();
   2784 }
   2785 
   2786 void WebViewImpl::scrollFocusedNodeIntoRect(const WebRect& rect)
   2787 {
   2788     LocalFrame* frame = page()->mainFrame() && page()->mainFrame()->isLocalFrame()
   2789         ? page()->deprecatedLocalMainFrame() : 0;
   2790     Element* element = focusedElement();
   2791     if (!frame || !frame->view() || !element)
   2792         return;
   2793 
   2794     if (!m_webSettings->autoZoomFocusedNodeToLegibleScale()) {
   2795         frame->view()->scrollElementToRect(element, IntRect(rect.x, rect.y, rect.width, rect.height));
   2796         return;
   2797     }
   2798 
   2799     float scale;
   2800     IntPoint scroll;
   2801     bool needAnimation;
   2802     computeScaleAndScrollForFocusedNode(element, scale, scroll, needAnimation);
   2803     if (needAnimation)
   2804         startPageScaleAnimation(scroll, false, scale, scrollAndScaleAnimationDurationInSeconds);
   2805 }
   2806 
   2807 void WebViewImpl::computeScaleAndScrollForFocusedNode(Node* focusedNode, float& newScale, IntPoint& newScroll, bool& needAnimation)
   2808 {
   2809     focusedNode->document().updateLayoutIgnorePendingStylesheets();
   2810 
   2811     // 'caret' is rect encompassing the blinking cursor.
   2812     IntRect textboxRect = focusedNode->document().view()->contentsToWindow(pixelSnappedIntRect(focusedNode->Node::boundingBox()));
   2813     WebRect caret, unusedEnd;
   2814     selectionBounds(caret, unusedEnd);
   2815     IntRect unscaledCaret = caret;
   2816     unscaledCaret.scale(1 / pageScaleFactor());
   2817     caret = unscaledCaret;
   2818 
   2819     // Pick a scale which is reasonably readable. This is the scale at which
   2820     // the caret height will become minReadableCaretHeight (adjusted for dpi
   2821     // and font scale factor).
   2822     newScale = clampPageScaleFactorToLimits(legibleScale() * minReadableCaretHeight / caret.height);
   2823     newScale = std::max(newScale, pageScaleFactor());
   2824     const float deltaScale = newScale / pageScaleFactor();
   2825 
   2826     // Convert the rects to absolute space in the new scale.
   2827     IntRect textboxRectInDocumentCoordinates = textboxRect;
   2828     textboxRectInDocumentCoordinates.move(mainFrame()->scrollOffset());
   2829     IntRect caretInDocumentCoordinates = caret;
   2830     caretInDocumentCoordinates.move(mainFrame()->scrollOffset());
   2831 
   2832     int viewWidth = m_size.width / newScale;
   2833     int viewHeight = m_size.height / newScale;
   2834 
   2835     if (textboxRectInDocumentCoordinates.width() <= viewWidth) {
   2836         // Field is narrower than screen. Try to leave padding on left so field's
   2837         // label is visible, but it's more important to ensure entire field is
   2838         // onscreen.
   2839         int idealLeftPadding = viewWidth * leftBoxRatio;
   2840         int maxLeftPaddingKeepingBoxOnscreen = viewWidth - textboxRectInDocumentCoordinates.width();
   2841         newScroll.setX(textboxRectInDocumentCoordinates.x() - std::min<int>(idealLeftPadding, maxLeftPaddingKeepingBoxOnscreen));
   2842     } else {
   2843         // Field is wider than screen. Try to left-align field, unless caret would
   2844         // be offscreen, in which case right-align the caret.
   2845         newScroll.setX(std::max<int>(textboxRectInDocumentCoordinates.x(), caretInDocumentCoordinates.x() + caretInDocumentCoordinates.width() + caretPadding - viewWidth));
   2846     }
   2847     if (textboxRectInDocumentCoordinates.height() <= viewHeight) {
   2848         // Field is shorter than screen. Vertically center it.
   2849         newScroll.setY(textboxRectInDocumentCoordinates.y() - (viewHeight - textboxRectInDocumentCoordinates.height()) / 2);
   2850     } else {
   2851         // Field is taller than screen. Try to top align field, unless caret would
   2852         // be offscreen, in which case bottom-align the caret.
   2853         newScroll.setY(std::max<int>(textboxRectInDocumentCoordinates.y(), caretInDocumentCoordinates.y() + caretInDocumentCoordinates.height() + caretPadding - viewHeight));
   2854     }
   2855 
   2856     needAnimation = false;
   2857     // If we are at less than the target zoom level, zoom in.
   2858     if (deltaScale > minScaleChangeToTriggerZoom)
   2859         needAnimation = true;
   2860     // If the caret is offscreen, then animate.
   2861     IntRect sizeRect(0, 0, viewWidth, viewHeight);
   2862     sizeRect.scale(newScale / pageScaleFactor());
   2863     if (!sizeRect.contains(caret))
   2864         needAnimation = true;
   2865     // If the box is partially offscreen and it's possible to bring it fully
   2866     // onscreen, then animate.
   2867     if (sizeRect.contains(textboxRectInDocumentCoordinates.width(), textboxRectInDocumentCoordinates.height()) && !sizeRect.contains(textboxRect))
   2868         needAnimation = true;
   2869 }
   2870 
   2871 void WebViewImpl::advanceFocus(bool reverse)
   2872 {
   2873     page()->focusController().advanceFocus(reverse ? FocusTypeBackward : FocusTypeForward);
   2874 }
   2875 
   2876 double WebViewImpl::zoomLevel()
   2877 {
   2878     return m_zoomLevel;
   2879 }
   2880 
   2881 double WebViewImpl::setZoomLevel(double zoomLevel)
   2882 {
   2883     if (zoomLevel < m_minimumZoomLevel)
   2884         m_zoomLevel = m_minimumZoomLevel;
   2885     else if (zoomLevel > m_maximumZoomLevel)
   2886         m_zoomLevel = m_maximumZoomLevel;
   2887     else
   2888         m_zoomLevel = zoomLevel;
   2889 
   2890     LocalFrame* frame = mainFrameImpl()->frame();
   2891     WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
   2892     if (pluginContainer)
   2893         pluginContainer->plugin()->setZoomLevel(m_zoomLevel, false);
   2894     else {
   2895         float zoomFactor = m_zoomFactorOverride ? m_zoomFactorOverride : static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel));
   2896         frame->setPageZoomFactor(zoomFactor);
   2897     }
   2898 
   2899     return m_zoomLevel;
   2900 }
   2901 
   2902 void WebViewImpl::zoomLimitsChanged(double minimumZoomLevel,
   2903                                     double maximumZoomLevel)
   2904 {
   2905     m_minimumZoomLevel = minimumZoomLevel;
   2906     m_maximumZoomLevel = maximumZoomLevel;
   2907     m_client->zoomLimitsChanged(m_minimumZoomLevel, m_maximumZoomLevel);
   2908 }
   2909 
   2910 float WebViewImpl::textZoomFactor()
   2911 {
   2912     return mainFrameImpl()->frame()->textZoomFactor();
   2913 }
   2914 
   2915 float WebViewImpl::setTextZoomFactor(float textZoomFactor)
   2916 {
   2917     LocalFrame* frame = mainFrameImpl()->frame();
   2918     if (WebLocalFrameImpl::pluginContainerFromFrame(frame))
   2919         return 1;
   2920 
   2921     frame->setTextZoomFactor(textZoomFactor);
   2922 
   2923     return textZoomFactor;
   2924 }
   2925 
   2926 void WebViewImpl::fullFramePluginZoomLevelChanged(double zoomLevel)
   2927 {
   2928     if (zoomLevel == m_zoomLevel)
   2929         return;
   2930 
   2931     m_zoomLevel = std::max(std::min(zoomLevel, m_maximumZoomLevel), m_minimumZoomLevel);
   2932     m_client->zoomLevelChanged();
   2933 }
   2934 
   2935 double WebView::zoomLevelToZoomFactor(double zoomLevel)
   2936 {
   2937     return pow(textSizeMultiplierRatio, zoomLevel);
   2938 }
   2939 
   2940 double WebView::zoomFactorToZoomLevel(double factor)
   2941 {
   2942     // Since factor = 1.2^level, level = log(factor) / log(1.2)
   2943     return log(factor) / log(textSizeMultiplierRatio);
   2944 }
   2945 
   2946 float WebViewImpl::pageScaleFactor() const
   2947 {
   2948     if (!page())
   2949         return 1;
   2950 
   2951     if (!pinchVirtualViewportEnabled())
   2952         return page()->pageScaleFactor();
   2953 
   2954     return page()->frameHost().pinchViewport().scale();
   2955 }
   2956 
   2957 float WebViewImpl::clampPageScaleFactorToLimits(float scaleFactor) const
   2958 {
   2959     return m_pageScaleConstraintsSet.finalConstraints().clampToConstraints(scaleFactor);
   2960 }
   2961 
   2962 IntPoint WebViewImpl::clampOffsetAtScale(const IntPoint& offset, float scale)
   2963 {
   2964     FrameView* view = mainFrameImpl()->frameView();
   2965     if (!view)
   2966         return offset;
   2967 
   2968     return view->clampOffsetAtScale(offset, scale);
   2969 }
   2970 
   2971 bool WebViewImpl::pinchVirtualViewportEnabled() const
   2972 {
   2973     ASSERT(page());
   2974     return page()->settings().pinchVirtualViewportEnabled();
   2975 }
   2976 
   2977 void WebViewImpl::setPinchViewportOffset(const WebFloatPoint& offset)
   2978 {
   2979     ASSERT(page());
   2980 
   2981     if (!pinchVirtualViewportEnabled())
   2982         return;
   2983 
   2984     page()->frameHost().pinchViewport().setLocation(offset);
   2985 }
   2986 
   2987 WebFloatPoint WebViewImpl::pinchViewportOffset() const
   2988 {
   2989     ASSERT(page());
   2990 
   2991     if (!pinchVirtualViewportEnabled())
   2992         return WebFloatPoint();
   2993 
   2994     return page()->frameHost().pinchViewport().visibleRect().location();
   2995 }
   2996 
   2997 void WebViewImpl::scrollAndRescaleViewports(float scaleFactor,
   2998     const IntPoint& mainFrameOrigin,
   2999     const FloatPoint& pinchViewportOrigin)
   3000 {
   3001     // Old way
   3002     if (!pinchVirtualViewportEnabled()) {
   3003         setPageScaleFactor(scaleFactor, mainFrameOrigin);
   3004         return;
   3005     }
   3006 
   3007     if (!page())
   3008         return;
   3009 
   3010     if (!mainFrameImpl())
   3011         return;
   3012 
   3013     FrameView * view = mainFrameImpl()->frameView();
   3014     if (!view)
   3015         return;
   3016 
   3017     // Order is important: pinch viewport location is clamped based on
   3018     // main frame scroll position and pinch viewport scale.
   3019 
   3020     view->setScrollOffset(mainFrameOrigin);
   3021 
   3022     setPageScaleFactor(scaleFactor);
   3023 
   3024     page()->frameHost().pinchViewport().setLocation(pinchViewportOrigin);
   3025 }
   3026 
   3027 void WebViewImpl::setPageScaleFactor(float scaleFactor)
   3028 {
   3029     ASSERT(page());
   3030 
   3031     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
   3032     if (scaleFactor == pageScaleFactor())
   3033         return;
   3034 
   3035     // TODO(bokan): Old-style pinch path. Remove when we're migrated to
   3036     // virtual viewport pinch.
   3037     if (!pinchVirtualViewportEnabled()) {
   3038         IntPoint scrollOffset(mainFrame()->scrollOffset().width, mainFrame()->scrollOffset().height);
   3039         setPageScaleFactor(scaleFactor, scrollOffset);
   3040         return;
   3041     }
   3042 
   3043     page()->frameHost().pinchViewport().setScale(scaleFactor);
   3044     deviceOrPageScaleFactorChanged();
   3045 }
   3046 
   3047 void WebViewImpl::setMainFrameScrollOffset(const WebPoint& origin)
   3048 {
   3049     updateMainFrameScrollPosition(origin, false);
   3050 }
   3051 
   3052 void WebViewImpl::setPageScaleFactor(float scaleFactor, const WebPoint& origin)
   3053 {
   3054     if (!page())
   3055         return;
   3056 
   3057     IntPoint newScrollOffset = origin;
   3058     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
   3059     newScrollOffset = clampOffsetAtScale(newScrollOffset, scaleFactor);
   3060 
   3061     if (pinchVirtualViewportEnabled())
   3062         setPageScaleFactor(scaleFactor);
   3063         // Note, we don't set the offset in the new path. This method is going
   3064         // away for the new pinch model so that's ok.
   3065     else
   3066         page()->setPageScaleFactor(scaleFactor, newScrollOffset);
   3067 }
   3068 
   3069 float WebViewImpl::deviceScaleFactor() const
   3070 {
   3071     if (!page())
   3072         return 1;
   3073 
   3074     return page()->deviceScaleFactor();
   3075 }
   3076 
   3077 void WebViewImpl::setDeviceScaleFactor(float scaleFactor)
   3078 {
   3079     if (!page())
   3080         return;
   3081 
   3082     page()->setDeviceScaleFactor(scaleFactor);
   3083 
   3084     if (m_layerTreeView)
   3085         updateLayerTreeDeviceScaleFactor();
   3086 }
   3087 
   3088 void WebViewImpl::setDeviceColorProfile(const WebVector<char>& colorProfile)
   3089 {
   3090     if (!page())
   3091         return;
   3092 
   3093     Vector<char> deviceProfile;
   3094     deviceProfile.append(colorProfile.data(), colorProfile.size());
   3095 
   3096     page()->setDeviceColorProfile(deviceProfile);
   3097 }
   3098 
   3099 void WebViewImpl::resetDeviceColorProfile()
   3100 {
   3101     if (!page())
   3102         return;
   3103 
   3104     page()->resetDeviceColorProfile();
   3105 }
   3106 
   3107 void WebViewImpl::enableAutoResizeMode(const WebSize& minSize, const WebSize& maxSize)
   3108 {
   3109     m_shouldAutoResize = true;
   3110     m_minAutoSize = minSize;
   3111     m_maxAutoSize = maxSize;
   3112     configureAutoResizeMode();
   3113 }
   3114 
   3115 void WebViewImpl::disableAutoResizeMode()
   3116 {
   3117     m_shouldAutoResize = false;
   3118     configureAutoResizeMode();
   3119 }
   3120 
   3121 void WebViewImpl::setUserAgentPageScaleConstraints(PageScaleConstraints newConstraints)
   3122 {
   3123     if (newConstraints == m_pageScaleConstraintsSet.userAgentConstraints())
   3124         return;
   3125 
   3126     m_pageScaleConstraintsSet.setUserAgentConstraints(newConstraints);
   3127 
   3128     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
   3129         return;
   3130 
   3131     mainFrameImpl()->frameView()->setNeedsLayout();
   3132 }
   3133 
   3134 void WebViewImpl::setInitialPageScaleOverride(float initialPageScaleFactorOverride)
   3135 {
   3136     PageScaleConstraints constraints = m_pageScaleConstraintsSet.userAgentConstraints();
   3137     constraints.initialScale = initialPageScaleFactorOverride;
   3138 
   3139     if (constraints == m_pageScaleConstraintsSet.userAgentConstraints())
   3140         return;
   3141 
   3142     m_pageScaleConstraintsSet.setNeedsReset(true);
   3143     setUserAgentPageScaleConstraints(constraints);
   3144 }
   3145 
   3146 void WebViewImpl::setPageScaleFactorLimits(float minPageScale, float maxPageScale)
   3147 {
   3148     PageScaleConstraints constraints = m_pageScaleConstraintsSet.userAgentConstraints();
   3149     constraints.minimumScale = minPageScale;
   3150     constraints.maximumScale = maxPageScale;
   3151     setUserAgentPageScaleConstraints(constraints);
   3152 }
   3153 
   3154 void WebViewImpl::setIgnoreViewportTagScaleLimits(bool ignore)
   3155 {
   3156     PageScaleConstraints constraints = m_pageScaleConstraintsSet.userAgentConstraints();
   3157     if (ignore) {
   3158         constraints.minimumScale = m_pageScaleConstraintsSet.defaultConstraints().minimumScale;
   3159         constraints.maximumScale = m_pageScaleConstraintsSet.defaultConstraints().maximumScale;
   3160     } else {
   3161         constraints.minimumScale = -1;
   3162         constraints.maximumScale = -1;
   3163     }
   3164     setUserAgentPageScaleConstraints(constraints);
   3165 }
   3166 
   3167 void WebViewImpl::refreshPageScaleFactorAfterLayout()
   3168 {
   3169     if (!mainFrame() || !page() || !page()->mainFrame() || !page()->mainFrame()->isLocalFrame() || !page()->deprecatedLocalMainFrame()->view())
   3170         return;
   3171     FrameView* view = page()->deprecatedLocalMainFrame()->view();
   3172 
   3173     updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
   3174     m_pageScaleConstraintsSet.computeFinalConstraints();
   3175 
   3176     if (settings()->shrinksViewportContentToFit()) {
   3177         int verticalScrollbarWidth = 0;
   3178         if (view->verticalScrollbar() && !view->verticalScrollbar()->isOverlayScrollbar())
   3179             verticalScrollbarWidth = view->verticalScrollbar()->width();
   3180         m_pageScaleConstraintsSet.adjustFinalConstraintsToContentsSize(contentsSize(), verticalScrollbarWidth);
   3181     }
   3182 
   3183     if (pinchVirtualViewportEnabled())
   3184         mainFrameImpl()->frameView()->resize(m_pageScaleConstraintsSet.mainFrameSize(contentsSize()));
   3185 
   3186     float newPageScaleFactor = pageScaleFactor();
   3187     if (m_pageScaleConstraintsSet.needsReset() && m_pageScaleConstraintsSet.finalConstraints().initialScale != -1) {
   3188         newPageScaleFactor = m_pageScaleConstraintsSet.finalConstraints().initialScale;
   3189         m_pageScaleConstraintsSet.setNeedsReset(false);
   3190     }
   3191     setPageScaleFactor(newPageScaleFactor);
   3192 
   3193     updateLayerTreeViewport();
   3194 
   3195     // Relayout immediately to avoid violating the rule that needsLayout()
   3196     // isn't set at the end of a layout.
   3197     if (view->needsLayout())
   3198         view->layout();
   3199 }
   3200 
   3201 void WebViewImpl::updatePageDefinedViewportConstraints(const ViewportDescription& description)
   3202 {
   3203     if (!settings()->viewportEnabled() || !page() || (!m_size.width && !m_size.height) || !page()->mainFrame()->isLocalFrame())
   3204         return;
   3205 
   3206     Document* document = page()->deprecatedLocalMainFrame()->document();
   3207 
   3208     m_matchesHeuristicsForGpuRasterization = description.maxWidth == Length(DeviceWidth)
   3209         && description.minZoom == 1.0
   3210         && description.minZoomIsExplicit;
   3211     if (m_layerTreeView)
   3212         m_layerTreeView->heuristicsForGpuRasterizationUpdated(m_matchesHeuristicsForGpuRasterization);
   3213 
   3214     Length defaultMinWidth = document->viewportDefaultMinWidth();
   3215     if (defaultMinWidth.isAuto())
   3216         defaultMinWidth = Length(ExtendToZoom);
   3217 
   3218     ViewportDescription adjustedDescription = description;
   3219     if (settingsImpl()->viewportMetaLayoutSizeQuirk() && adjustedDescription.type == ViewportDescription::ViewportMeta) {
   3220         const int legacyWidthSnappingMagicNumber = 320;
   3221         if (adjustedDescription.maxWidth.isFixed() && adjustedDescription.maxWidth.value() <= legacyWidthSnappingMagicNumber)
   3222             adjustedDescription.maxWidth = Length(DeviceWidth);
   3223         if (adjustedDescription.maxHeight.isFixed() && adjustedDescription.maxHeight.value() <= m_size.height)
   3224             adjustedDescription.maxHeight = Length(DeviceHeight);
   3225         adjustedDescription.minWidth = adjustedDescription.maxWidth;
   3226         adjustedDescription.minHeight = adjustedDescription.maxHeight;
   3227     }
   3228 
   3229     float oldInitialScale = m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale;
   3230     m_pageScaleConstraintsSet.updatePageDefinedConstraints(adjustedDescription, defaultMinWidth);
   3231 
   3232     if (settingsImpl()->clobberUserAgentInitialScaleQuirk()
   3233         && m_pageScaleConstraintsSet.userAgentConstraints().initialScale != -1
   3234         && m_pageScaleConstraintsSet.userAgentConstraints().initialScale * deviceScaleFactor() <= 1) {
   3235         if (description.maxWidth == Length(DeviceWidth)
   3236             || (description.maxWidth.type() == Auto && m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale == 1.0f))
   3237             setInitialPageScaleOverride(-1);
   3238     }
   3239 
   3240     m_pageScaleConstraintsSet.adjustForAndroidWebViewQuirks(adjustedDescription, defaultMinWidth.intValue(), deviceScaleFactor(), settingsImpl()->supportDeprecatedTargetDensityDPI(), page()->settings().wideViewportQuirkEnabled(), page()->settings().useWideViewport(), page()->settings().loadWithOverviewMode(), settingsImpl()->viewportMetaNonUserScalableQuirk());
   3241     float newInitialScale = m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale;
   3242     if (oldInitialScale != newInitialScale && newInitialScale != -1) {
   3243         m_pageScaleConstraintsSet.setNeedsReset(true);
   3244         if (mainFrameImpl() && mainFrameImpl()->frameView())
   3245             mainFrameImpl()->frameView()->setNeedsLayout();
   3246     }
   3247 
   3248     updateMainFrameLayoutSize();
   3249 
   3250     if (LocalFrame* frame = page()->deprecatedLocalMainFrame()) {
   3251         if (TextAutosizer* textAutosizer = frame->document()->textAutosizer())
   3252             textAutosizer->updatePageInfoInAllFrames();
   3253     }
   3254 }
   3255 
   3256 void WebViewImpl::updateMainFrameLayoutSize()
   3257 {
   3258     if (m_shouldAutoResize || !mainFrameImpl())
   3259         return;
   3260 
   3261     RefPtr<FrameView> view = mainFrameImpl()->frameView();
   3262     if (!view)
   3263         return;
   3264 
   3265     WebSize layoutSize = m_size;
   3266 
   3267     if (settings()->viewportEnabled())
   3268         layoutSize = flooredIntSize(m_pageScaleConstraintsSet.pageDefinedConstraints().layoutSize);
   3269 
   3270     if (page()->settings().forceZeroLayoutHeight())
   3271         layoutSize.height = 0;
   3272 
   3273     view->setLayoutSize(layoutSize);
   3274 }
   3275 
   3276 IntSize WebViewImpl::contentsSize() const
   3277 {
   3278     if (!page()->mainFrame()->isLocalFrame())
   3279         return IntSize();
   3280     RenderView* root = page()->deprecatedLocalMainFrame()->contentRenderer();
   3281     if (!root)
   3282         return IntSize();
   3283     return root->documentRect().size();
   3284 }
   3285 
   3286 WebSize WebViewImpl::contentsPreferredMinimumSize()
   3287 {
   3288     Document* document = m_page->mainFrame()->isLocalFrame() ? m_page->deprecatedLocalMainFrame()->document() : 0;
   3289     if (!document || !document->renderView() || !document->documentElement())
   3290         return WebSize();
   3291 
   3292     layout();
   3293     FontCachePurgePreventer fontCachePurgePreventer; // Required by minPreferredLogicalWidth().
   3294     IntSize preferredMinimumSize(document->renderView()->minPreferredLogicalWidth(), document->documentElement()->scrollHeight());
   3295     preferredMinimumSize.scale(zoomLevelToZoomFactor(zoomLevel()));
   3296     return preferredMinimumSize;
   3297 }
   3298 
   3299 float WebViewImpl::minimumPageScaleFactor() const
   3300 {
   3301     return m_pageScaleConstraintsSet.finalConstraints().minimumScale;
   3302 }
   3303 
   3304 float WebViewImpl::maximumPageScaleFactor() const
   3305 {
   3306     return m_pageScaleConstraintsSet.finalConstraints().maximumScale;
   3307 }
   3308 
   3309 void WebViewImpl::resetScrollAndScaleState()
   3310 {
   3311     // TODO: This is done by the pinchViewport().reset() call below and can be removed when
   3312     // the new pinch path is the only one.
   3313     setPageScaleFactor(1);
   3314     updateMainFrameScrollPosition(IntPoint(), true);
   3315     page()->frameHost().pinchViewport().reset();
   3316 
   3317     if (!page()->mainFrame()->isLocalFrame())
   3318         return;
   3319 
   3320     // Clear out the values for the current history item. This will prevent the history item from clobbering the
   3321     // value determined during page scale initialization, which may be less than 1.
   3322     page()->deprecatedLocalMainFrame()->loader().clearScrollPositionAndViewState();
   3323     m_pageScaleConstraintsSet.setNeedsReset(true);
   3324 
   3325     // Clobber saved scales and scroll offsets.
   3326     if (FrameView* view = page()->deprecatedLocalMainFrame()->document()->view())
   3327         view->cacheCurrentScrollPosition();
   3328 }
   3329 
   3330 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
   3331                                            const WebPoint& location)
   3332 {
   3333     HitTestResult result = hitTestResultForWindowPos(location);
   3334     RefPtrWillBeRawPtr<Node> node = result.innerNonSharedNode();
   3335     if (!isHTMLVideoElement(*node) && !isHTMLAudioElement(*node))
   3336         return;
   3337 
   3338     RefPtrWillBeRawPtr<HTMLMediaElement> mediaElement = static_pointer_cast<HTMLMediaElement>(node);
   3339     switch (action.type) {
   3340     case WebMediaPlayerAction::Play:
   3341         if (action.enable)
   3342             mediaElement->play();
   3343         else
   3344             mediaElement->pause();
   3345         break;
   3346     case WebMediaPlayerAction::Mute:
   3347         mediaElement->setMuted(action.enable);
   3348         break;
   3349     case WebMediaPlayerAction::Loop:
   3350         mediaElement->setLoop(action.enable);
   3351         break;
   3352     case WebMediaPlayerAction::Controls:
   3353         mediaElement->setBooleanAttribute(HTMLNames::controlsAttr, action.enable);
   3354         break;
   3355     default:
   3356         ASSERT_NOT_REACHED();
   3357     }
   3358 }
   3359 
   3360 void WebViewImpl::performPluginAction(const WebPluginAction& action,
   3361                                       const WebPoint& location)
   3362 {
   3363     HitTestResult result = hitTestResultForWindowPos(location);
   3364     RefPtrWillBeRawPtr<Node> node = result.innerNonSharedNode();
   3365     if (!isHTMLObjectElement(*node) && !isHTMLEmbedElement(*node))
   3366         return;
   3367 
   3368     RenderObject* object = node->renderer();
   3369     if (object && object->isWidget()) {
   3370         Widget* widget = toRenderWidget(object)->widget();
   3371         if (widget && widget->isPluginContainer()) {
   3372             WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget);
   3373             switch (action.type) {
   3374             case WebPluginAction::Rotate90Clockwise:
   3375                 plugin->plugin()->rotateView(WebPlugin::RotationType90Clockwise);
   3376                 break;
   3377             case WebPluginAction::Rotate90Counterclockwise:
   3378                 plugin->plugin()->rotateView(WebPlugin::RotationType90Counterclockwise);
   3379                 break;
   3380             default:
   3381                 ASSERT_NOT_REACHED();
   3382             }
   3383         }
   3384     }
   3385 }
   3386 
   3387 WebHitTestResult WebViewImpl::hitTestResultAt(const WebPoint& point)
   3388 {
   3389     return coreHitTestResultAt(point);
   3390 }
   3391 
   3392 HitTestResult WebViewImpl::coreHitTestResultAt(const WebPoint& point)
   3393 {
   3394     IntPoint scaledPoint = point;
   3395     scaledPoint.scale(1 / pageScaleFactor(), 1 / pageScaleFactor());
   3396     return hitTestResultForWindowPos(scaledPoint);
   3397 }
   3398 
   3399 void WebViewImpl::copyImageAt(const WebPoint& point)
   3400 {
   3401     if (!m_page)
   3402         return;
   3403 
   3404     HitTestResult result = hitTestResultForWindowPos(point);
   3405     Node* node = result.innerNonSharedNode();
   3406     ASSERT(node);
   3407 
   3408     if (!isHTMLCanvasElement(*node) && result.absoluteImageURL().isEmpty()) {
   3409         // There isn't actually an image at these coordinates.  Might be because
   3410         // the window scrolled while the context menu was open or because the page
   3411         // changed itself between when we thought there was an image here and when
   3412         // we actually tried to retreive the image.
   3413         //
   3414         // FIXME: implement a cache of the most recent HitTestResult to avoid having
   3415         //        to do two hit tests.
   3416         return;
   3417     }
   3418 
   3419     m_page->deprecatedLocalMainFrame()->editor().copyImage(result);
   3420 }
   3421 
   3422 void WebViewImpl::saveImageAt(const WebPoint& point)
   3423 {
   3424     if (!m_client)
   3425         return;
   3426 
   3427     Node* node = hitTestResultForWindowPos(point).innerNonSharedNode();
   3428     if (!node || !(isHTMLCanvasElement(*node) || isHTMLImageElement(*node)))
   3429         return;
   3430 
   3431     String url = toElement(*node).imageSourceURL();
   3432     if (!KURL(KURL(), url).protocolIsData())
   3433         return;
   3434 
   3435     m_client->saveImageFromDataURL(url);
   3436 }
   3437 
   3438 void WebViewImpl::dragSourceEndedAt(
   3439     const WebPoint& clientPoint,
   3440     const WebPoint& screenPoint,
   3441     WebDragOperation operation)
   3442 {
   3443     PlatformMouseEvent pme(clientPoint, screenPoint, LeftButton, PlatformEvent::MouseMoved,
   3444         0, false, false, false, false, PlatformMouseEvent::RealOrIndistinguishable, 0);
   3445     m_page->deprecatedLocalMainFrame()->eventHandler().dragSourceEndedAt(pme,
   3446         static_cast<DragOperation>(operation));
   3447 }
   3448 
   3449 void WebViewImpl::dragSourceSystemDragEnded()
   3450 {
   3451     // It's possible for us to get this callback while not doing a drag if
   3452     // it's from a previous page that got unloaded.
   3453     if (m_doingDragAndDrop) {
   3454         m_page->dragController().dragEnded();
   3455         m_doingDragAndDrop = false;
   3456     }
   3457 }
   3458 
   3459 WebDragOperation WebViewImpl::dragTargetDragEnter(
   3460     const WebDragData& webDragData,
   3461     const WebPoint& clientPoint,
   3462     const WebPoint& screenPoint,
   3463     WebDragOperationsMask operationsAllowed,
   3464     int keyModifiers)
   3465 {
   3466     ASSERT(!m_currentDragData);
   3467 
   3468     m_currentDragData = webDragData.getValue();
   3469     m_operationsAllowed = operationsAllowed;
   3470 
   3471     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragEnter, keyModifiers);
   3472 }
   3473 
   3474 WebDragOperation WebViewImpl::dragTargetDragOver(
   3475     const WebPoint& clientPoint,
   3476     const WebPoint& screenPoint,
   3477     WebDragOperationsMask operationsAllowed,
   3478     int keyModifiers)
   3479 {
   3480     m_operationsAllowed = operationsAllowed;
   3481 
   3482     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragOver, keyModifiers);
   3483 }
   3484 
   3485 void WebViewImpl::dragTargetDragLeave()
   3486 {
   3487     ASSERT(m_currentDragData);
   3488 
   3489     DragData dragData(
   3490         m_currentDragData.get(),
   3491         IntPoint(),
   3492         IntPoint(),
   3493         static_cast<DragOperation>(m_operationsAllowed));
   3494 
   3495     m_page->dragController().dragExited(&dragData);
   3496 
   3497     // FIXME: why is the drag scroll timer not stopped here?
   3498 
   3499     m_dragOperation = WebDragOperationNone;
   3500     m_currentDragData = nullptr;
   3501 }
   3502 
   3503 void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
   3504                                  const WebPoint& screenPoint,
   3505                                  int keyModifiers)
   3506 {
   3507     ASSERT(m_currentDragData);
   3508 
   3509     UserGestureNotifier notifier(m_autofillClient, &m_userGestureObserved);
   3510 
   3511     // If this webview transitions from the "drop accepting" state to the "not
   3512     // accepting" state, then our IPC message reply indicating that may be in-
   3513     // flight, or else delayed by javascript processing in this webview.  If a
   3514     // drop happens before our IPC reply has reached the browser process, then
   3515     // the browser forwards the drop to this webview.  So only allow a drop to
   3516     // proceed if our webview m_dragOperation state is not DragOperationNone.
   3517 
   3518     if (m_dragOperation == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop.
   3519         dragTargetDragLeave();
   3520         return;
   3521     }
   3522 
   3523     m_currentDragData->setModifierKeyState(webInputEventKeyStateToPlatformEventKeyState(keyModifiers));
   3524     DragData dragData(
   3525         m_currentDragData.get(),
   3526         clientPoint,
   3527         screenPoint,
   3528         static_cast<DragOperation>(m_operationsAllowed));
   3529 
   3530     UserGestureIndicator gesture(DefinitelyProcessingNewUserGesture);
   3531     m_page->dragController().performDrag(&dragData);
   3532 
   3533     m_dragOperation = WebDragOperationNone;
   3534     m_currentDragData = nullptr;
   3535 }
   3536 
   3537 void WebViewImpl::spellingMarkers(WebVector<uint32_t>* markers)
   3538 {
   3539     Vector<uint32_t> result;
   3540     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
   3541         if (!frame->isLocalFrame())
   3542             continue;
   3543         const DocumentMarkerVector& documentMarkers = toLocalFrame(frame)->document()->markers().markers();
   3544         for (size_t i = 0; i < documentMarkers.size(); ++i)
   3545             result.append(documentMarkers[i]->hash());
   3546     }
   3547     markers->assign(result);
   3548 }
   3549 
   3550 void WebViewImpl::removeSpellingMarkersUnderWords(const WebVector<WebString>& words)
   3551 {
   3552     Vector<String> convertedWords;
   3553     convertedWords.append(words.data(), words.size());
   3554 
   3555     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
   3556         if (frame->isLocalFrame())
   3557             toLocalFrame(frame)->removeSpellingMarkersUnderWords(convertedWords);
   3558     }
   3559 }
   3560 
   3561 WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPoint, const WebPoint& screenPoint, DragAction dragAction, int keyModifiers)
   3562 {
   3563     ASSERT(m_currentDragData);
   3564 
   3565     m_currentDragData->setModifierKeyState(webInputEventKeyStateToPlatformEventKeyState(keyModifiers));
   3566     DragData dragData(
   3567         m_currentDragData.get(),
   3568         clientPoint,
   3569         screenPoint,
   3570         static_cast<DragOperation>(m_operationsAllowed));
   3571 
   3572     DragSession dragSession;
   3573     if (dragAction == DragEnter)
   3574         dragSession = m_page->dragController().dragEntered(&dragData);
   3575     else
   3576         dragSession = m_page->dragController().dragUpdated(&dragData);
   3577 
   3578     DragOperation dropEffect = dragSession.operation;
   3579 
   3580     // Mask the drop effect operation against the drag source's allowed operations.
   3581     if (!(dropEffect & dragData.draggingSourceOperationMask()))
   3582         dropEffect = DragOperationNone;
   3583 
   3584      m_dragOperation = static_cast<WebDragOperation>(dropEffect);
   3585 
   3586     return m_dragOperation;
   3587 }
   3588 
   3589 void WebViewImpl::sendResizeEventAndRepaint()
   3590 {
   3591     // FIXME: This is wrong. The FrameView is responsible sending a resizeEvent
   3592     // as part of layout. Layout is also responsible for sending invalidations
   3593     // to the embedder. This method and all callers may be wrong. -- eseidel.
   3594     if (localFrameRootTemporary()->frameView()) {
   3595         // Enqueues the resize event.
   3596         localFrameRootTemporary()->frame()->document()->enqueueResizeEvent();
   3597     }
   3598 
   3599     if (m_client) {
   3600         if (isAcceleratedCompositingActive()) {
   3601             updateLayerTreeViewport();
   3602         } else {
   3603             WebRect damagedRect(0, 0, m_size.width, m_size.height);
   3604             m_client->didInvalidateRect(damagedRect);
   3605         }
   3606     }
   3607     if (m_pageOverlays)
   3608         m_pageOverlays->update();
   3609 }
   3610 
   3611 void WebViewImpl::configureAutoResizeMode()
   3612 {
   3613     if (!mainFrameImpl() || !mainFrameImpl()->frame() || !mainFrameImpl()->frame()->view())
   3614         return;
   3615 
   3616     if (m_shouldAutoResize)
   3617         mainFrameImpl()->frame()->view()->enableAutoSizeMode(m_minAutoSize, m_maxAutoSize);
   3618     else
   3619         mainFrameImpl()->frame()->view()->disableAutoSizeMode();
   3620 }
   3621 
   3622 unsigned long WebViewImpl::createUniqueIdentifierForRequest()
   3623 {
   3624     return createUniqueIdentifier();
   3625 }
   3626 
   3627 void WebViewImpl::inspectElementAt(const WebPoint& point)
   3628 {
   3629     if (!m_page)
   3630         return;
   3631 
   3632     if (point.x == -1 || point.y == -1) {
   3633         m_page->inspectorController().inspect(0);
   3634     } else {
   3635         HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::AllowChildFrameContent;
   3636         HitTestRequest request(hitType);
   3637 
   3638         WebMouseEvent dummyEvent;
   3639         dummyEvent.type = WebInputEvent::MouseDown;
   3640         dummyEvent.x = point.x;
   3641         dummyEvent.y = point.y;
   3642         IntPoint transformedPoint = PlatformMouseEventBuilder(m_page->deprecatedLocalMainFrame()->view(), dummyEvent).position();
   3643         HitTestResult result(m_page->deprecatedLocalMainFrame()->view()->windowToContents(transformedPoint));
   3644         m_page->deprecatedLocalMainFrame()->contentRenderer()->hitTest(request, result);
   3645         Node* node = result.innerNode();
   3646         if (!node && m_page->deprecatedLocalMainFrame()->document())
   3647             node = m_page->deprecatedLocalMainFrame()->document()->documentElement();
   3648         m_page->inspectorController().inspect(node);
   3649     }
   3650 }
   3651 
   3652 void WebViewImpl::setCompositorDeviceScaleFactorOverride(float deviceScaleFactor)
   3653 {
   3654     if (m_compositorDeviceScaleFactorOverride == deviceScaleFactor)
   3655         return;
   3656     m_compositorDeviceScaleFactorOverride = deviceScaleFactor;
   3657     if (page() && m_layerTreeView)
   3658         updateLayerTreeDeviceScaleFactor();
   3659 }
   3660 
   3661 void WebViewImpl::setRootLayerTransform(const WebSize& rootLayerOffset, float rootLayerScale)
   3662 {
   3663     if (m_rootLayerScale == rootLayerScale && m_rootLayerOffset == rootLayerOffset)
   3664         return;
   3665     m_rootLayerScale = rootLayerScale;
   3666     m_rootLayerOffset = rootLayerOffset;
   3667     if (mainFrameImpl())
   3668         mainFrameImpl()->setInputEventsTransformForEmulation(m_rootLayerOffset, m_rootLayerScale);
   3669     updateRootLayerTransform();
   3670 }
   3671 
   3672 WebDevToolsAgent* WebViewImpl::devToolsAgent()
   3673 {
   3674     return m_devToolsAgent.get();
   3675 }
   3676 
   3677 WebAXObject WebViewImpl::accessibilityObject()
   3678 {
   3679     if (!mainFrameImpl())
   3680         return WebAXObject();
   3681 
   3682     Document* document = mainFrameImpl()->frame()->document();
   3683     return WebAXObject(
   3684         document->axObjectCache()->getOrCreate(document->renderView()));
   3685 }
   3686 
   3687 void WebViewImpl::performCustomContextMenuAction(unsigned action)
   3688 {
   3689     if (!m_page)
   3690         return;
   3691     ContextMenu* menu = m_page->contextMenuController().contextMenu();
   3692     if (!menu)
   3693         return;
   3694     const ContextMenuItem* item = menu->itemWithAction(static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + action));
   3695     if (item)
   3696         m_page->contextMenuController().contextMenuItemSelected(item);
   3697     m_page->contextMenuController().clearContextMenu();
   3698 }
   3699 
   3700 void WebViewImpl::showContextMenu()
   3701 {
   3702     if (!page())
   3703         return;
   3704 
   3705     page()->contextMenuController().clearContextMenu();
   3706     m_contextMenuAllowed = true;
   3707     if (LocalFrame* focusedFrame = toLocalFrame(page()->focusController().focusedOrMainFrame()))
   3708         focusedFrame->eventHandler().sendContextMenuEventForKey();
   3709     m_contextMenuAllowed = false;
   3710 }
   3711 
   3712 void WebViewImpl::extractSmartClipData(WebRect rect, WebString& clipText, WebString& clipHtml, WebRect& clipRect)
   3713 {
   3714     LocalFrame* localFrame = toLocalFrame(focusedCoreFrame());
   3715     if (!localFrame)
   3716         return;
   3717     SmartClipData clipData = SmartClip(localFrame).dataForRect(rect);
   3718     clipText = clipData.clipData();
   3719     clipRect = clipData.rect();
   3720 
   3721     WebLocalFrameImpl* frame = mainFrameImpl();
   3722     if (!frame)
   3723         return;
   3724     WebPoint startPoint(rect.x, rect.y);
   3725     WebPoint endPoint(rect.x + rect.width, rect.y + rect.height);
   3726     VisiblePosition startVisiblePosition = frame->visiblePositionForWindowPoint(startPoint);
   3727     VisiblePosition endVisiblePosition = frame->visiblePositionForWindowPoint(endPoint);
   3728 
   3729     Position startPosition = startVisiblePosition.deepEquivalent();
   3730     Position endPosition = endVisiblePosition.deepEquivalent();
   3731 
   3732     // document() will return null if -webkit-user-select is set to none.
   3733     if (!startPosition.document() || !endPosition.document())
   3734         return;
   3735 
   3736     RefPtrWillBeRawPtr<Range> range = Range::create(*startPosition.document(), startPosition, endPosition);
   3737     if (!range)
   3738         return;
   3739 
   3740     clipHtml = createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
   3741 }
   3742 
   3743 void WebViewImpl::hidePopups()
   3744 {
   3745     hideSelectPopup();
   3746     if (m_pagePopup)
   3747         closePagePopup(m_pagePopup.get());
   3748 }
   3749 
   3750 void WebViewImpl::setIsTransparent(bool isTransparent)
   3751 {
   3752     // Set any existing frames to be transparent.
   3753     Frame* frame = m_page->mainFrame();
   3754     while (frame) {
   3755         if (frame->isLocalFrame())
   3756             toLocalFrame(frame)->view()->setTransparent(isTransparent);
   3757         frame = frame->tree().traverseNext();
   3758     }
   3759 
   3760     // Future frames check this to know whether to be transparent.
   3761     m_isTransparent = isTransparent;
   3762 }
   3763 
   3764 bool WebViewImpl::isTransparent() const
   3765 {
   3766     return m_isTransparent;
   3767 }
   3768 
   3769 void WebViewImpl::setBaseBackgroundColor(WebColor color)
   3770 {
   3771     layout();
   3772 
   3773     if (m_baseBackgroundColor == color)
   3774         return;
   3775 
   3776     m_baseBackgroundColor = color;
   3777 
   3778     if (m_page->mainFrame() && m_page->mainFrame()->isLocalFrame())
   3779         m_page->deprecatedLocalMainFrame()->view()->setBaseBackgroundColor(color);
   3780 
   3781     updateLayerTreeBackgroundColor();
   3782 }
   3783 
   3784 void WebViewImpl::setIsActive(bool active)
   3785 {
   3786     if (page())
   3787         page()->focusController().setActive(active);
   3788 }
   3789 
   3790 bool WebViewImpl::isActive() const
   3791 {
   3792     return page() ? page()->focusController().isActive() : false;
   3793 }
   3794 
   3795 void WebViewImpl::setDomainRelaxationForbidden(bool forbidden, const WebString& scheme)
   3796 {
   3797     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme));
   3798 }
   3799 
   3800 void WebViewImpl::setWindowFeatures(const WebWindowFeatures& features)
   3801 {
   3802     m_page->chrome().setWindowFeatures(features);
   3803 }
   3804 
   3805 void WebViewImpl::setOpenedByDOM()
   3806 {
   3807     m_page->setOpenedByDOM();
   3808 }
   3809 
   3810 void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor,
   3811                                      unsigned activeForegroundColor,
   3812                                      unsigned inactiveBackgroundColor,
   3813                                      unsigned inactiveForegroundColor) {
   3814 #if USE(DEFAULT_RENDER_THEME)
   3815     RenderThemeChromiumDefault::setSelectionColors(activeBackgroundColor, activeForegroundColor, inactiveBackgroundColor, inactiveForegroundColor);
   3816     RenderTheme::theme().platformColorsDidChange();
   3817 #endif
   3818 }
   3819 
   3820 void WebView::injectStyleSheet(const WebString& sourceCode, const WebVector<WebString>& patternsIn, WebView::StyleInjectionTarget injectIn)
   3821 {
   3822     Vector<String> patterns;
   3823     for (size_t i = 0; i < patternsIn.size(); ++i)
   3824         patterns.append(patternsIn[i]);
   3825 
   3826     InjectedStyleSheets::instance().add(sourceCode, patterns, static_cast<blink::StyleInjectionTarget>(injectIn));
   3827 }
   3828 
   3829 void WebView::removeInjectedStyleSheets()
   3830 {
   3831     InjectedStyleSheets::instance().removeAll();
   3832 }
   3833 
   3834 void WebViewImpl::didCommitLoad(bool isNewNavigation, bool isNavigationWithinPage)
   3835 {
   3836     if (isNewNavigation && !isNavigationWithinPage)
   3837         m_pageScaleConstraintsSet.setNeedsReset(true);
   3838 
   3839     // Make sure link highlight from previous page is cleared.
   3840     m_linkHighlights.clear();
   3841     endActiveFlingAnimation();
   3842     m_userGestureObserved = false;
   3843 }
   3844 
   3845 void WebViewImpl::willInsertBody(WebLocalFrameImpl* webframe)
   3846 {
   3847     if (webframe != mainFrameImpl())
   3848         return;
   3849 
   3850     if (!m_page->mainFrame()->isLocalFrame())
   3851         return;
   3852 
   3853     // If we get to the <body> tag and we have no pending stylesheet and import load, we
   3854     // can be fairly confident we'll have something sensible to paint soon and
   3855     // can turn off deferred commits.
   3856     if (m_page->deprecatedLocalMainFrame()->document()->isRenderingReady())
   3857         resumeTreeViewCommits();
   3858 }
   3859 
   3860 void WebViewImpl::didRemoveAllPendingStylesheet(WebLocalFrameImpl* webframe)
   3861 {
   3862     if (webframe != mainFrameImpl())
   3863         return;
   3864 
   3865     // If we have no more stylesheets to load and we're past the body tag,
   3866     // we should have something to paint and should start as soon as possible.
   3867     if (m_page->deprecatedLocalMainFrame()->document()->body())
   3868         resumeTreeViewCommits();
   3869 }
   3870 
   3871 void WebViewImpl::resumeTreeViewCommits()
   3872 {
   3873     if (m_layerTreeViewCommitsDeferred) {
   3874         if (m_layerTreeView)
   3875             m_layerTreeView->setDeferCommits(false);
   3876         m_layerTreeViewCommitsDeferred = false;
   3877     }
   3878 }
   3879 
   3880 void WebViewImpl::layoutUpdated(WebLocalFrameImpl* webframe)
   3881 {
   3882     if (!m_client || !webframe->frame()->isLocalRoot())
   3883         return;
   3884 
   3885     // If we finished a layout while in deferred commit mode,
   3886     // that means it's time to start producing frames again so un-defer.
   3887     resumeTreeViewCommits();
   3888 
   3889     if (m_shouldAutoResize && webframe->frame() && webframe->frame()->view()) {
   3890         WebSize frameSize = webframe->frame()->view()->frameRect().size();
   3891         if (frameSize != m_size) {
   3892             m_size = frameSize;
   3893 
   3894             page()->frameHost().pinchViewport().setSize(m_size);
   3895             m_pageScaleConstraintsSet.didChangeViewSize(m_size);
   3896 
   3897             m_client->didAutoResize(m_size);
   3898             sendResizeEventAndRepaint();
   3899         }
   3900     }
   3901 
   3902     if (m_pageScaleConstraintsSet.constraintsDirty())
   3903         refreshPageScaleFactorAfterLayout();
   3904 
   3905     m_client->didUpdateLayout();
   3906 }
   3907 
   3908 void WebViewImpl::didChangeContentsSize()
   3909 {
   3910     m_pageScaleConstraintsSet.didChangeContentsSize(contentsSize(), pageScaleFactor());
   3911 }
   3912 
   3913 void WebViewImpl::deviceOrPageScaleFactorChanged()
   3914 {
   3915     m_pageScaleConstraintsSet.setNeedsReset(false);
   3916     updateLayerTreeViewport();
   3917     m_page->inspectorController().deviceOrPageScaleFactorChanged();
   3918 }
   3919 
   3920 bool WebViewImpl::useExternalPopupMenus()
   3921 {
   3922     return shouldUseExternalPopupMenus;
   3923 }
   3924 
   3925 void WebViewImpl::startDragging(LocalFrame* frame,
   3926                                 const WebDragData& dragData,
   3927                                 WebDragOperationsMask mask,
   3928                                 const WebImage& dragImage,
   3929                                 const WebPoint& dragImageOffset)
   3930 {
   3931     if (!m_client)
   3932         return;
   3933     ASSERT(!m_doingDragAndDrop);
   3934     m_doingDragAndDrop = true;
   3935     m_client->startDragging(WebLocalFrameImpl::fromFrame(frame), dragData, mask, dragImage, dragImageOffset);
   3936 }
   3937 
   3938 void WebViewImpl::setIgnoreInputEvents(bool newValue)
   3939 {
   3940     ASSERT(m_ignoreInputEvents != newValue);
   3941     m_ignoreInputEvents = newValue;
   3942 }
   3943 
   3944 void WebViewImpl::setBackgroundColorOverride(WebColor color)
   3945 {
   3946     m_backgroundColorOverride = color;
   3947     updateLayerTreeBackgroundColor();
   3948 }
   3949 
   3950 void WebViewImpl::setZoomFactorOverride(float zoomFactor)
   3951 {
   3952     m_zoomFactorOverride = zoomFactor;
   3953     setZoomLevel(zoomLevel());
   3954 }
   3955 
   3956 void WebViewImpl::addPageOverlay(WebPageOverlay* overlay, int zOrder)
   3957 {
   3958     if (!m_pageOverlays)
   3959         m_pageOverlays = PageOverlayList::create(this);
   3960 
   3961     m_pageOverlays->add(overlay, zOrder);
   3962 }
   3963 
   3964 void WebViewImpl::removePageOverlay(WebPageOverlay* overlay)
   3965 {
   3966     if (m_pageOverlays && m_pageOverlays->remove(overlay) && m_pageOverlays->empty())
   3967         m_pageOverlays = nullptr;
   3968 }
   3969 
   3970 void WebViewImpl::setOverlayLayer(GraphicsLayer* layer)
   3971 {
   3972     if (!m_rootGraphicsLayer)
   3973         return;
   3974 
   3975     if (!m_page->mainFrame()->isLocalFrame())
   3976         return;
   3977 
   3978     if (pinchVirtualViewportEnabled()) {
   3979         m_page->deprecatedLocalMainFrame()->view()->renderView()->compositor()->setOverlayLayer(layer);
   3980         return;
   3981     }
   3982 
   3983     // FIXME(bokan): This path goes away after virtual viewport pinch is enabled everywhere.
   3984     if (!m_rootTransformLayer)
   3985         m_rootTransformLayer = m_page->deprecatedLocalMainFrame()->view()->renderView()->compositor()->ensureRootTransformLayer();
   3986 
   3987     if (m_rootTransformLayer) {
   3988         if (layer->parent() != m_rootTransformLayer)
   3989             m_rootTransformLayer->addChild(layer);
   3990     }
   3991 }
   3992 
   3993 Element* WebViewImpl::focusedElement() const
   3994 {
   3995     Frame* frame = m_page->focusController().focusedFrame();
   3996     if (!frame || !frame->isLocalFrame())
   3997         return 0;
   3998 
   3999     Document* document = toLocalFrame(frame)->document();
   4000     if (!document)
   4001         return 0;
   4002 
   4003     return document->focusedElement();
   4004 }
   4005 
   4006 HitTestResult WebViewImpl::hitTestResultForWindowPos(const IntPoint& pos)
   4007 {
   4008     if (!m_page->mainFrame()->isLocalFrame())
   4009         return HitTestResult();
   4010     IntPoint docPoint(m_page->deprecatedLocalMainFrame()->view()->windowToContents(pos));
   4011     HitTestResult result = m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
   4012     result.setToShadowHostIfInUserAgentShadowRoot();
   4013     return result;
   4014 }
   4015 
   4016 void WebViewImpl::setTabsToLinks(bool enable)
   4017 {
   4018     m_tabsToLinks = enable;
   4019 }
   4020 
   4021 bool WebViewImpl::tabsToLinks() const
   4022 {
   4023     return m_tabsToLinks;
   4024 }
   4025 
   4026 void WebViewImpl::suppressInvalidations(bool enable)
   4027 {
   4028     if (m_client)
   4029         m_client->suppressCompositorScheduling(enable);
   4030 }
   4031 
   4032 void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
   4033 {
   4034     suppressInvalidations(true);
   4035 
   4036     if (pinchVirtualViewportEnabled()) {
   4037         PinchViewport& pinchViewport = page()->frameHost().pinchViewport();
   4038         pinchViewport.attachToLayerTree(layer, graphicsLayerFactory());
   4039         if (layer) {
   4040             m_rootGraphicsLayer = pinchViewport.rootGraphicsLayer();
   4041             m_rootLayer = pinchViewport.rootGraphicsLayer()->platformLayer();
   4042             m_rootTransformLayer = pinchViewport.rootGraphicsLayer();
   4043         } else {
   4044             m_rootGraphicsLayer = 0;
   4045             m_rootLayer = 0;
   4046             m_rootTransformLayer = 0;
   4047         }
   4048     } else {
   4049         m_rootGraphicsLayer = layer;
   4050         m_rootLayer = layer ? layer->platformLayer() : 0;
   4051         m_rootTransformLayer = 0;
   4052     }
   4053 
   4054     setIsAcceleratedCompositingActive(layer != 0);
   4055 
   4056     updateRootLayerTransform();
   4057 
   4058     if (m_layerTreeView) {
   4059         if (m_rootLayer) {
   4060             m_layerTreeView->setRootLayer(*m_rootLayer);
   4061             // We register viewport layers here since there may not be a layer
   4062             // tree view prior to this point.
   4063             if (pinchVirtualViewportEnabled()) {
   4064                 page()->frameHost().pinchViewport().registerLayersWithTreeView(m_layerTreeView);
   4065             } else {
   4066                 GraphicsLayer* rootScrollLayer = compositor()->scrollLayer();
   4067                 ASSERT(rootScrollLayer);
   4068                 WebLayer* pageScaleLayer = rootScrollLayer->parent() ? rootScrollLayer->parent()->platformLayer() : 0;
   4069                 m_layerTreeView->registerViewportLayers(pageScaleLayer, rootScrollLayer->platformLayer(), 0);
   4070             }
   4071         } else {
   4072             m_layerTreeView->clearRootLayer();
   4073             if (pinchVirtualViewportEnabled())
   4074                 page()->frameHost().pinchViewport().clearLayersForTreeView(m_layerTreeView);
   4075             else
   4076                 m_layerTreeView->clearViewportLayers();
   4077         }
   4078     }
   4079 
   4080     suppressInvalidations(false);
   4081 }
   4082 
   4083 void WebViewImpl::scheduleCompositingLayerSync()
   4084 {
   4085     m_layerTreeView->setNeedsAnimate();
   4086 }
   4087 
   4088 void WebViewImpl::invalidateRect(const IntRect& rect)
   4089 {
   4090     if (m_isAcceleratedCompositingActive) {
   4091         ASSERT(m_layerTreeView);
   4092         updateLayerTreeViewport();
   4093     } else if (m_client)
   4094         m_client->didInvalidateRect(rect);
   4095 }
   4096 
   4097 GraphicsLayerFactory* WebViewImpl::graphicsLayerFactory() const
   4098 {
   4099     return m_graphicsLayerFactory.get();
   4100 }
   4101 
   4102 RenderLayerCompositor* WebViewImpl::compositor() const
   4103 {
   4104     if (!page() || !page()->mainFrame())
   4105         return 0;
   4106 
   4107     if (!page()->mainFrame()->isLocalFrame())
   4108         return localFrameRootTemporary()->frame()->document()->renderView()->compositor();
   4109 
   4110     if (!page()->deprecatedLocalMainFrame()->document() || !page()->deprecatedLocalMainFrame()->document()->renderView())
   4111         return 0;
   4112 
   4113     return page()->deprecatedLocalMainFrame()->document()->renderView()->compositor();
   4114 }
   4115 
   4116 void WebViewImpl::registerForAnimations(WebLayer* layer)
   4117 {
   4118     if (m_layerTreeView)
   4119         m_layerTreeView->registerForAnimations(layer);
   4120 }
   4121 
   4122 GraphicsLayer* WebViewImpl::rootGraphicsLayer()
   4123 {
   4124     return m_rootGraphicsLayer;
   4125 }
   4126 
   4127 void WebViewImpl::scheduleAnimation()
   4128 {
   4129     if (m_layerTreeView) {
   4130         m_layerTreeView->setNeedsAnimate();
   4131         return;
   4132     }
   4133     if (m_client)
   4134         m_client->scheduleAnimation();
   4135 }
   4136 
   4137 void WebViewImpl::initializeLayerTreeView()
   4138 {
   4139     if (m_client) {
   4140         m_client->initializeLayerTreeView();
   4141         m_layerTreeView = m_client->layerTreeView();
   4142     }
   4143 
   4144     m_page->settings().setAcceleratedCompositingEnabled(m_layerTreeView != 0);
   4145 
   4146     // FIXME: only unittests, click to play, Android priting, and printing (for headers and footers)
   4147     // make this assert necessary. We should make them not hit this code and then delete allowsBrokenNullLayerTreeView.
   4148     ASSERT(m_layerTreeView || !m_client || m_client->allowsBrokenNullLayerTreeView());
   4149 }
   4150 
   4151 void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
   4152 {
   4153     // In the middle of shutting down; don't try to spin back up a compositor.
   4154     // FIXME: compositing startup/shutdown should be refactored so that it
   4155     // turns on explicitly rather than lazily, which causes this awkwardness.
   4156     if (m_layerTreeViewClosed)
   4157         return;
   4158 
   4159     ASSERT(!active || m_layerTreeView);
   4160     Platform::current()->histogramEnumeration("GPU.setIsAcceleratedCompositingActive", active * 2 + m_isAcceleratedCompositingActive, 4);
   4161 
   4162     if (m_isAcceleratedCompositingActive == active)
   4163         return;
   4164 
   4165     if (!m_client)
   4166         return;
   4167 
   4168     if (!active) {
   4169         m_isAcceleratedCompositingActive = false;
   4170         if (!m_layerTreeViewCommitsDeferred) {
   4171             ASSERT(m_layerTreeView);
   4172             // This means that we're transitioning to a new page. Suppress commits until WebKit generates invalidations so
   4173             // we don't attempt to paint too early in the next page load.
   4174             m_layerTreeView->setDeferCommits(true);
   4175             m_layerTreeViewCommitsDeferred = true;
   4176         }
   4177     } else {
   4178         TRACE_EVENT0("blink", "WebViewImpl::setIsAcceleratedCompositingActive(true)");
   4179         m_layerTreeView->setRootLayer(*m_rootLayer);
   4180 
   4181         bool visible = page()->visibilityState() == PageVisibilityStateVisible;
   4182         m_layerTreeView->setVisible(visible);
   4183         updateLayerTreeDeviceScaleFactor();
   4184         m_layerTreeView->setPageScaleFactorAndLimits(pageScaleFactor(), minimumPageScaleFactor(), maximumPageScaleFactor());
   4185         updateLayerTreeBackgroundColor();
   4186         m_layerTreeView->setHasTransparentBackground(isTransparent());
   4187 #if USE(RUBBER_BANDING)
   4188         RefPtr<Image> overhangImage = OverscrollTheme::theme()->getOverhangImage();
   4189         if (overhangImage && overhangImage->nativeImageForCurrentFrame())
   4190             m_layerTreeView->setOverhangBitmap(overhangImage->nativeImageForCurrentFrame()->bitmap());
   4191 #endif
   4192         updateLayerTreeViewport();
   4193         m_isAcceleratedCompositingActive = true;
   4194         if (m_pageOverlays)
   4195             m_pageOverlays->update();
   4196         m_layerTreeView->setShowFPSCounter(m_showFPSCounter);
   4197         m_layerTreeView->setShowPaintRects(m_showPaintRects);
   4198         m_layerTreeView->setShowDebugBorders(m_showDebugBorders);
   4199         m_layerTreeView->setContinuousPaintingEnabled(m_continuousPaintingEnabled);
   4200         m_layerTreeView->setShowScrollBottleneckRects(m_showScrollBottleneckRects);
   4201         m_layerTreeView->heuristicsForGpuRasterizationUpdated(m_matchesHeuristicsForGpuRasterization);
   4202     }
   4203     if (page() && page()->mainFrame()->isLocalFrame())
   4204         page()->deprecatedLocalMainFrame()->view()->setClipsRepaints(!m_isAcceleratedCompositingActive);
   4205 }
   4206 
   4207 void WebViewImpl::updateMainFrameScrollPosition(const IntPoint& scrollPosition, bool programmaticScroll)
   4208 {
   4209     if (!page()->mainFrame()->isLocalFrame())
   4210         return;
   4211 
   4212     FrameView* frameView = page()->deprecatedLocalMainFrame()->view();
   4213     if (!frameView)
   4214         return;
   4215 
   4216     if (frameView->scrollPosition() == scrollPosition)
   4217         return;
   4218 
   4219     bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
   4220     frameView->setInProgrammaticScroll(programmaticScroll);
   4221     frameView->notifyScrollPositionChanged(scrollPosition);
   4222     frameView->setInProgrammaticScroll(oldProgrammaticScroll);
   4223 }
   4224 
   4225 void WebViewImpl::applyViewportDeltas(
   4226     const WebSize& pinchViewportDelta,
   4227     const WebSize& mainFrameDelta,
   4228     float pageScaleDelta,
   4229     float topControlsDelta)
   4230 {
   4231     // FIXME(bokan): Will be replaced in 3-sided patch once Chromium side is landed.
   4232     applyViewportDeltas(pinchViewportDelta + mainFrameDelta, pageScaleDelta, topControlsDelta);
   4233 }
   4234 
   4235 void WebViewImpl::applyViewportDeltas(const WebSize& scrollDelta, float pageScaleDelta, float topControlsDelta)
   4236 {
   4237     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
   4238         return;
   4239 
   4240     setTopControlsContentOffset(m_topControlsContentOffset + topControlsDelta);
   4241 
   4242     if (pinchVirtualViewportEnabled()) {
   4243         if (pageScaleDelta != 1) {
   4244             // When the virtual viewport is enabled, offsets are already set for us.
   4245             setPageScaleFactor(pageScaleFactor() * pageScaleDelta);
   4246             m_doubleTapZoomPending = false;
   4247         }
   4248 
   4249         return;
   4250     }
   4251 
   4252     // TODO(bokan): Old pinch path only - virtual viewport pinch scrolls are automatically updated via GraphicsLayer::DidScroll.
   4253     // this should be removed once old pinch is removed.
   4254     if (pageScaleDelta == 1) {
   4255         TRACE_EVENT_INSTANT2("blink", "WebViewImpl::applyScrollAndScale::scrollBy", "x", scrollDelta.width, "y", scrollDelta.height);
   4256         WebSize webScrollOffset = mainFrame()->scrollOffset();
   4257         IntPoint scrollOffset(webScrollOffset.width + scrollDelta.width, webScrollOffset.height + scrollDelta.height);
   4258         updateMainFrameScrollPosition(scrollOffset, false);
   4259     } else {
   4260         // The page scale changed, so apply a scale and scroll in a single
   4261         // operation.
   4262         WebSize scrollOffset = mainFrame()->scrollOffset();
   4263         scrollOffset.width += scrollDelta.width;
   4264         scrollOffset.height += scrollDelta.height;
   4265 
   4266         WebPoint scrollPoint(scrollOffset.width, scrollOffset.height);
   4267         setPageScaleFactor(pageScaleFactor() * pageScaleDelta, scrollPoint);
   4268         m_doubleTapZoomPending = false;
   4269     }
   4270 }
   4271 
   4272 void WebViewImpl::updateLayerTreeViewport()
   4273 {
   4274     if (!page() || !m_layerTreeView)
   4275         return;
   4276 
   4277     m_layerTreeView->setPageScaleFactorAndLimits(pageScaleFactor(), minimumPageScaleFactor(), maximumPageScaleFactor());
   4278 }
   4279 
   4280 void WebViewImpl::updateLayerTreeBackgroundColor()
   4281 {
   4282     if (!m_layerTreeView)
   4283         return;
   4284 
   4285     m_layerTreeView->setBackgroundColor(alphaChannel(m_backgroundColorOverride) ? m_backgroundColorOverride : backgroundColor());
   4286 }
   4287 
   4288 void WebViewImpl::updateLayerTreeDeviceScaleFactor()
   4289 {
   4290     ASSERT(page());
   4291     ASSERT(m_layerTreeView);
   4292 
   4293     float deviceScaleFactor = m_compositorDeviceScaleFactorOverride ? m_compositorDeviceScaleFactorOverride : page()->deviceScaleFactor();
   4294     m_layerTreeView->setDeviceScaleFactor(deviceScaleFactor);
   4295 }
   4296 
   4297 void WebViewImpl::updateRootLayerTransform()
   4298 {
   4299     // If we don't have a root graphics layer, we won't bother trying to find
   4300     // or update the transform layer.
   4301     if (!m_rootGraphicsLayer)
   4302         return;
   4303 
   4304     // FIXME(bokan): m_rootTransformLayer is always set here in pinch virtual viewport. This can go away once
   4305     // that's default everywhere.
   4306     if (!m_rootTransformLayer && m_page->mainFrame()->isLocalFrame())
   4307         m_rootTransformLayer = m_page->deprecatedLocalMainFrame()->view()->renderView()->compositor()->ensureRootTransformLayer();
   4308 
   4309     if (m_rootTransformLayer) {
   4310         TransformationMatrix transform;
   4311         transform.translate(m_rootLayerOffset.width, m_rootLayerOffset.height);
   4312         transform = transform.scale(m_rootLayerScale);
   4313         m_rootTransformLayer->setTransform(transform);
   4314     }
   4315 }
   4316 
   4317 bool WebViewImpl::detectContentOnTouch(const WebPoint& position)
   4318 {
   4319     HitTestResult touchHit = hitTestResultForWindowPos(position);
   4320 
   4321     if (touchHit.isContentEditable())
   4322         return false;
   4323 
   4324     Node* node = touchHit.innerNode();
   4325     if (!node || !node->isTextNode())
   4326         return false;
   4327 
   4328     // Ignore when tapping on links or nodes listening to click events, unless the click event is on the
   4329     // body element, in which case it's unlikely that the original node itself was intended to be clickable.
   4330     for (; node && !isHTMLBodyElement(*node); node = NodeRenderingTraversal::parent(node)) {
   4331         if (node->isLink() || node->willRespondToTouchEvents() || node->willRespondToMouseClickEvents())
   4332             return false;
   4333     }
   4334 
   4335     WebContentDetectionResult content = m_client->detectContentAround(touchHit);
   4336     if (!content.isValid())
   4337         return false;
   4338 
   4339     m_client->scheduleContentIntent(content.intent());
   4340     return true;
   4341 }
   4342 
   4343 void WebViewImpl::setVisibilityState(WebPageVisibilityState visibilityState,
   4344                                      bool isInitialState) {
   4345     if (!page())
   4346         return;
   4347 
   4348     ASSERT(visibilityState == WebPageVisibilityStateVisible || visibilityState == WebPageVisibilityStateHidden || visibilityState == WebPageVisibilityStatePrerender);
   4349     m_page->setVisibilityState(static_cast<PageVisibilityState>(static_cast<int>(visibilityState)), isInitialState);
   4350 
   4351     if (m_layerTreeView) {
   4352         bool visible = visibilityState == WebPageVisibilityStateVisible;
   4353         m_layerTreeView->setVisible(visible);
   4354     }
   4355 }
   4356 
   4357 bool WebViewImpl::requestPointerLock()
   4358 {
   4359     return m_client && m_client->requestPointerLock();
   4360 }
   4361 
   4362 void WebViewImpl::requestPointerUnlock()
   4363 {
   4364     if (m_client)
   4365         m_client->requestPointerUnlock();
   4366 }
   4367 
   4368 bool WebViewImpl::isPointerLocked()
   4369 {
   4370     return m_client && m_client->isPointerLocked();
   4371 }
   4372 
   4373 void WebViewImpl::pointerLockMouseEvent(const WebInputEvent& event)
   4374 {
   4375     OwnPtr<UserGestureIndicator> gestureIndicator;
   4376     AtomicString eventType;
   4377     switch (event.type) {
   4378     case WebInputEvent::MouseDown:
   4379         eventType = EventTypeNames::mousedown;
   4380         gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture));
   4381         m_pointerLockGestureToken = gestureIndicator->currentToken();
   4382         break;
   4383     case WebInputEvent::MouseUp:
   4384         eventType = EventTypeNames::mouseup;
   4385         gestureIndicator = adoptPtr(new UserGestureIndicator(m_pointerLockGestureToken.release()));
   4386         break;
   4387     case WebInputEvent::MouseMove:
   4388         eventType = EventTypeNames::mousemove;
   4389         break;
   4390     default:
   4391         ASSERT_NOT_REACHED();
   4392     }
   4393 
   4394     const WebMouseEvent& mouseEvent = static_cast<const WebMouseEvent&>(event);
   4395 
   4396     if (page())
   4397         page()->pointerLockController().dispatchLockedMouseEvent(
   4398             PlatformMouseEventBuilder(mainFrameImpl()->frameView(), mouseEvent),
   4399             eventType);
   4400 }
   4401 
   4402 bool WebViewImpl::shouldDisableDesktopWorkarounds()
   4403 {
   4404     if (!settings()->viewportEnabled())
   4405         return false;
   4406 
   4407     // A document is considered adapted to small screen UAs if one of these holds:
   4408     // 1. The author specified viewport has a constrained width that is equal to
   4409     //    the initial viewport width.
   4410     // 2. The author has disabled viewport zoom.
   4411 
   4412     const PageScaleConstraints& constraints = m_pageScaleConstraintsSet.pageDefinedConstraints();
   4413 
   4414     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
   4415         return false;
   4416 
   4417     return mainFrameImpl()->frameView()->layoutSize().width() == m_size.width
   4418         || (constraints.minimumScale == constraints.maximumScale && constraints.minimumScale != -1);
   4419 }
   4420 
   4421 } // namespace blink
   4422