/*
 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "web/WebViewImpl.h"

#include "core/CSSValueKeywords.h"
#include "core/HTMLNames.h"
#include "core/InputTypeNames.h"
#include "core/clipboard/DataObject.h"
#include "core/dom/Document.h"
#include "core/dom/Fullscreen.h"
#include "core/dom/LayoutTreeBuilderTraversal.h"
#include "core/dom/Text.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/InputMethodController.h"
#include "core/editing/iterators/TextIterator.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/editing/serializers/HTMLInterchange.h"
#include "core/editing/serializers/Serialization.h"
#include "core/events/KeyboardEvent.h"
#include "core/events/UIEventWithKeyState.h"
#include "core/events/WheelEvent.h"
#include "core/fetch/UniqueIdentifier.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/PageScaleConstraintsSet.h"
#include "core/frame/RemoteFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/SmartClip.h"
#include "core/frame/TopControls.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLPlugInElement.h"
#include "core/html/HTMLTextAreaElement.h"
#include "core/input/EventHandler.h"
#include "core/input/TouchActionUtil.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/LayoutView.h"
#include "core/layout/TextAutosizer.h"
#include "core/layout/compositing/PaintLayerCompositor.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/FrameLoaderStateMachine.h"
#include "core/page/ContextMenuController.h"
#include "core/page/ContextMenuProvider.h"
#include "core/page/DragController.h"
#include "core/page/DragData.h"
#include "core/page/DragSession.h"
#include "core/page/FocusController.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "core/page/PagePopupClient.h"
#include "core/page/PointerLockController.h"
#include "core/page/ScopedPageLoadDeferrer.h"
#include "core/page/TouchDisambiguation.h"
#include "core/paint/PaintLayer.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "modules/accessibility/AXObject.h"
#include "modules/accessibility/AXObjectCacheImpl.h"
#include "modules/credentialmanager/CredentialManagerClient.h"
#include "modules/encryptedmedia/MediaKeysController.h"
#include "modules/storage/StorageNamespaceController.h"
#include "modules/webgl/WebGLRenderingContext.h"
#include "platform/ContextMenu.h"
#include "platform/ContextMenuItem.h"
#include "platform/Cursor.h"
#include "platform/KeyboardCodes.h"
#include "platform/Logging.h"
#include "platform/NotImplemented.h"
#include "platform/PlatformGestureEvent.h"
#include "platform/PlatformKeyboardEvent.h"
#include "platform/PlatformMouseEvent.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/TraceEvent.h"
#include "platform/UserGestureIndicator.h"
#include "platform/exported/WebActiveGestureAnimation.h"
#include "platform/fonts/FontCache.h"
#include "platform/graphics/Color.h"
#include "platform/graphics/FirstPaintInvalidationTracking.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/Image.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/gpu/DrawingBuffer.h"
#include "platform/graphics/paint/DrawingRecorder.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositeAndReadbackAsyncCallback.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebDragData.h"
#include "public/platform/WebFloatPoint.h"
#include "public/platform/WebGestureCurve.h"
#include "public/platform/WebImage.h"
#include "public/platform/WebLayerTreeView.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/WebVector.h"
#include "public/platform/WebViewScheduler.h"
#include "public/web/WebAXObject.h"
#include "public/web/WebActiveWheelFlingParameters.h"
#include "public/web/WebAutofillClient.h"
#include "public/web/WebElement.h"
#include "public/web/WebFrame.h"
#include "public/web/WebFrameClient.h"
#include "public/web/WebHitTestResult.h"
#include "public/web/WebInputElement.h"
#include "public/web/WebMeaningfulLayout.h"
#include "public/web/WebMediaPlayerAction.h"
#include "public/web/WebNode.h"
#include "public/web/WebPlugin.h"
#include "public/web/WebPluginAction.h"
#include "public/web/WebRange.h"
#include "public/web/WebSelection.h"
#include "public/web/WebTextInputInfo.h"
#include "public/web/WebViewClient.h"
#include "public/web/WebWindowFeatures.h"
#include "web/CompositionUnderlineVectorBuilder.h"
#include "web/ContextFeaturesClientImpl.h"
#include "web/ContextMenuAllowedScope.h"
#include "web/DatabaseClientImpl.h"
#include "web/DevToolsEmulator.h"
#include "web/FullscreenController.h"
#include "web/GraphicsLayerFactoryChromium.h"
#include "web/InspectorOverlay.h"
#include "web/LinkHighlightImpl.h"
#include "web/PageOverlay.h"
#include "web/PrerendererClientImpl.h"
#include "web/ResizeViewportAnchor.h"
#include "web/RotationViewportAnchor.h"
#include "web/SpeechRecognitionClientProxy.h"
#include "web/StorageQuotaClientImpl.h"
#include "web/ValidationMessageClientImpl.h"
#include "web/ViewportAnchor.h"
#include "web/WebDevToolsAgentImpl.h"
#include "web/WebInputEventConversion.h"
#include "web/WebLocalFrameImpl.h"
#include "web/WebPagePopupImpl.h"
#include "web/WebPluginContainerImpl.h"
#include "web/WebRemoteFrameImpl.h"
#include "web/WebSettingsImpl.h"
#include "web/WorkerGlobalScopeProxyProviderImpl.h"
#include "wtf/CurrentTime.h"
#include "wtf/RefPtr.h"
#include "wtf/TemporaryChange.h"

#if USE(DEFAULT_RENDER_THEME)
#include "core/layout/LayoutThemeDefault.h"
#endif

// Get rid of WTF's pow define so we can use std::pow.
#undef pow
#include <cmath> // for std::pow

// The following constants control parameters for automated scaling of webpages
// (such as due to a double tap gesture or find in page etc.). These are
// experimentally determined.
static const int touchPointPadding = 32;
static const int nonUserInitiatedPointPadding = 11;
static const float minScaleDifference = 0.01f;
static const float doubleTapZoomContentDefaultMargin = 5;
static const float doubleTapZoomContentMinimumMargin = 2;
static const double doubleTapZoomAnimationDurationInSeconds = 0.25;
static const float doubleTapZoomAlreadyLegibleRatio = 1.2f;

static const double multipleTargetsZoomAnimationDurationInSeconds = 0.25;
static const double findInPageAnimationDurationInSeconds = 0;

// Constants for viewport anchoring on resize.
static const float viewportAnchorCoordX = 0.5f;
static const float viewportAnchorCoordY = 0;

// Constants for zooming in on a focused text field.
static const double scrollAndScaleAnimationDurationInSeconds = 0.2;
static const int minReadableCaretHeight = 16;
static const int minReadableCaretHeightForTextArea = 13;
static const float minScaleChangeToTriggerZoom = 1.5f;
static const float leftBoxRatio = 0.3f;
static const int caretPadding = 10;

namespace blink {

// Change the text zoom level by kTextSizeMultiplierRatio each time the user
// zooms text in or out (ie., change by 20%).  The min and max values limit
// text zoom to half and 3x the original text size.  These three values match
// those in Apple's port in WebKit/WebKit/WebView/WebView.mm
const double WebView::textSizeMultiplierRatio = 1.2;
const double WebView::minTextSizeMultiplier = 0.5;
const double WebView::maxTextSizeMultiplier = 3.0;

// Used to defer all page activity in cases where the embedder wishes to run
// a nested event loop. Using a stack enables nesting of message loop invocations.
static Vector<OwnPtr<ScopedPageLoadDeferrer>>& pageLoadDeferrerStack()
{
    DEFINE_STATIC_LOCAL(Vector<OwnPtr<ScopedPageLoadDeferrer>>, deferrerStack, ());
    return deferrerStack;
}

// Ensure that the WebDragOperation enum values stay in sync with the original
// DragOperation constants.
#define STATIC_ASSERT_MATCHING_ENUM(coreName) \
    static_assert(int(coreName) == int(Web##coreName), "DragOperation and WebDragOperation enum mismatch: " #coreName)
STATIC_ASSERT_MATCHING_ENUM(DragOperationNone);
STATIC_ASSERT_MATCHING_ENUM(DragOperationCopy);
STATIC_ASSERT_MATCHING_ENUM(DragOperationLink);
STATIC_ASSERT_MATCHING_ENUM(DragOperationGeneric);
STATIC_ASSERT_MATCHING_ENUM(DragOperationPrivate);
STATIC_ASSERT_MATCHING_ENUM(DragOperationMove);
STATIC_ASSERT_MATCHING_ENUM(DragOperationDelete);
STATIC_ASSERT_MATCHING_ENUM(DragOperationEvery);

static bool shouldUseExternalPopupMenus = false;

namespace {

class UserGestureNotifier {
public:
    // If a UserGestureIndicator is created for a user gesture since the last
    // page load and *userGestureObserved is false, the UserGestureNotifier
    // will notify the client and set *userGestureObserved to true.
    UserGestureNotifier(WebAutofillClient*, bool* userGestureObserved);
    ~UserGestureNotifier();

private:
    WebAutofillClient* const m_client;
    bool* const m_userGestureObserved;
};

UserGestureNotifier::UserGestureNotifier(WebAutofillClient* client, bool* userGestureObserved)
    : m_client(client)
    , m_userGestureObserved(userGestureObserved)
{
    ASSERT(m_userGestureObserved);
}

UserGestureNotifier::~UserGestureNotifier()
{
    if (!*m_userGestureObserved && UserGestureIndicator::processedUserGestureSinceLoad()) {
        *m_userGestureObserved = true;
        if (m_client)
            m_client->firstUserGestureObserved();
    }
}

class EmptyEventListener final : public EventListener {
public:
    static PassRefPtrWillBeRawPtr<EmptyEventListener> create()
    {
        return adoptRefWillBeNoop(new EmptyEventListener());
    }

    bool operator==(const EventListener& other) const override
    {
        return this == &other;
    }

private:
    EmptyEventListener()
        : EventListener(CPPEventListenerType)
    {
    }

    void handleEvent(ExecutionContext* executionContext, Event*) override
    {
    }
};

class ColorOverlay final : public PageOverlay::Delegate {
public:
    explicit ColorOverlay(WebColor color)
        : m_color(color)
    {
    }

    virtual ~ColorOverlay()
    {
    }

private:
    void paintPageOverlay(const PageOverlay& pageOverlay, GraphicsContext& graphicsContext, const WebSize& size) const override
    {
        if (DrawingRecorder::useCachedDrawingIfPossible(graphicsContext, pageOverlay, DisplayItem::PageOverlay))
            return;
        FloatRect rect(0, 0, size.width, size.height);
        DrawingRecorder drawingRecorder(graphicsContext, pageOverlay, DisplayItem::PageOverlay, rect);
        graphicsContext.fillRect(rect, m_color);
    }

    WebColor m_color;
};

#if OS(ANDROID)
// Array used to convert canonical encoding method name to index to be
// uploaded to UMA for the experiment on text encoding auto detection.
// The listed order should be in sync with the enum definition 'EncodingMethod'
// in tools/metrics/histograms/histograms.xml.
static const char* kEncodingNames[] = {
    "UNKNOWN",
    "Big5",
    "EUC-JP",
    "EUC-KR",
    "GBK",
    "IBM866",
    "ISO-2022-JP",
    "ISO-8859-10",
    "ISO-8859-13",
    "ISO-8859-14",
    "ISO-8859-15",
    "ISO-8859-16",
    "ISO-8859-2",
    "ISO-8859-3",
    "ISO-8859-4",
    "ISO-8859-5",
    "ISO-8859-6",
    "ISO-8859-7",
    "ISO-8859-8",
    "ISO-8859-8-I",
    "KOI8-R",
    "KOI8-U",
    "Shift_JIS",
    "UTF-16LE",
    "UTF-8",
    "gb18030",
    "macintosh",
    "windows-1250",
    "windows-1251",
    "windows-1252",
    "windows-1253",
    "windows-1254",
    "windows-1255",
    "windows-1256",
    "windows-1257",
    "windows-1258",
    "windows-874"
};

// Returns the index of the entry in the array that matches
// the given encoding method.
static int encodingToUmaId(const WTF::TextEncoding& encoding)
{
    const char* encodingName = encoding.name();
    for (size_t i = 0; i < WTF_ARRAY_LENGTH(kEncodingNames); ++i) {
        if (!strcasecmp(kEncodingNames[i], encodingName))
            return i;
    }
    return 0;
}

static bool isInternalURL(const KURL& url)
{
    const String& protocol = url.protocol();
    return protocol == "chrome" || protocol == "chrome-native" || protocol == "swappedout";
}
#endif
} // namespace

// WebView ----------------------------------------------------------------

WebView* WebView::create(WebViewClient* client)
{
    // Pass the WebViewImpl's self-reference to the caller.
    return WebViewImpl::create(client);
}

WebViewImpl* WebViewImpl::create(WebViewClient* client)
{
    // Pass the WebViewImpl's self-reference to the caller.
    return adoptRef(new WebViewImpl(client)).leakRef();
}

void WebView::setUseExternalPopupMenus(bool useExternalPopupMenus)
{
    shouldUseExternalPopupMenus = useExternalPopupMenus;
}

void WebView::updateVisitedLinkState(unsigned long long linkHash)
{
    Page::visitedStateChanged(linkHash);
}

void WebView::resetVisitedLinkState(bool invalidateVisitedLinkHashes)
{
    Page::allVisitedStateChanged(invalidateVisitedLinkHashes);
}

void WebView::willEnterModalLoop()
{
    pageLoadDeferrerStack().append(adoptPtr(new ScopedPageLoadDeferrer()));
}

void WebView::didExitModalLoop()
{
    ASSERT(pageLoadDeferrerStack().size());
    pageLoadDeferrerStack().removeLast();
}

void WebViewImpl::setMainFrame(WebFrame* frame)
{
    frame->toImplBase()->initializeCoreFrame(&page()->frameHost(), 0, nullAtom, nullAtom);
}

void WebViewImpl::setCredentialManagerClient(WebCredentialManagerClient* webCredentialManagerClient)
{
    ASSERT(m_page);
    provideCredentialManagerClientTo(*m_page, new CredentialManagerClient(webCredentialManagerClient));
}

void WebViewImpl::setPrerendererClient(WebPrerendererClient* prerendererClient)
{
    ASSERT(m_page);
    providePrerendererClientTo(*m_page, new PrerendererClientImpl(prerendererClient));
}

void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient)
{
    m_spellCheckClient = spellCheckClient;
}

// static
HashSet<WebViewImpl*>& WebViewImpl::allInstances()
{
    DEFINE_STATIC_LOCAL(HashSet<WebViewImpl*>, allInstances, ());
    return allInstances;
}

WebViewImpl::WebViewImpl(WebViewClient* client)
    : m_client(client)
    , m_spellCheckClient(nullptr)
    , m_chromeClientImpl(ChromeClientImpl::create(this))
    , m_contextMenuClientImpl(this)
    , m_dragClientImpl(this)
    , m_editorClientImpl(this)
    , m_spellCheckerClientImpl(this)
    , m_storageClientImpl(this)
    , m_shouldAutoResize(false)
    , m_zoomLevel(0)
    , m_minimumZoomLevel(zoomFactorToZoomLevel(minTextSizeMultiplier))
    , m_maximumZoomLevel(zoomFactorToZoomLevel(maxTextSizeMultiplier))
    , m_zoomFactorForDeviceScaleFactor(1.f)
    , m_maximumLegibleScale(1)
    , m_doubleTapZoomPageScaleFactor(0)
    , m_doubleTapZoomPending(false)
    , m_enableFakePageScaleAnimationForTesting(false)
    , m_fakePageScaleAnimationPageScaleFactor(0)
    , m_fakePageScaleAnimationUseAnchor(false)
    , m_doingDragAndDrop(false)
    , m_ignoreInputEvents(false)
    , m_compositorDeviceScaleFactorOverride(0)
    , m_rootLayerScale(1)
    , m_suppressNextKeypressEvent(false)
    , m_imeAcceptEvents(true)
    , m_operationsAllowed(WebDragOperationNone)
    , m_dragOperation(WebDragOperationNone)
    , m_devToolsEmulator(nullptr)
    , m_isTransparent(false)
    , m_tabsToLinks(false)
    , m_layerTreeView(nullptr)
    , m_rootLayer(nullptr)
    , m_rootGraphicsLayer(nullptr)
    , m_graphicsLayerFactory(adoptPtr(new GraphicsLayerFactoryChromium(this)))
    , m_matchesHeuristicsForGpuRasterization(false)
    , m_flingModifier(0)
    , m_flingSourceDevice(WebGestureDeviceUninitialized)
    , m_fullscreenController(FullscreenController::create(this))
    , m_showFPSCounter(false)
    , m_baseBackgroundColor(Color::white)
    , m_backgroundColorOverride(Color::transparent)
    , m_zoomFactorOverride(0)
    , m_userGestureObserved(false)
    , m_shouldDispatchFirstVisuallyNonEmptyLayout(false)
    , m_shouldDispatchFirstLayoutAfterFinishedParsing(false)
    , m_shouldDispatchFirstLayoutAfterFinishedLoading(false)
    , m_displayMode(WebDisplayModeBrowser)
    , m_elasticOverscroll(FloatSize())
    , m_scheduler(Platform::current()->currentThread()->scheduler()->createWebViewScheduler(this).release())
{
    Page::PageClients pageClients;
    pageClients.chromeClient = m_chromeClientImpl.get();
    pageClients.contextMenuClient = &m_contextMenuClientImpl;
    pageClients.editorClient = &m_editorClientImpl;
    pageClients.dragClient = &m_dragClientImpl;
    pageClients.spellCheckerClient = &m_spellCheckerClientImpl;

    m_page = Page::createOrdinary(pageClients);
    MediaKeysController::provideMediaKeysTo(*m_page, &m_mediaKeysClientImpl);
    provideSpeechRecognitionTo(*m_page, SpeechRecognitionClientProxy::create(client ? client->speechRecognizer() : nullptr));
    provideContextFeaturesTo(*m_page, ContextFeaturesClientImpl::create());
    provideDatabaseClientTo(*m_page, DatabaseClientImpl::create());

    provideStorageQuotaClientTo(*m_page, StorageQuotaClientImpl::create());
    m_page->setValidationMessageClient(ValidationMessageClientImpl::create(*this));
    provideWorkerGlobalScopeProxyProviderTo(*m_page, WorkerGlobalScopeProxyProviderImpl::create());
    StorageNamespaceController::provideStorageNamespaceTo(*m_page, &m_storageClientImpl);

    if (m_client) {
        setVisibilityState(m_client->visibilityState(), true);
    }

    initializeLayerTreeView();

    m_devToolsEmulator = DevToolsEmulator::create(this);

    allInstances().add(this);

    m_pageImportanceSignals.setObserver(client);
}

WebViewImpl::~WebViewImpl()
{
    ASSERT(!m_page);

    // Each highlight uses m_owningWebViewImpl->m_linkHighlightsTimeline
    // in destructor. m_linkHighlightsTimeline might be destroyed earlier
    // than m_linkHighlights.
    ASSERT(m_linkHighlights.isEmpty());
}

WebDevToolsAgentImpl* WebViewImpl::mainFrameDevToolsAgentImpl()
{
    WebLocalFrameImpl* mainFrame = mainFrameImpl();
    return mainFrame ? mainFrame->devToolsAgentImpl() : nullptr;
}

InspectorOverlay* WebViewImpl::inspectorOverlay()
{
    if (WebDevToolsAgentImpl* devtools = mainFrameDevToolsAgentImpl())
        return devtools->overlay();
    return nullptr;
}

WebLocalFrameImpl* WebViewImpl::mainFrameImpl() const
{
    return m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame()
        ? WebLocalFrameImpl::fromFrame(m_page->deprecatedLocalMainFrame()) : nullptr;
}

bool WebViewImpl::tabKeyCyclesThroughElements() const
{
    ASSERT(m_page);
    return m_page->tabKeyCyclesThroughElements();
}

void WebViewImpl::setTabKeyCyclesThroughElements(bool value)
{
    if (m_page)
        m_page->setTabKeyCyclesThroughElements(value);
}

void WebViewImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseEvent& event)
{
    m_client->setMouseOverURL(WebURL());
    PageWidgetEventHandler::handleMouseLeave(mainFrame, event);
}

void WebViewImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEvent& event)
{
    // If there is a popup open, close it as the user is clicking on the page
    // (outside of the popup). We also save it so we can prevent a click on an
    // element from immediately reopening the same popup.
    RefPtr<WebPagePopupImpl> pagePopup;
    if (event.button == WebMouseEvent::ButtonLeft) {
        pagePopup = m_pagePopup;
        hidePopups();
        ASSERT(!m_pagePopup);
    }

    m_lastMouseDownPoint = WebPoint(event.x, event.y);

    // Take capture on a mouse down on a plugin so we can send it mouse events.
    // If the hit node is a plugin but a scrollbar is over it don't start mouse
    // capture because it will interfere with the scrollbar receiving events.
    IntPoint point(event.x, event.y);
    if (event.button == WebMouseEvent::ButtonLeft && m_page->mainFrame()->isLocalFrame()) {
        point = m_page->deprecatedLocalMainFrame()->view()->rootFrameToContents(point);
        HitTestResult result(m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(point));
        result.setToShadowHostIfInUserAgentShadowRoot();
        Node* hitNode = result.innerNodeOrImageMapImage();

        if (!result.scrollbar() && hitNode && hitNode->layoutObject() && hitNode->layoutObject()->isEmbeddedObject()) {
            m_mouseCaptureNode = hitNode;
            TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
        }
    }

    PageWidgetEventHandler::handleMouseDown(mainFrame, event);

    if (event.button == WebMouseEvent::ButtonLeft && m_mouseCaptureNode)
        m_mouseCaptureGestureToken = mainFrame.eventHandler().takeLastMouseDownGestureToken();

    if (m_pagePopup && pagePopup && m_pagePopup->hasSamePopupClient(pagePopup.get())) {
        // That click triggered a page popup that is the same as the one we just closed.
        // It needs to be closed.
        cancelPagePopup();
    }

    // Dispatch the contextmenu event regardless of if the click was swallowed.
    if (!page()->settings().showContextMenuOnMouseUp()) {
#if OS(MACOSX)
        if (event.button == WebMouseEvent::ButtonRight
            || (event.button == WebMouseEvent::ButtonLeft
                && event.modifiers & WebMouseEvent::ControlKey))
            mouseContextMenu(event);
#else
        if (event.button == WebMouseEvent::ButtonRight)
            mouseContextMenu(event);
#endif
    }
}

void WebViewImpl::setDisplayMode(WebDisplayMode mode)
{
    m_displayMode = mode;
    if (!mainFrameImpl() || !mainFrameImpl()->frameView())
        return;

    mainFrameImpl()->frameView()->setDisplayMode(mode);
}

void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
{
    if (!mainFrameImpl() || !mainFrameImpl()->frameView())
        return;

    m_page->contextMenuController().clearContextMenu();

    PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), event);

    // Find the right target frame. See issue 1186900.
    HitTestResult result = hitTestResultForRootFramePos(pme.position());
    Frame* targetFrame;
    if (result.innerNodeOrImageMapImage())
        targetFrame = result.innerNodeOrImageMapImage()->document().frame();
    else
        targetFrame = m_page->focusController().focusedOrMainFrame();

    if (!targetFrame->isLocalFrame())
        return;

    LocalFrame* targetLocalFrame = toLocalFrame(targetFrame);

#if OS(WIN)
    targetLocalFrame->view()->setCursor(pointerCursor());
#endif

    {
        ContextMenuAllowedScope scope;
        targetLocalFrame->eventHandler().sendContextMenuEvent(pme, nullptr);
    }
    // Actually showing the context menu is handled by the ContextMenuClient
    // implementation...
}

void WebViewImpl::handleMouseUp(LocalFrame& mainFrame, const WebMouseEvent& event)
{
    PageWidgetEventHandler::handleMouseUp(mainFrame, event);

    if (page()->settings().showContextMenuOnMouseUp()) {
        // Dispatch the contextmenu event regardless of if the click was swallowed.
        // On Mac/Linux, we handle it on mouse down, not up.
        if (event.button == WebMouseEvent::ButtonRight)
            mouseContextMenu(event);
    }
}

WebInputEventResult WebViewImpl::handleMouseWheel(LocalFrame& mainFrame, const WebMouseWheelEvent& event)
{
    hidePopups();
    return PageWidgetEventHandler::handleMouseWheel(mainFrame, event);
}

bool WebViewImpl::scrollBy(const WebFloatSize& delta, const WebFloatSize& velocity)
{
    ASSERT(m_flingSourceDevice != WebGestureDeviceUninitialized);
    if (m_flingSourceDevice == WebGestureDeviceTouchpad) {
        WebMouseWheelEvent syntheticWheel;
        const float tickDivisor = WheelEvent::TickMultiplier;

        syntheticWheel.deltaX = delta.width;
        syntheticWheel.deltaY = delta.height;
        syntheticWheel.wheelTicksX = delta.width / tickDivisor;
        syntheticWheel.wheelTicksY = delta.height / tickDivisor;
        syntheticWheel.hasPreciseScrollingDeltas = true;
        syntheticWheel.x = m_positionOnFlingStart.x;
        syntheticWheel.y = m_positionOnFlingStart.y;
        syntheticWheel.globalX = m_globalPositionOnFlingStart.x;
        syntheticWheel.globalY = m_globalPositionOnFlingStart.y;
        syntheticWheel.modifiers = m_flingModifier;

        if (m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() && m_page->deprecatedLocalMainFrame()->view())
            return handleMouseWheel(*m_page->deprecatedLocalMainFrame(), syntheticWheel) != WebInputEventResult::NotHandled;
    } else {
        WebGestureEvent syntheticGestureEvent;

        syntheticGestureEvent.type = WebInputEvent::GestureScrollUpdate;
        syntheticGestureEvent.data.scrollUpdate.preventPropagation = true;
        syntheticGestureEvent.data.scrollUpdate.deltaX = delta.width;
        syntheticGestureEvent.data.scrollUpdate.deltaY = delta.height;
        syntheticGestureEvent.data.scrollUpdate.velocityX = velocity.width;
        syntheticGestureEvent.data.scrollUpdate.velocityY = velocity.height;
        syntheticGestureEvent.x = m_positionOnFlingStart.x;
        syntheticGestureEvent.y = m_positionOnFlingStart.y;
        syntheticGestureEvent.globalX = m_globalPositionOnFlingStart.x;
        syntheticGestureEvent.globalY = m_globalPositionOnFlingStart.y;
        syntheticGestureEvent.modifiers = m_flingModifier;
        syntheticGestureEvent.sourceDevice = WebGestureDeviceTouchscreen;
        syntheticGestureEvent.data.scrollUpdate.inertial = true;

        if (m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() && m_page->deprecatedLocalMainFrame()->view())
            return handleGestureEvent(syntheticGestureEvent) != WebInputEventResult::NotHandled;
    }
    return false;
}

WebInputEventResult WebViewImpl::handleGestureEvent(const WebGestureEvent& event)
{
    if (!m_client)
        return WebInputEventResult::NotHandled;

    WebInputEventResult eventResult = WebInputEventResult::NotHandled;
    bool eventCancelled = false; // for disambiguation

    // Special handling for slow-path fling gestures.
    switch (event.type) {
    case WebInputEvent::GestureFlingStart: {
        if (mainFrameImpl()->frame()->eventHandler().isScrollbarHandlingGestures())
            break;
        endActiveFlingAnimation();
        m_client->cancelScheduledContentIntents();
        m_positionOnFlingStart = WebPoint(event.x, event.y);
        m_globalPositionOnFlingStart = WebPoint(event.globalX, event.globalY);
        m_flingModifier = event.modifiers;
        m_flingSourceDevice = event.sourceDevice;
        ASSERT(m_flingSourceDevice != WebGestureDeviceUninitialized);
        OwnPtr<WebGestureCurve> flingCurve = adoptPtr(Platform::current()->createFlingAnimationCurve(event.sourceDevice, WebFloatPoint(event.data.flingStart.velocityX, event.data.flingStart.velocityY), WebSize()));
        ASSERT(flingCurve);
        m_gestureAnimation = WebActiveGestureAnimation::createAtAnimationStart(flingCurve.release(), this);
        scheduleAnimation();
        eventResult = WebInputEventResult::HandledSystem;

        // Plugins may need to see GestureFlingStart to balance
        // GestureScrollBegin (since the former replaces GestureScrollEnd when
        // transitioning to a fling).
        PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
        // TODO(dtapuska): Why isn't the response used?
        mainFrameImpl()->frame()->eventHandler().handleGestureScrollEvent(platformEvent);

        m_client->didHandleGestureEvent(event, eventCancelled);
        return WebInputEventResult::HandledSystem;
    }
    case WebInputEvent::GestureFlingCancel:
        if (endActiveFlingAnimation())
            eventResult = WebInputEventResult::HandledSuppressed;

        m_client->didHandleGestureEvent(event, eventCancelled);
        return eventResult;
    default:
        break;
    }

    PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);

    // Special handling for double tap and scroll events as we don't want to
    // hit test for them.
    switch (event.type) {
    case WebInputEvent::GestureDoubleTap:
        if (m_webSettings->doubleTapToZoomEnabled() && minimumPageScaleFactor() != maximumPageScaleFactor()) {
            m_client->cancelScheduledContentIntents();
            animateDoubleTapZoom(platformEvent.position());
        }
        // GestureDoubleTap is currently only used by Android for zooming. For WebCore,
        // GestureTap with tap count = 2 is used instead. So we drop GestureDoubleTap here.
        eventResult = WebInputEventResult::HandledSystem;
        m_client->didHandleGestureEvent(event, eventCancelled);
        return eventResult;
    case WebInputEvent::GestureScrollBegin:
        m_client->cancelScheduledContentIntents();
    case WebInputEvent::GestureScrollEnd:
    case WebInputEvent::GestureScrollUpdate:
    case WebInputEvent::GestureFlingStart:
        // Scrolling-related gesture events invoke EventHandler recursively for each frame down
        // the chain, doing a single-frame hit-test per frame. This matches handleWheelEvent.
        // Perhaps we could simplify things by rewriting scroll handling to work inner frame
        // out, and then unify with other gesture events.
        eventResult = mainFrameImpl()->frame()->eventHandler().handleGestureScrollEvent(platformEvent);
        m_client->didHandleGestureEvent(event, eventCancelled);
        return eventResult;
    case WebInputEvent::GesturePinchBegin:
    case WebInputEvent::GesturePinchEnd:
    case WebInputEvent::GesturePinchUpdate:
        return WebInputEventResult::NotHandled;
    default:
        break;
    }

    // Hit test across all frames and do touch adjustment as necessary for the event type.
    GestureEventWithHitTestResults targetedEvent =
        m_page->deprecatedLocalMainFrame()->eventHandler().targetGestureEvent(platformEvent);

    // Handle link highlighting outside the main switch to avoid getting lost in the
    // complicated set of cases handled below.
    switch (event.type) {
    case WebInputEvent::GestureShowPress:
        // Queue a highlight animation, then hand off to regular handler.
        enableTapHighlightAtPoint(targetedEvent);
        break;
    case WebInputEvent::GestureTapCancel:
    case WebInputEvent::GestureTap:
    case WebInputEvent::GestureLongPress:
        for (size_t i = 0; i < m_linkHighlights.size(); ++i)
            m_linkHighlights[i]->startHighlightAnimationIfNeeded();
        break;
    default:
        break;
    }

    switch (event.type) {
    case WebInputEvent::GestureTap: {
        // If there is a popup open, close it as the user is clicking on the page
        // (outside of the popup). We also save it so we can prevent a tap on an
        // element from immediately reopening the same popup.
        RefPtr<WebPagePopupImpl> pagePopup = m_pagePopup;
        hidePopups();
        ASSERT(!m_pagePopup);

        m_client->cancelScheduledContentIntents();
        if (detectContentOnTouch(targetedEvent)) {
            eventResult = WebInputEventResult::HandledSystem;
            break;
        }

        // Don't trigger a disambiguation popup on sites designed for mobile devices.
        // Instead, assume that the page has been designed with big enough buttons and links.
        // Don't trigger a disambiguation popup when screencasting, since it's implemented outside of
        // compositor pipeline and is not being screencasted itself. This leads to bad user experience.
        WebDevToolsAgentImpl* devTools = mainFrameDevToolsAgentImpl();
        VisualViewport& visualViewport = page()->frameHost().visualViewport();
        bool screencastEnabled = devTools && devTools->screencastEnabled();
        if (event.data.tap.width > 0 && !visualViewport.shouldDisableDesktopWorkarounds() && !screencastEnabled) {
            IntRect boundingBox(visualViewport.viewportToRootFrame(IntRect(
                event.x - event.data.tap.width / 2,
                event.y - event.data.tap.height / 2,
                event.data.tap.width,
                event.data.tap.height)));

            // TODO(bokan): We shouldn't pass details of the VisualViewport offset to render_view_impl.
            //              crbug.com/459591
            WebSize visualViewportOffset = flooredIntSize(visualViewport.location());

            if (m_webSettings->multiTargetTapNotificationEnabled()) {
                Vector<IntRect> goodTargets;
                WillBeHeapVector<RawPtrWillBeMember<Node>> highlightNodes;
                findGoodTouchTargets(boundingBox, mainFrameImpl()->frame(), goodTargets, highlightNodes);
                // FIXME: replace touch adjustment code when numberOfGoodTargets == 1?
                // Single candidate case is currently handled by: https://bugs.webkit.org/show_bug.cgi?id=85101
                if (goodTargets.size() >= 2 && m_client
                    && m_client->didTapMultipleTargets(visualViewportOffset, boundingBox, goodTargets)) {

                    enableTapHighlights(highlightNodes);
                    for (size_t i = 0; i < m_linkHighlights.size(); ++i)
                        m_linkHighlights[i]->startHighlightAnimationIfNeeded();
                    eventResult = WebInputEventResult::HandledSystem;
                    eventCancelled = true;
                    break;
                }
            }
        }

        eventResult = mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent);

        if (m_pagePopup && pagePopup && m_pagePopup->hasSamePopupClient(pagePopup.get())) {
            // The tap triggered a page popup that is the same as the one we just closed.
            // It needs to be closed.
            cancelPagePopup();
        }
        break;
    }
    case WebInputEvent::GestureTwoFingerTap:
    case WebInputEvent::GestureLongPress:
    case WebInputEvent::GestureLongTap: {
        if (!mainFrameImpl() || !mainFrameImpl()->frameView())
            break;

        m_client->cancelScheduledContentIntents();
        m_page->contextMenuController().clearContextMenu();
        {
            ContextMenuAllowedScope scope;
            eventResult = mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent);
        }

        break;
    }
    case WebInputEvent::GestureShowPress:
        m_client->cancelScheduledContentIntents();
    case WebInputEvent::GestureTapDown:
    case WebInputEvent::GestureTapCancel:
    case WebInputEvent::GestureTapUnconfirmed: {
        eventResult = mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent);
        break;
    }
    default:
        ASSERT_NOT_REACHED();
    }
    m_client->didHandleGestureEvent(event, eventCancelled);
    return eventResult;
}

WebInputEventResult WebViewImpl::handleSyntheticWheelFromTouchpadPinchEvent(const WebGestureEvent& pinchEvent)
{
    ASSERT(pinchEvent.type == WebInputEvent::GesturePinchUpdate);

    // Touchscreen pinch events should not reach Blink.
    ASSERT(pinchEvent.sourceDevice == WebGestureDeviceTouchpad);

    // For pinch gesture events, match typical trackpad behavior on Windows by sending fake
    // wheel events with the ctrl modifier set when we see trackpad pinch gestures.  Ideally
    // we'd someday get a platform 'pinch' event and send that instead.
    WebMouseWheelEvent wheelEvent;
    wheelEvent.type = WebInputEvent::MouseWheel;
    wheelEvent.timeStampSeconds = pinchEvent.timeStampSeconds;
    wheelEvent.windowX = wheelEvent.x = pinchEvent.x;
    wheelEvent.windowY = wheelEvent.y = pinchEvent.y;
    wheelEvent.globalX = pinchEvent.globalX;
    wheelEvent.globalY = pinchEvent.globalY;
    wheelEvent.modifiers =
        pinchEvent.modifiers | WebInputEvent::ControlKey;
    wheelEvent.deltaX = 0;

    // The function to convert scales to deltaY values is designed to be
    // compatible with websites existing use of wheel events, and with existing
    // Windows trackpad behavior.  In particular, we want:
    //  - deltas should accumulate via addition: f(s1*s2)==f(s1)+f(s2)
    //  - deltas should invert via negation: f(1/s) == -f(s)
    //  - zoom in should be positive: f(s) > 0 iff s > 1
    //  - magnitude roughly matches wheels: f(2) > 25 && f(2) < 100
    //  - a formula that's relatively easy to use from JavaScript
    // Note that 'wheel' event deltaY values have their sign inverted.  So to
    // convert a wheel deltaY back to a scale use Math.exp(-deltaY/100).
    ASSERT(pinchEvent.data.pinchUpdate.scale > 0);
    wheelEvent.deltaY = 100.0f * log(pinchEvent.data.pinchUpdate.scale);
    wheelEvent.hasPreciseScrollingDeltas = true;
    wheelEvent.wheelTicksX = 0;
    wheelEvent.wheelTicksY =
        pinchEvent.data.pinchUpdate.scale > 1 ? 1 : -1;
    wheelEvent.canScroll = false;

    return handleInputEvent(wheelEvent);
}

void WebViewImpl::transferActiveWheelFlingAnimation(const WebActiveWheelFlingParameters& parameters)
{
    TRACE_EVENT0("blink", "WebViewImpl::transferActiveWheelFlingAnimation");
    ASSERT(!m_gestureAnimation);
    m_positionOnFlingStart = parameters.point;
    m_globalPositionOnFlingStart = parameters.globalPoint;
    m_flingModifier = parameters.modifiers;
    OwnPtr<WebGestureCurve> curve = adoptPtr(Platform::current()->createFlingAnimationCurve(parameters.sourceDevice, WebFloatPoint(parameters.delta), parameters.cumulativeScroll));
    ASSERT(curve);
    m_gestureAnimation = WebActiveGestureAnimation::createWithTimeOffset(curve.release(), this, parameters.startTime);
    ASSERT(parameters.sourceDevice != WebGestureDeviceUninitialized);
    m_flingSourceDevice = parameters.sourceDevice;
    scheduleAnimation();
}

bool WebViewImpl::endActiveFlingAnimation()
{
    if (m_gestureAnimation) {
        m_gestureAnimation.clear();
        m_flingSourceDevice = WebGestureDeviceUninitialized;
        if (m_layerTreeView)
            m_layerTreeView->didStopFlinging();
        return true;
    }
    return false;
}

bool WebViewImpl::startPageScaleAnimation(const IntPoint& targetPosition, bool useAnchor, float newScale, double durationInSeconds)
{
    VisualViewport& visualViewport = page()->frameHost().visualViewport();
    WebPoint clampedPoint = targetPosition;
    if (!useAnchor) {
        clampedPoint = visualViewport.clampDocumentOffsetAtScale(targetPosition, newScale);
        if (!durationInSeconds) {
            setPageScaleFactor(newScale);

            FrameView* view = mainFrameImpl()->frameView();
            if (view && view->scrollableArea())
                view->scrollableArea()->setScrollPosition(DoublePoint(clampedPoint.x, clampedPoint.y), ProgrammaticScroll);

            return false;
        }
    }
    if (useAnchor && newScale == pageScaleFactor())
        return false;

    if (m_enableFakePageScaleAnimationForTesting) {
        m_fakePageScaleAnimationTargetPosition = targetPosition;
        m_fakePageScaleAnimationUseAnchor = useAnchor;
        m_fakePageScaleAnimationPageScaleFactor = newScale;
    } else {
        if (!m_layerTreeView)
            return false;
        m_layerTreeView->startPageScaleAnimation(targetPosition, useAnchor, newScale, durationInSeconds);
    }
    return true;
}

void WebViewImpl::enableFakePageScaleAnimationForTesting(bool enable)
{
    m_enableFakePageScaleAnimationForTesting = enable;
}

void WebViewImpl::setShowFPSCounter(bool show)
{
    if (m_layerTreeView) {
        TRACE_EVENT0("blink", "WebViewImpl::setShowFPSCounter");
        m_layerTreeView->setShowFPSCounter(show && !m_devToolsEmulator->deviceEmulationEnabled());
    }
    m_showFPSCounter = show;
}

void WebViewImpl::setShowPaintRects(bool show)
{
    if (m_layerTreeView) {
        TRACE_EVENT0("blink", "WebViewImpl::setShowPaintRects");
        m_layerTreeView->setShowPaintRects(show);
    }
    setFirstPaintInvalidationTrackingEnabledForShowPaintRects(show);
}

void WebViewImpl::setShowDebugBorders(bool show)
{
    if (m_layerTreeView)
        m_layerTreeView->setShowDebugBorders(show);
}

void WebViewImpl::updateShowFPSCounter()
{
    if (m_layerTreeView)
        m_layerTreeView->setShowFPSCounter(m_showFPSCounter && !m_devToolsEmulator->deviceEmulationEnabled());
}

void WebViewImpl::setShowScrollBottleneckRects(bool show)
{
    if (m_layerTreeView)
        m_layerTreeView->setShowScrollBottleneckRects(show);
}

void WebViewImpl::acceptLanguagesChanged()
{
    if (!page())
        return;

    page()->acceptLanguagesChanged();
}

WebInputEventResult WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
{
    ASSERT((event.type == WebInputEvent::RawKeyDown)
        || (event.type == WebInputEvent::KeyDown)
        || (event.type == WebInputEvent::KeyUp));
    TRACE_EVENT2("input", "WebViewImpl::handleKeyEvent",
        "type", inputTypeToName(event.type),
        "text", String(event.text).utf8());

    // Halt an in-progress fling on a key event.
    endActiveFlingAnimation();

    // Please refer to the comments explaining the m_suppressNextKeypressEvent
    // member.
    // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
    // Webkit. A keyDown event is typically associated with a keyPress(char)
    // event and a keyUp event. We reset this flag here as this is a new keyDown
    // event.
    m_suppressNextKeypressEvent = false;

    // If there is a popup, it should be the one processing the event, not the
    // page.
    if (m_pagePopup) {
        m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
        // We need to ignore the next Char event after this otherwise pressing
        // enter when selecting an item in the popup will go to the page.
        if (WebInputEvent::RawKeyDown == event.type)
            m_suppressNextKeypressEvent = true;
        return WebInputEventResult::HandledSystem;
    }

    RefPtrWillBeRawPtr<Frame> focusedFrame = focusedCoreFrame();
    if (focusedFrame && focusedFrame->isRemoteFrame()) {
        WebRemoteFrameImpl* webFrame = WebRemoteFrameImpl::fromFrame(*toRemoteFrame(focusedFrame.get()));
        webFrame->client()->forwardInputEvent(&event);
        return WebInputEventResult::HandledSystem;
    }

    if (!focusedFrame || !focusedFrame->isLocalFrame())
        return WebInputEventResult::NotHandled;

    LocalFrame* frame = toLocalFrame(focusedFrame.get());

    PlatformKeyboardEventBuilder evt(event);

    WebInputEventResult result = frame->eventHandler().keyEvent(evt);
    if (result != WebInputEventResult::NotHandled) {
        if (WebInputEvent::RawKeyDown == event.type) {
            // Suppress the next keypress event unless the focused node is a plugin node.
            // (Flash needs these keypress events to handle non-US keyboards.)
            Element* element = focusedElement();
            if (element && element->layoutObject() && element->layoutObject()->isEmbeddedObject()) {
                if (event.windowsKeyCode == VKEY_TAB) {
                    // If the plugin supports keyboard focus then we should not send a tab keypress event.
                    Widget* widget = toLayoutPart(element->layoutObject())->widget();
                    if (widget && widget->isPluginContainer()) {
                        WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget);
                        if (plugin && plugin->supportsKeyboardFocus())
                            m_suppressNextKeypressEvent = true;
                    }
                }
            } else {
                m_suppressNextKeypressEvent = true;
            }
        }
        return result;
    }

#if !OS(MACOSX)
    const WebInputEvent::Type contextMenuTriggeringEventType =
#if OS(WIN)
        WebInputEvent::KeyUp;
#else
        WebInputEvent::RawKeyDown;
#endif

    bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS;
    bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10;
    if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) {
        sendContextMenuEvent(event);
        return WebInputEventResult::HandledSystem;
    }
#endif // !OS(MACOSX)

    if (keyEventDefault(event))
        return WebInputEventResult::HandledSystem;
    return WebInputEventResult::NotHandled;
}

WebInputEventResult WebViewImpl::handleCharEvent(const WebKeyboardEvent& event)
{
    ASSERT(event.type == WebInputEvent::Char);
    TRACE_EVENT1("input", "WebViewImpl::handleCharEvent",
        "text", String(event.text).utf8());

    // Please refer to the comments explaining the m_suppressNextKeypressEvent
    // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
    // handled by Webkit. A keyDown event is typically associated with a
    // keyPress(char) event and a keyUp event. We reset this flag here as it
    // only applies to the current keyPress event.
    bool suppress = m_suppressNextKeypressEvent;
    m_suppressNextKeypressEvent = false;

    // If there is a popup, it should be the one processing the event, not the
    // page.
    if (m_pagePopup)
        return m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));

    LocalFrame* frame = toLocalFrame(focusedCoreFrame());
    if (!frame)
        return suppress ? WebInputEventResult::HandledSuppressed : WebInputEventResult::NotHandled;

    EventHandler& handler = frame->eventHandler();

    PlatformKeyboardEventBuilder evt(event);
    if (!evt.isCharacterKey())
        return WebInputEventResult::HandledSuppressed;

    // Accesskeys are triggered by char events and can't be suppressed.
    if (handler.handleAccessKey(evt))
        return WebInputEventResult::HandledSystem;

    // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
    // the eventHandler::keyEvent. We mimic this behavior on all platforms since
    // for now we are converting other platform's key events to windows key
    // events.
    if (evt.isSystemKey())
        return WebInputEventResult::NotHandled;

    if (suppress)
        return WebInputEventResult::HandledSuppressed;

    WebInputEventResult result = handler.keyEvent(evt);
    if (result != WebInputEventResult::NotHandled)
        return result;
    if (keyEventDefault(event))
        return WebInputEventResult::HandledSystem;

    return WebInputEventResult::NotHandled;
}

WebRect WebViewImpl::computeBlockBound(const WebPoint& pointInRootFrame, bool ignoreClipping)
{
    if (!mainFrameImpl())
        return WebRect();

    // Use the point-based hit test to find the node.
    IntPoint point = mainFrameImpl()->frameView()->rootFrameToContents(IntPoint(pointInRootFrame.x, pointInRootFrame.y));
    HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | (ignoreClipping ? HitTestRequest::IgnoreClipping : 0);
    HitTestResult result = mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(point, hitType);
    result.setToShadowHostIfInUserAgentShadowRoot();

    Node* node = result.innerNodeOrImageMapImage();
    if (!node)
        return WebRect();

    // Find the block type node based on the hit node.
    // FIXME: This wants to walk composed tree with LayoutTreeBuilderTraversal::parent().
    while (node && (!node->layoutObject() || node->layoutObject()->isInline()))
        node = LayoutTreeBuilderTraversal::parent(*node);

    // Return the bounding box in the root frame's coordinate space.
    if (node) {
        IntRect pointInRootFrame = node->Node::pixelSnappedBoundingBox();
        LocalFrame* frame = node->document().frame();
        return frame->view()->contentsToRootFrame(pointInRootFrame);
    }
    return WebRect();
}

WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int targetMargin, int minimumMargin)
{
    WebSize maxSize;
    if (mainFrame())
        maxSize = mainFrame()->contentsSize();
    IntSize scrollOffset;
    if (mainFrame())
        scrollOffset = mainFrame()->scrollOffset();
    int leftMargin = targetMargin;
    int rightMargin = targetMargin;

    const int absoluteSourceX = source.x + scrollOffset.width();
    if (leftMargin > absoluteSourceX) {
        leftMargin = absoluteSourceX;
        rightMargin = std::max(leftMargin, minimumMargin);
    }

    const int maximumRightMargin = maxSize.width - (source.width + absoluteSourceX);
    if (rightMargin > maximumRightMargin) {
        rightMargin = maximumRightMargin;
        leftMargin = std::min(leftMargin, std::max(rightMargin, minimumMargin));
    }

    const int newWidth = source.width + leftMargin + rightMargin;
    const int newX = source.x - leftMargin;

    ASSERT(newWidth >= 0);
    ASSERT(scrollOffset.width() + newX + newWidth <= maxSize.width);

    return WebRect(newX, source.y, newWidth, source.height);
}

float WebViewImpl::maximumLegiblePageScale() const
{
    // Pages should be as legible as on desktop when at dpi scale, so no
    // need to zoom in further when automatically determining zoom level
    // (after double tap, find in page, etc), though the user should still
    // be allowed to manually pinch zoom in further if they desire.
    if (page())
        return m_maximumLegibleScale * page()->settings().accessibilityFontScaleFactor();
    return m_maximumLegibleScale;
}

void WebViewImpl::computeScaleAndScrollForBlockRect(const WebPoint& hitPointInRootFrame, const WebRect& blockRectInRootFrame, float padding, float defaultScaleWhenAlreadyLegible, float& scale, WebPoint& scroll)
{
    scale = pageScaleFactor();
    scroll.x = scroll.y = 0;

    WebRect rect = blockRectInRootFrame;

    if (!rect.isEmpty()) {
        float defaultMargin = doubleTapZoomContentDefaultMargin;
        float minimumMargin = doubleTapZoomContentMinimumMargin;
        // We want the margins to have the same physical size, which means we
        // need to express them in post-scale size. To do that we'd need to know
        // the scale we're scaling to, but that depends on the margins. Instead
        // we express them as a fraction of the target rectangle: this will be
        // correct if we end up fully zooming to it, and won't matter if we
        // don't.
        rect = widenRectWithinPageBounds(rect,
                static_cast<int>(defaultMargin * rect.width / m_size.width),
                static_cast<int>(minimumMargin * rect.width / m_size.width));
        // Fit block to screen, respecting limits.
        scale = static_cast<float>(m_size.width) / rect.width;
        scale = std::min(scale, maximumLegiblePageScale());
        if (pageScaleFactor() < defaultScaleWhenAlreadyLegible)
            scale = std::max(scale, defaultScaleWhenAlreadyLegible);
        scale = clampPageScaleFactorToLimits(scale);
    }

    // FIXME: If this is being called for auto zoom during find in page,
    // then if the user manually zooms in it'd be nice to preserve the
    // relative increase in zoom they caused (if they zoom out then it's ok
    // to zoom them back in again). This isn't compatible with our current
    // double-tap zoom strategy (fitting the containing block to the screen)
    // though.

    float screenWidth = m_size.width / scale;
    float screenHeight = m_size.height / scale;

    // Scroll to vertically align the block.
    if (rect.height < screenHeight) {
        // Vertically center short blocks.
        rect.y -= 0.5 * (screenHeight - rect.height);
    } else {
        // Ensure position we're zooming to (+ padding) isn't off the bottom of
        // the screen.
        rect.y = std::max<float>(rect.y, hitPointInRootFrame.y + padding - screenHeight);
    } // Otherwise top align the block.

    // Do the same thing for horizontal alignment.
    if (rect.width < screenWidth)
        rect.x -= 0.5 * (screenWidth - rect.width);
    else
        rect.x = std::max<float>(rect.x, hitPointInRootFrame.x + padding - screenWidth);
    scroll.x = rect.x;
    scroll.y = rect.y;

    scale = clampPageScaleFactorToLimits(scale);
    scroll = mainFrameImpl()->frameView()->rootFrameToContents(scroll);
    scroll = page()->frameHost().visualViewport().clampDocumentOffsetAtScale(scroll, scale);
}

static Node* findCursorDefiningAncestor(Node* node, LocalFrame* frame)
{
    // Go up the tree to find the node that defines a mouse cursor style
    while (node) {
        if (node->layoutObject()) {
            ECursor cursor = node->layoutObject()->style()->cursor();
            if (cursor != CURSOR_AUTO || frame->eventHandler().useHandCursor(node, node->isLink()))
                break;
        }
        node = LayoutTreeBuilderTraversal::parent(*node);
    }

    return node;
}

static bool showsHandCursor(Node* node, LocalFrame* frame)
{
    if (!node || !node->layoutObject())
        return false;

    ECursor cursor = node->layoutObject()->style()->cursor();
    return cursor == CURSOR_POINTER
        || (cursor == CURSOR_AUTO && frame->eventHandler().useHandCursor(node, node->isLink()));
}

Node* WebViewImpl::bestTapNode(const GestureEventWithHitTestResults& targetedTapEvent)
{
    TRACE_EVENT0("input", "WebViewImpl::bestTapNode");

    if (!m_page || !m_page->mainFrame())
        return nullptr;

    Node* bestTouchNode = targetedTapEvent.hitTestResult().innerNode();
    if (!bestTouchNode)
        return nullptr;

    // We might hit something like an image map that has no layoutObject on it
    // Walk up the tree until we have a node with an attached layoutObject
    while (!bestTouchNode->layoutObject()) {
        bestTouchNode = LayoutTreeBuilderTraversal::parent(*bestTouchNode);
        if (!bestTouchNode)
            return nullptr;
    }

    // Editable nodes should not be highlighted (e.g., <input>)
    if (bestTouchNode->hasEditableStyle())
        return nullptr;

    Node* cursorDefiningAncestor =
        findCursorDefiningAncestor(bestTouchNode, m_page->deprecatedLocalMainFrame());
    // We show a highlight on tap only when the current node shows a hand cursor
    if (!cursorDefiningAncestor || !showsHandCursor(cursorDefiningAncestor, m_page->deprecatedLocalMainFrame())) {
        return nullptr;
    }

    // We should pick the largest enclosing node with hand cursor set. We do this by first jumping
    // up to cursorDefiningAncestor (which is already known to have hand cursor set). Then we locate
    // the next cursor-defining ancestor up in the the tree and repeat the jumps as long as the node
    // has hand cursor set.
    do {
        bestTouchNode = cursorDefiningAncestor;
        cursorDefiningAncestor = findCursorDefiningAncestor(LayoutTreeBuilderTraversal::parent(*bestTouchNode),
            m_page->deprecatedLocalMainFrame());
    } while (cursorDefiningAncestor && showsHandCursor(cursorDefiningAncestor, m_page->deprecatedLocalMainFrame()));

    return bestTouchNode;
}

void WebViewImpl::enableTapHighlightAtPoint(const GestureEventWithHitTestResults& targetedTapEvent)
{
    Node* touchNode = bestTapNode(targetedTapEvent);

    WillBeHeapVector<RawPtrWillBeMember<Node>> highlightNodes;
    highlightNodes.append(touchNode);

    enableTapHighlights(highlightNodes);
}

void WebViewImpl::enableTapHighlights(WillBeHeapVector<RawPtrWillBeMember<Node>>& highlightNodes)
{
    if (highlightNodes.isEmpty())
        return;

    // Always clear any existing highlight when this is invoked, even if we
    // don't get a new target to highlight.
    m_linkHighlights.clear();

    for (size_t i = 0; i < highlightNodes.size(); ++i) {
        Node* node = highlightNodes[i];

        if (!node || !node->layoutObject())
            continue;

        Color highlightColor = node->layoutObject()->style()->tapHighlightColor();
        // Safari documentation for -webkit-tap-highlight-color says if the specified color has 0 alpha,
        // then tap highlighting is disabled.
        // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
        if (!highlightColor.alpha())
            continue;

        m_linkHighlights.append(LinkHighlightImpl::create(node, this));
    }

    updateAllLifecyclePhases();
}

void WebViewImpl::animateDoubleTapZoom(const IntPoint& pointInRootFrame)
{
    if (!mainFrameImpl())
        return;

    WebRect blockBounds = computeBlockBound(pointInRootFrame, false);
    float scale;
    WebPoint scroll;

    computeScaleAndScrollForBlockRect(pointInRootFrame, blockBounds, touchPointPadding, minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio, scale, scroll);

    bool stillAtPreviousDoubleTapScale = (pageScaleFactor() == m_doubleTapZoomPageScaleFactor
        && m_doubleTapZoomPageScaleFactor != minimumPageScaleFactor())
        || m_doubleTapZoomPending;

    bool scaleUnchanged = fabs(pageScaleFactor() - scale) < minScaleDifference;
    bool shouldZoomOut = blockBounds.isEmpty() || scaleUnchanged || stillAtPreviousDoubleTapScale;

    bool isAnimating;

    if (shouldZoomOut) {
        scale = minimumPageScaleFactor();
        IntPoint targetPosition = mainFrameImpl()->frameView()->rootFrameToContents(pointInRootFrame);
        isAnimating = startPageScaleAnimation(targetPosition, true, scale, doubleTapZoomAnimationDurationInSeconds);
    } else {
        isAnimating = startPageScaleAnimation(scroll, false, scale, doubleTapZoomAnimationDurationInSeconds);
    }

    if (isAnimating) {
        m_doubleTapZoomPageScaleFactor = scale;
        m_doubleTapZoomPending = true;
    }
}

void WebViewImpl::zoomToFindInPageRect(const WebRect& rectInRootFrame)
{
    if (!mainFrameImpl())
        return;

    WebRect blockBounds = computeBlockBound(WebPoint(rectInRootFrame.x + rectInRootFrame.width / 2, rectInRootFrame.y + rectInRootFrame.height / 2), true);

    if (blockBounds.isEmpty()) {
        // Keep current scale (no need to scroll as x,y will normally already
        // be visible). FIXME: Revisit this if it isn't always true.
        return;
    }

    float scale;
    WebPoint scroll;

    computeScaleAndScrollForBlockRect(WebPoint(rectInRootFrame.x, rectInRootFrame.y), blockBounds, nonUserInitiatedPointPadding, minimumPageScaleFactor(), scale, scroll);

    startPageScaleAnimation(scroll, false, scale, findInPageAnimationDurationInSeconds);
}

bool WebViewImpl::zoomToMultipleTargetsRect(const WebRect& rectInRootFrame)
{
    if (!mainFrameImpl())
        return false;

    float scale;
    WebPoint scroll;

    computeScaleAndScrollForBlockRect(WebPoint(rectInRootFrame.x, rectInRootFrame.y), rectInRootFrame, nonUserInitiatedPointPadding, minimumPageScaleFactor(), scale, scroll);

    if (scale <= pageScaleFactor())
        return false;

    startPageScaleAnimation(scroll, false, scale, multipleTargetsZoomAnimationDurationInSeconds);
    return true;
}

void WebViewImpl::hasTouchEventHandlers(bool hasTouchHandlers)
{
    if (m_client)
        m_client->hasTouchEventHandlers(hasTouchHandlers);
}

bool WebViewImpl::hasTouchEventHandlersAt(const WebPoint& point)
{
    // FIXME: Implement this. Note that the point must be divided by pageScaleFactor.
    return true;
}

#if !OS(MACOSX)
// Mac has no way to open a context menu based on a keyboard event.
WebInputEventResult WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
{
    // The contextMenuController() holds onto the last context menu that was
    // popped up on the page until a new one is created. We need to clear
    // this menu before propagating the event through the DOM so that we can
    // detect if we create a new menu for this event, since we won't create
    // a new menu if the DOM swallows the event and the defaultEventHandler does
    // not run.
    page()->contextMenuController().clearContextMenu();

    {
        ContextMenuAllowedScope scope;
        Frame* focusedFrame = page()->focusController().focusedOrMainFrame();
        if (!focusedFrame->isLocalFrame())
            return WebInputEventResult::NotHandled;
        return toLocalFrame(focusedFrame)->eventHandler().sendContextMenuEventForKey(nullptr);
    }
}
#endif

void WebViewImpl::showContextMenuAtPoint(float x, float y, PassRefPtrWillBeRawPtr<ContextMenuProvider> menuProvider)
{
    if (!page()->mainFrame()->isLocalFrame())
        return;
    {
        ContextMenuAllowedScope scope;
        page()->contextMenuController().clearContextMenu();
        page()->contextMenuController().showContextMenuAtPoint(page()->deprecatedLocalMainFrame(), x, y, menuProvider);
    }
}

void WebViewImpl::showContextMenuForElement(WebElement element)
{
    if (!page())
        return;

    page()->contextMenuController().clearContextMenu();
    {
        ContextMenuAllowedScope scope;
        if (LocalFrame* focusedFrame = toLocalFrame(page()->focusController().focusedOrMainFrame()))
            focusedFrame->eventHandler().sendContextMenuEventForKey(element.unwrap<Element>());
    }
}

bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
{
    LocalFrame* frame = toLocalFrame(focusedCoreFrame());
    if (!frame)
        return false;

    switch (event.type) {
    case WebInputEvent::Char:
        if (event.windowsKeyCode == VKEY_SPACE) {
            int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
            return scrollViewWithKeyboard(keyCode, event.modifiers);
        }
        break;
    case WebInputEvent::RawKeyDown:
        if (event.modifiers == WebInputEvent::ControlKey) {
            switch (event.windowsKeyCode) {
#if !OS(MACOSX)
            case 'A':
                focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
                return true;
            case VKEY_INSERT:
            case 'C':
                focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
                return true;
#endif
            // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
            // key combinations which affect scrolling. Safari is buggy in the
            // sense that it scrolls the page for all Ctrl+scrolling key
            // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
            case VKEY_HOME:
            case VKEY_END:
                break;
            default:
                return false;
            }
        }
        if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
            return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
        break;
    default:
        break;
    }
    return false;
}

bool WebViewImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
{
    ScrollDirectionPhysical scrollDirectionPhysical;
    ScrollGranularity scrollGranularity;
#if OS(MACOSX)
    // Alt-Up/Down should be PageUp/Down on Mac.
    if (modifiers & WebMouseEvent::AltKey) {
      if (keyCode == VKEY_UP)
        keyCode = VKEY_PRIOR;
      else if (keyCode == VKEY_DOWN)
        keyCode = VKEY_NEXT;
    }
#endif
    if (!mapKeyCodeForScroll(keyCode, &scrollDirectionPhysical, &scrollGranularity))
        return false;

    if (LocalFrame* frame = toLocalFrame(focusedCoreFrame()))
        return frame->eventHandler().bubblingScroll(toScrollDirection(scrollDirectionPhysical), scrollGranularity);
    return false;
}

bool WebViewImpl::mapKeyCodeForScroll(
    int keyCode,
    ScrollDirectionPhysical* scrollDirection,
    ScrollGranularity* scrollGranularity)
{
    switch (keyCode) {
    case VKEY_LEFT:
        *scrollDirection = ScrollLeft;
        *scrollGranularity = ScrollByLine;
        break;
    case VKEY_RIGHT:
        *scrollDirection = ScrollRight;
        *scrollGranularity = ScrollByLine;
        break;
    case VKEY_UP:
        *scrollDirection = ScrollUp;
        *scrollGranularity = ScrollByLine;
        break;
    case VKEY_DOWN:
        *scrollDirection = ScrollDown;
        *scrollGranularity = ScrollByLine;
        break;
    case VKEY_HOME:
        *scrollDirection = ScrollUp;
        *scrollGranularity = ScrollByDocument;
        break;
    case VKEY_END:
        *scrollDirection = ScrollDown;
        *scrollGranularity = ScrollByDocument;
        break;
    case VKEY_PRIOR:  // page up
        *scrollDirection = ScrollUp;
        *scrollGranularity = ScrollByPage;
        break;
    case VKEY_NEXT:  // page down
        *scrollDirection = ScrollDown;
        *scrollGranularity = ScrollByPage;
        break;
    default:
        return false;
    }

    return true;
}

PagePopup* WebViewImpl::openPagePopup(PagePopupClient* client)
{
    ASSERT(client);
    if (hasOpenedPopup())
        hidePopups();
    ASSERT(!m_pagePopup);

    WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypePage);
    ASSERT(popupWidget);
    m_pagePopup = toWebPagePopupImpl(popupWidget);
    if (!m_pagePopup->initialize(this, client)) {
        m_pagePopup->closePopup();
        m_pagePopup = nullptr;
    }
    enablePopupMouseWheelEventListener();
    return m_pagePopup.get();
}

void WebViewImpl::closePagePopup(PagePopup* popup)
{
    ASSERT(popup);
    WebPagePopupImpl* popupImpl = toWebPagePopupImpl(popup);
    ASSERT(m_pagePopup.get() == popupImpl);
    if (m_pagePopup.get() != popupImpl)
        return;
    m_pagePopup->closePopup();
    cleanupPagePopup();
}

void WebViewImpl::cleanupPagePopup()
{
    m_pagePopup = nullptr;
    disablePopupMouseWheelEventListener();
}

void WebViewImpl::cancelPagePopup()
{
    if (m_pagePopup)
        m_pagePopup->cancel();
}

void WebViewImpl::enablePopupMouseWheelEventListener()
{
    // TODO(kenrb): Popup coordination for out-of-process iframes needs to be
    // added. Because of the early return here a select element
    // popup can remain visible even when the element underneath it is
    // scrolled to a new position. This is part of a larger set of issues with
    // popups.
    // See https://crbug.com/566130
    if (!mainFrameImpl() || !mainFrameImpl()->frame()->isLocalFrame())
        return;
    ASSERT(!m_popupMouseWheelEventListener);
    Document* document = mainFrameImpl()->frame()->document();
    ASSERT(document);
    // We register an empty event listener, EmptyEventListener, so that mouse
    // wheel events get sent to the WebView.
    m_popupMouseWheelEventListener = EmptyEventListener::create();
    document->addEventListener(EventTypeNames::mousewheel, m_popupMouseWheelEventListener, false);
}

void WebViewImpl::disablePopupMouseWheelEventListener()
{
    // TODO(kenrb): Concerns the same as in enablePopupMouseWheelEventListener.
    // See https://crbug.com/566130
    if (!mainFrameImpl() || !mainFrameImpl()->frame()->isLocalFrame())
        return;
    ASSERT(m_popupMouseWheelEventListener);
    Document* document = mainFrameImpl()->frame()->document();
    ASSERT(document);
    // Document may have already removed the event listener, for instance, due
    // to a navigation, but remove it anyway.
    document->removeEventListener(EventTypeNames::mousewheel, m_popupMouseWheelEventListener.release(), false);
}

LocalDOMWindow* WebViewImpl::pagePopupWindow() const
{
    return m_pagePopup ? m_pagePopup->window() : nullptr;
}

Frame* WebViewImpl::focusedCoreFrame() const
{
    return m_page ? m_page->focusController().focusedOrMainFrame() : nullptr;
}

WebViewImpl* WebViewImpl::fromPage(Page* page)
{
    return page ? static_cast<WebViewImpl*>(page->chromeClient().webView()) : nullptr;
}

// WebWidget ------------------------------------------------------------------

void WebViewImpl::close()
{
    WebDevToolsAgentImpl::webViewImplClosed(this);
    ASSERT(allInstances().contains(this));
    allInstances().remove(this);

    if (m_page) {
        // Initiate shutdown for the entire frameset.  This will cause a lot of
        // notifications to be sent.
        m_page->willBeDestroyed();
        m_page.clear();
    }

    // Reset the delegate to prevent notifications being sent as we're being
    // deleted.
    m_client = nullptr;

    deref();  // Balances ref() acquired in WebView::create
}

void WebViewImpl::willStartLiveResize()
{
    if (mainFrameImpl() && mainFrameImpl()->frameView())
        mainFrameImpl()->frameView()->willStartLiveResize();
}

WebSize WebViewImpl::size()
{
    return m_size;
}

void WebViewImpl::resizeVisualViewport(const WebSize& newSize)
{
    page()->frameHost().visualViewport().setSize(newSize);
    page()->frameHost().visualViewport().clampToBoundaries();
}

void WebViewImpl::performResize()
{
    // We'll keep the initial containing block size from changing when the top
    // controls hide so that the ICB will always be the same size as the
    // viewport with the top controls shown.
    IntSize ICBSize = m_size;
    if (!topControls().shrinkViewport())
        ICBSize.expand(0, -topControls().height());

    pageScaleConstraintsSet().didChangeInitialContainingBlockSize(ICBSize);

    updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
    updateMainFrameLayoutSize();

    page()->frameHost().visualViewport().setSize(m_size);

    if (mainFrameImpl()->frameView()) {
        if (!mainFrameImpl()->frameView()->needsLayout())
            postLayoutResize(mainFrameImpl());
    }
}

void WebViewImpl::setTopControlsHeight(float height, bool topControlsShrinkLayoutSize)
{
    topControls().setHeight(height, topControlsShrinkLayoutSize);
}

void WebViewImpl::updateTopControlsState(WebTopControlsState constraint, WebTopControlsState current, bool animate)
{
    topControls().updateConstraints(constraint);
    if (m_layerTreeView)
        m_layerTreeView->updateTopControlsState(constraint, current, animate);
}

void WebViewImpl::didUpdateTopControls()
{
    if (m_layerTreeView) {
        m_layerTreeView->setTopControlsShownRatio(topControls().shownRatio());
        m_layerTreeView->setTopControlsHeight(topControls().height(), topControls().shrinkViewport());
    }

    WebLocalFrameImpl* mainFrame = mainFrameImpl();
    if (!mainFrame)
        return;

    FrameView* view = mainFrame->frameView();
    if (!view)
        return;

    VisualViewport& visualViewport = page()->frameHost().visualViewport();
    float topControlsViewportAdjustment = topControls().layoutHeight() - topControls().contentOffset();
    visualViewport.setTopControlsAdjustment(topControlsViewportAdjustment);

    // Shrink the FrameView by the amount that will maintain the aspect-ratio with the VisualViewport.
    view->setTopControlsViewportAdjustment(topControlsViewportAdjustment / minimumPageScaleFactor());
}

TopControls& WebViewImpl::topControls()
{
    return page()->frameHost().topControls();
}

void WebViewImpl::resizeViewWhileAnchored(FrameView* view)
{
    ASSERT(mainFrameImpl() && mainFrameImpl()->frame()->isLocalFrame());

    {
        // Avoids unnecessary invalidations while various bits of state in TextAutosizer are updated.
        TextAutosizer::DeferUpdatePageInfo deferUpdatePageInfo(page());
        performResize();
    }

    m_fullscreenController->updateSize();

    // Update lifecyle phases immediately to recalculate the minimum scale limit for rotation anchoring,
    // and to make sure that no lifecycle states are stale if this WebView is embedded in another one.
    updateAllLifecyclePhases();
}

void WebViewImpl::resize(const WebSize& newSize)
{
    if (m_shouldAutoResize || m_size == newSize)
        return;

    if (page()->mainFrame() && !page()->mainFrame()->isLocalFrame()) {
        // Viewport resize for a remote main frame does not require any
        // particular action, but the state needs to reflect the correct size
        // so that it can be used for initalization if the main frame gets
        // swapped to a LocalFrame at a later time.
        m_size = newSize;
        pageScaleConstraintsSet().didChangeInitialContainingBlockSize(m_size);
        page()->frameHost().visualViewport().setSize(m_size);
        return;
    }

    WebLocalFrameImpl* mainFrame = mainFrameImpl();
    if (!mainFrame)
        return;

    FrameView* view = mainFrame->frameView();
    if (!view)
        return;

    VisualViewport& visualViewport = page()->frameHost().visualViewport();

    bool isRotation = settings()->mainFrameResizesAreOrientationChanges()
        && m_size.width && contentsSize().width() && newSize.width != m_size.width && !m_fullscreenController->isFullscreen();
    m_size = newSize;

    FloatSize viewportAnchorCoords(viewportAnchorCoordX, viewportAnchorCoordY);
    if (isRotation) {
        RotationViewportAnchor anchor(*view, visualViewport, viewportAnchorCoords, pageScaleConstraintsSet());
        resizeViewWhileAnchored(view);
    } else {
        ResizeViewportAnchor anchor(*view, visualViewport);
        resizeViewWhileAnchored(view);
    }
    sendResizeEventAndRepaint();
}

void WebViewImpl::willEndLiveResize()
{
    if (mainFrameImpl() && mainFrameImpl()->frameView())
        mainFrameImpl()->frameView()->willEndLiveResize();
}

void WebViewImpl::didEnterFullScreen()
{
    m_fullscreenController->didEnterFullScreen();
}

void WebViewImpl::didExitFullScreen()
{
    m_fullscreenController->didExitFullScreen();
}

void WebViewImpl::beginFrame(double lastFrameTimeMonotonic)
{
    TRACE_EVENT1("blink", "WebViewImpl::beginFrame", "frameTime", lastFrameTimeMonotonic);
    ASSERT(lastFrameTimeMonotonic);

    // Create synthetic wheel events as necessary for fling.
    if (m_gestureAnimation) {
        if (m_gestureAnimation->animate(lastFrameTimeMonotonic))
            scheduleAnimation();
        else {
            ASSERT(m_flingSourceDevice != WebGestureDeviceUninitialized);
            WebGestureDevice lastFlingSourceDevice = m_flingSourceDevice;
            endActiveFlingAnimation();

            PlatformGestureEvent endScrollEvent(PlatformEvent::GestureScrollEnd,
                m_positionOnFlingStart, m_globalPositionOnFlingStart,
                IntSize(), 0, PlatformEvent::NoModifiers, lastFlingSourceDevice == WebGestureDeviceTouchpad ? PlatformGestureSourceTouchpad : PlatformGestureSourceTouchscreen);
            endScrollEvent.setScrollGestureData(0, 0, ScrollByPrecisePixel, 0, 0, true, false, -1 /* null plugin id */);

            mainFrameImpl()->frame()->eventHandler().handleGestureScrollEnd(endScrollEvent);
        }
    }

    if (!m_page)
        return;

    PageWidgetDelegate::animate(*m_page, lastFrameTimeMonotonic);
}

void WebViewImpl::updateAllLifecyclePhases()
{
    TRACE_EVENT0("blink", "WebViewImpl::updateAllLifecyclePhases");
    if (!mainFrameImpl())
        return;

    updateLayerTreeBackgroundColor();

    PageWidgetDelegate::updateAllLifecyclePhases(*m_page, *mainFrameImpl()->frame());

    if (InspectorOverlay* overlay = inspectorOverlay()) {
        overlay->updateAllLifecyclePhases();
        // TODO(chrishtr): integrate paint into the overlay's lifecycle.
        if (overlay->pageOverlay() && overlay->pageOverlay()->graphicsLayer())
            overlay->pageOverlay()->graphicsLayer()->paint(nullptr);
    }
    if (m_pageColorOverlay)
        m_pageColorOverlay->graphicsLayer()->paint(nullptr);

    // TODO(chrishtr): link highlights don't currently paint themselves, it's still driven by cc.
    // Fix this.
    for (size_t i = 0; i < m_linkHighlights.size(); ++i)
        m_linkHighlights[i]->updateGeometry();

    if (FrameView* view = mainFrameImpl()->frameView()) {
        LocalFrame* frame = mainFrameImpl()->frame();

        if (m_shouldDispatchFirstVisuallyNonEmptyLayout && view->isVisuallyNonEmpty()) {
            m_shouldDispatchFirstVisuallyNonEmptyLayout = false;
            // TODO(esprehn): Move users of this callback to something
            // better, the heuristic for "visually non-empty" is bad.
            client()->didMeaningfulLayout(WebMeaningfulLayout::VisuallyNonEmpty);
        }

        if (m_shouldDispatchFirstLayoutAfterFinishedParsing && frame->document()->hasFinishedParsing())  {
            m_shouldDispatchFirstLayoutAfterFinishedParsing = false;
            client()->didMeaningfulLayout(WebMeaningfulLayout::FinishedParsing);
        }

        if (m_shouldDispatchFirstLayoutAfterFinishedLoading && frame->document()->isLoadCompleted()) {
            m_shouldDispatchFirstLayoutAfterFinishedLoading = false;
            client()->didMeaningfulLayout(WebMeaningfulLayout::FinishedLoading);
        }
    }
}

void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
{
    // This should only be used when compositing is not being used for this
    // WebView, and it is painting into the recording of its parent.
    ASSERT(!isAcceleratedCompositingActive());

    double paintStart = currentTime();
    PageWidgetDelegate::paint(*m_page, canvas, rect, *m_page->deprecatedLocalMainFrame());
    double paintEnd = currentTime();
    double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart);
    Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
    Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
}

#if OS(ANDROID)
void WebViewImpl::paintCompositedDeprecated(WebCanvas* canvas, const WebRect& rect)
{
    // Note: This method exists on OS(ANDROID) and will hopefully be
    //       removed once the link disambiguation feature renders using
    //       the compositor.
    ASSERT(isAcceleratedCompositingActive());

    PageWidgetDelegate::paintIgnoringCompositing(*m_page, canvas, rect, *m_page->deprecatedLocalMainFrame());
}
#endif

void WebViewImpl::layoutAndPaintAsync(WebLayoutAndPaintAsyncCallback* callback)
{
    m_layerTreeView->layoutAndPaintAsync(callback);
}

void WebViewImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
{
    m_layerTreeView->compositeAndReadbackAsync(callback);
}

void WebViewImpl::themeChanged()
{
    if (!page())
        return;
    if (!page()->mainFrame()->isLocalFrame())
        return;
    FrameView* view = page()->deprecatedLocalMainFrame()->view();

    WebRect damagedRect(0, 0, m_size.width, m_size.height);
    view->invalidateRect(damagedRect);
}

void WebViewImpl::enterFullScreenForElement(Element* element)
{
    m_fullscreenController->enterFullScreenForElement(element);
}

void WebViewImpl::exitFullScreenForElement(Element* element)
{
    m_fullscreenController->exitFullScreenForElement(element);
}

void WebViewImpl::clearCompositedSelection()
{
    if (m_layerTreeView)
        m_layerTreeView->clearSelection();
}

void WebViewImpl::updateCompositedSelection(const WebSelection& selection)
{
    if (m_layerTreeView)
        m_layerTreeView->registerSelection(selection);
}

bool WebViewImpl::hasHorizontalScrollbar()
{
    return mainFrameImpl()->frameView()->horizontalScrollbar();
}

bool WebViewImpl::hasVerticalScrollbar()
{
    return mainFrameImpl()->frameView()->verticalScrollbar();
}

const WebInputEvent* WebViewImpl::m_currentInputEvent = nullptr;

WebInputEventResult WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
{
    // TODO(dcheng): The fact that this is getting called when there is no local
    // main frame is problematic and probably indicates a bug in the input event
    // routing code.
    if (!mainFrameImpl())
        return WebInputEventResult::NotHandled;

    WebAutofillClient* autofillClient = mainFrameImpl()->autofillClient();
    UserGestureNotifier notifier(autofillClient, &m_userGestureObserved);
    // On the first input event since page load, |notifier| instructs the
    // autofill client to unblock values of password input fields of any forms
    // on the page. There is a single input event, GestureTap, which can both
    // be the first event after page load, and cause a form submission. In that
    // case, the form submission happens before the autofill client is told
    // to unblock the password values, and so the password values are not
    // submitted. To avoid that, GestureTap is handled explicitly:
    if (inputEvent.type == WebInputEvent::GestureTap && autofillClient) {
        m_userGestureObserved = true;
        autofillClient->firstUserGestureObserved();
    }

    page()->frameHost().visualViewport().startTrackingPinchStats();

    TRACE_EVENT1("input", "WebViewImpl::handleInputEvent", "type", inputTypeToName(inputEvent.type));
    // If we've started a drag and drop operation, ignore input events until
    // we're done.
    if (m_doingDragAndDrop)
        return WebInputEventResult::HandledSuppressed;

    if (m_devToolsEmulator->handleInputEvent(inputEvent))
        return WebInputEventResult::HandledSuppressed;

    if (InspectorOverlay* overlay = inspectorOverlay()) {
        if (overlay->handleInputEvent(inputEvent))
            return WebInputEventResult::HandledSuppressed;
    }

    if (inputEvent.modifiers & WebInputEvent::IsTouchAccessibility
        && WebInputEvent::isMouseEventType(inputEvent.type)) {
        PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), static_cast<const WebMouseEvent&>(inputEvent));

        // Find the right target frame. See issue 1186900.
        HitTestResult result = hitTestResultForRootFramePos(pme.position());
        Frame* targetFrame;
        if (result.innerNodeOrImageMapImage())
            targetFrame = result.innerNodeOrImageMapImage()->document().frame();
        else
            targetFrame = m_page->focusController().focusedOrMainFrame();

        if (targetFrame->isLocalFrame()) {
            LocalFrame* targetLocalFrame = toLocalFrame(targetFrame);
            Document* document = targetLocalFrame->document();
            if (document) {
                AXObjectCache* cache = document->existingAXObjectCache();
                if (cache)
                    cache->onTouchAccessibilityHover(pme.position());
            }
        }
    }

    // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
    if (m_ignoreInputEvents)
        return WebInputEventResult::NotHandled;

    TemporaryChange<const WebInputEvent*> currentEventChange(m_currentInputEvent, &inputEvent);
    UIEventWithKeyState::clearNewTabModifierSetFromIsolatedWorld();

    if (isPointerLocked() && WebInputEvent::isMouseEventType(inputEvent.type)) {
        pointerLockMouseEvent(inputEvent);
        return WebInputEventResult::HandledSystem;
    }

    if (m_mouseCaptureNode && WebInputEvent::isMouseEventType(inputEvent.type)) {
        TRACE_EVENT1("input", "captured mouse event", "type", inputEvent.type);
        // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
        RefPtrWillBeRawPtr<Node> node = m_mouseCaptureNode;

        // Not all platforms call mouseCaptureLost() directly.
        if (inputEvent.type == WebInputEvent::MouseUp)
            mouseCaptureLost();

        OwnPtr<UserGestureIndicator> gestureIndicator;

        AtomicString eventType;
        switch (inputEvent.type) {
        case WebInputEvent::MouseMove:
            eventType = EventTypeNames::mousemove;
            break;
        case WebInputEvent::MouseLeave:
            eventType = EventTypeNames::mouseout;
            break;
        case WebInputEvent::MouseDown:
            eventType = EventTypeNames::mousedown;
            gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture));
            m_mouseCaptureGestureToken = gestureIndicator->currentToken();
            break;
        case WebInputEvent::MouseUp:
            eventType = EventTypeNames::mouseup;
            gestureIndicator = adoptPtr(new UserGestureIndicator(m_mouseCaptureGestureToken.release()));
            break;
        default:
            ASSERT_NOT_REACHED();
        }

        node->dispatchMouseEvent(
            PlatformMouseEventBuilder(mainFrameImpl()->frameView(), static_cast<const WebMouseEvent&>(inputEvent)),
            eventType, static_cast<const WebMouseEvent&>(inputEvent).clickCount);
        return WebInputEventResult::HandledSystem;
    }

    // FIXME: This should take in the intended frame, not the local frame root.
    WebInputEventResult result = PageWidgetDelegate::handleInputEvent(*this, inputEvent, mainFrameImpl()->frame());
    if (result != WebInputEventResult::NotHandled)
        return result;

    // Unhandled touchpad gesture pinch events synthesize mouse wheel events.
    if (inputEvent.type == WebInputEvent::GesturePinchUpdate) {
        const WebGestureEvent& pinchEvent = static_cast<const WebGestureEvent&>(inputEvent);

        // First, synthesize a Windows-like wheel event to send to any handlers that may exist.
        result = handleSyntheticWheelFromTouchpadPinchEvent(pinchEvent);
        if (result != WebInputEventResult::NotHandled)
            return result;

        if (pinchEvent.data.pinchUpdate.zoomDisabled)
            return WebInputEventResult::NotHandled;

        if (page()->frameHost().visualViewport().magnifyScaleAroundAnchor(pinchEvent.data.pinchUpdate.scale, FloatPoint(pinchEvent.x, pinchEvent.y)))
            return WebInputEventResult::HandledSystem;
    }

    return WebInputEventResult::NotHandled;
}

void WebViewImpl::setCursorVisibilityState(bool isVisible)
{
    if (m_page)
        m_page->setIsCursorVisible(isVisible);
}

void WebViewImpl::mouseCaptureLost()
{
    TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
    m_mouseCaptureNode = nullptr;
}

void WebViewImpl::setFocus(bool enable)
{
    m_page->focusController().setFocused(enable);
    if (enable) {
        m_page->focusController().setActive(true);
        RefPtrWillBeRawPtr<LocalFrame> focusedFrame = m_page->focusController().focusedFrame();
        if (focusedFrame) {
            Element* element = focusedFrame->document()->focusedElement();
            if (element && focusedFrame->selection().selection().isNone()) {
                // If the selection was cleared while the WebView was not
                // focused, then the focus element shows with a focus ring but
                // no caret and does respond to keyboard inputs.
                if (element->isTextFormControl()) {
                    element->updateFocusAppearance(SelectionBehaviorOnFocus::Restore);
                } else if (element->isContentEditable()) {
                    // updateFocusAppearance() selects all the text of
                    // contentseditable DIVs. So we set the selection explicitly
                    // instead. Note that this has the side effect of moving the
                    // caret back to the beginning of the text.
                    Position position(element, 0);
                    focusedFrame->selection().setSelection(VisibleSelection(position, SelDefaultAffinity));
                }
            }
        }
        m_imeAcceptEvents = true;
    } else {
        hidePopups();

        // Clear focus on the currently focused frame if any.
        if (!m_page)
            return;

        LocalFrame* frame = m_page->mainFrame() && m_page->mainFrame()->isLocalFrame()
            ? m_page->deprecatedLocalMainFrame() : nullptr;
        if (!frame)
            return;

        RefPtrWillBeRawPtr<LocalFrame> focusedFrame = m_page->focusController().focusedFrame();
        if (focusedFrame) {
            // Finish an ongoing composition to delete the composition node.
            if (focusedFrame->inputMethodController().hasComposition()) {
                WebAutofillClient* autofillClient = WebLocalFrameImpl::fromFrame(focusedFrame.get())->autofillClient();

                if (autofillClient)
                    autofillClient->setIgnoreTextChanges(true);

                focusedFrame->inputMethodController().confirmComposition();

                if (autofillClient)
                    autofillClient->setIgnoreTextChanges(false);
            }
            m_imeAcceptEvents = false;
        }
    }
}

bool WebViewImpl::setComposition(
    const WebString& text,
    const WebVector<WebCompositionUnderline>& underlines,
    int selectionStart,
    int selectionEnd)
{
    LocalFrame* focused = toLocalFrame(focusedCoreFrame());
    if (!focused || !m_imeAcceptEvents)
        return false;

    if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused))
        return plugin->setComposition(text, underlines, selectionStart, selectionEnd);

    // The input focus has been moved to another WebWidget object.
    // We should use this |editor| object only to complete the ongoing
    // composition.
    InputMethodController& inputMethodController = focused->inputMethodController();
    if (!focused->editor().canEdit() && !inputMethodController.hasComposition())
        return false;

    // We should verify the parent node of this IME composition node are
    // editable because JavaScript may delete a parent node of the composition
    // node. In this case, WebKit crashes while deleting texts from the parent
    // node, which doesn't exist any longer.
    const EphemeralRange range = inputMethodController.compositionEphemeralRange();
    if (range.isNotNull()) {
        Node* node = range.startPosition().computeContainerNode();
        if (!node || !node->isContentEditable())
            return false;
    }

    // A keypress event is canceled. If an ongoing composition exists, then the
    // keydown event should have arisen from a handled key (e.g., backspace).
    // In this case we ignore the cancellation and continue; otherwise (no
    // ongoing composition) we exit and signal success only for attempts to
    // clear the composition.
    if (m_suppressNextKeypressEvent && !inputMethodController.hasComposition())
        return text.isEmpty();

    UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);

    // When the range of composition underlines overlap with the range between
    // selectionStart and selectionEnd, WebKit somehow won't paint the selection
    // at all (see InlineTextBox::paint() function in InlineTextBox.cpp).
    // But the selection range actually takes effect.
    inputMethodController.setComposition(String(text),
                           CompositionUnderlineVectorBuilder(underlines),
                           selectionStart, selectionEnd);

    return text.isEmpty() || inputMethodController.hasComposition();
}

bool WebViewImpl::confirmComposition()
{
    return confirmComposition(DoNotKeepSelection);
}

bool WebViewImpl::confirmComposition(ConfirmCompositionBehavior selectionBehavior)
{
    return confirmComposition(WebString(), selectionBehavior);
}

bool WebViewImpl::confirmComposition(const WebString& text)
{
    return confirmComposition(text, DoNotKeepSelection);
}

bool WebViewImpl::confirmComposition(const WebString& text, ConfirmCompositionBehavior selectionBehavior)
{
    LocalFrame* focused = toLocalFrame(focusedCoreFrame());
    if (!focused || !m_imeAcceptEvents)
        return false;

    if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused))
        return plugin->confirmComposition(text, selectionBehavior);

    return focused->inputMethodController().confirmCompositionOrInsertText(text, selectionBehavior == KeepSelection ? InputMethodController::KeepSelection : InputMethodController::DoNotKeepSelection);
}

bool WebViewImpl::compositionRange(size_t* location, size_t* length)
{
    // FIXME: Long term, the focused frame should be a local frame. For now,
    // return early to avoid crashes.
    Frame* frame = focusedCoreFrame();
    if (!frame || frame->isRemoteFrame())
        return false;

    LocalFrame* focused = toLocalFrame(frame);
    if (!focused || !m_imeAcceptEvents)
        return false;

    const EphemeralRange range = focused->inputMethodController().compositionEphemeralRange();
    if (range.isNull())
        return false;

    Element* editable = focused->selection().rootEditableElementOrDocumentElement();
    ASSERT(editable);
    PlainTextRange plainTextRange(PlainTextRange::create(*editable, range));
    if (plainTextRange.isNull())
        return false;
    *location = plainTextRange.start();
    *length = plainTextRange.length();
    return true;
}

WebTextInputInfo WebViewImpl::textInputInfo()
{
    WebTextInputInfo info;

    Frame* focusedFrame = focusedCoreFrame();
    if (!focusedFrame->isLocalFrame())
        return info;

    LocalFrame* focused = toLocalFrame(focusedFrame);
    if (!focused)
        return info;

    FrameSelection& selection = focused->selection();
    Element* element = selection.selection().rootEditableElement();
    if (!element)
        return info;

    info.inputMode = inputModeOfFocusedElement();

    info.type = textInputType();
    info.flags = textInputFlags();
    if (info.type == WebTextInputTypeNone)
        return info;

    if (!focused->editor().canEdit())
        return info;

    // Emits an object replacement character for each replaced element so that
    // it is exposed to IME and thus could be deleted by IME on android.
    info.value = plainText(EphemeralRange::rangeOfContents(*element), TextIteratorEmitsObjectReplacementCharacter);

    if (info.value.isEmpty())
        return info;

    EphemeralRange firstRange = firstEphemeralRangeOf(selection.selection());
    if (firstRange.isNotNull()) {
        PlainTextRange plainTextRange(PlainTextRange::create(*element, firstRange));
        if (plainTextRange.isNotNull()) {
            info.selectionStart = plainTextRange.start();
            info.selectionEnd = plainTextRange.end();
        }
    }

    EphemeralRange range = focused->inputMethodController().compositionEphemeralRange();
    if (range.isNotNull()) {
        PlainTextRange plainTextRange(PlainTextRange::create(*element, range));
        if (plainTextRange.isNotNull()) {
            info.compositionStart = plainTextRange.start();
            info.compositionEnd = plainTextRange.end();
        }
    }

    return info;
}

WebTextInputType WebViewImpl::textInputType()
{
    LocalFrame* focusedFrame = m_page->focusController().focusedFrame();
    if (!focusedFrame)
        return WebTextInputTypeNone;

    // It's important to preserve the equivalence of textInputInfo().type and textInputType(),
    // so perform the same rootEditableElement() existence check here for consistency.
    if (!focusedFrame || !focusedFrame->selection().selection().rootEditableElement())
        return WebTextInputTypeNone;

    Document* document = focusedFrame->document();
    if (!document)
        return WebTextInputTypeNone;

    Element* element = document->focusedElement();
    if (!element)
        return WebTextInputTypeNone;

    if (isHTMLInputElement(*element)) {
        HTMLInputElement& input = toHTMLInputElement(*element);
        const AtomicString& type = input.type();

        if (input.isDisabledOrReadOnly())
            return WebTextInputTypeNone;

        if (type == InputTypeNames::password)
            return WebTextInputTypePassword;
        if (type == InputTypeNames::search)
            return WebTextInputTypeSearch;
        if (type == InputTypeNames::email)
            return WebTextInputTypeEmail;
        if (type == InputTypeNames::number)
            return WebTextInputTypeNumber;
        if (type == InputTypeNames::tel)
            return WebTextInputTypeTelephone;
        if (type == InputTypeNames::url)
            return WebTextInputTypeURL;
        if (type == InputTypeNames::date)
            return WebTextInputTypeDate;
        if (type == InputTypeNames::datetime_local)
            return WebTextInputTypeDateTimeLocal;
        if (type == InputTypeNames::month)
            return WebTextInputTypeMonth;
        if (type == InputTypeNames::time)
            return WebTextInputTypeTime;
        if (type == InputTypeNames::week)
            return WebTextInputTypeWeek;
        if (type == InputTypeNames::text)
            return WebTextInputTypeText;

        return WebTextInputTypeNone;
    }

    if (isHTMLTextAreaElement(*element)) {
        if (toHTMLTextAreaElement(*element).isDisabledOrReadOnly())
            return WebTextInputTypeNone;
        return WebTextInputTypeTextArea;
    }

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    if (element->isHTMLElement()) {
        if (toHTMLElement(element)->isDateTimeFieldElement())
            return WebTextInputTypeDateTimeField;
    }
#endif

    if (element->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable))
        return WebTextInputTypeContentEditable;

    return WebTextInputTypeNone;
}

int WebViewImpl::textInputFlags()
{
    Element* element = focusedElement();
    if (!element)
        return WebTextInputFlagNone;

    DEFINE_STATIC_LOCAL(AtomicString, autocompleteString, ("autocomplete", AtomicString::ConstructFromLiteral));
    DEFINE_STATIC_LOCAL(AtomicString, autocorrectString, ("autocorrect", AtomicString::ConstructFromLiteral));
    int flags = 0;

    const AtomicString& autocomplete = element->getAttribute(autocompleteString);
    if (autocomplete == "on")
        flags |= WebTextInputFlagAutocompleteOn;
    else if (autocomplete == "off")
        flags |= WebTextInputFlagAutocompleteOff;

    const AtomicString& autocorrect = element->getAttribute(autocorrectString);
    if (autocorrect == "on")
        flags |= WebTextInputFlagAutocorrectOn;
    else if (autocorrect == "off")
        flags |= WebTextInputFlagAutocorrectOff;

    SpellcheckAttributeState spellcheck = element->spellcheckAttributeState();
    if (spellcheck == SpellcheckAttributeTrue)
        flags |= WebTextInputFlagSpellcheckOn;
    else if (spellcheck == SpellcheckAttributeFalse)
        flags |= WebTextInputFlagSpellcheckOff;

    if (isHTMLTextFormControlElement(element)) {
        HTMLTextFormControlElement* formElement = static_cast<HTMLTextFormControlElement*>(element);
        if (formElement->supportsAutocapitalize()) {
            DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::ConstructFromLiteral));
            DEFINE_STATIC_LOCAL(const AtomicString, characters, ("characters", AtomicString::ConstructFromLiteral));
            DEFINE_STATIC_LOCAL(const AtomicString, words, ("words", AtomicString::ConstructFromLiteral));
            DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences", AtomicString::ConstructFromLiteral));

            const AtomicString& autocapitalize = formElement->autocapitalize();
            if (autocapitalize == none)
                flags |= WebTextInputFlagAutocapitalizeNone;
            else if (autocapitalize == characters)
                flags |= WebTextInputFlagAutocapitalizeCharacters;
            else if (autocapitalize == words)
                flags |= WebTextInputFlagAutocapitalizeWords;
            else if (autocapitalize == sentences)
                flags |= WebTextInputFlagAutocapitalizeSentences;
            else
                ASSERT_NOT_REACHED();
        }
    }

    return flags;
}

WebString WebViewImpl::inputModeOfFocusedElement()
{
    if (!RuntimeEnabledFeatures::inputModeAttributeEnabled())
        return WebString();

    Element* element = focusedElement();
    if (!element)
        return WebString();

    if (isHTMLInputElement(*element)) {
        const HTMLInputElement& input = toHTMLInputElement(*element);
        if (input.supportsInputModeAttribute())
            return input.fastGetAttribute(HTMLNames::inputmodeAttr).lower();
        return WebString();
    }
    if (isHTMLTextAreaElement(*element)) {
        const HTMLTextAreaElement& textarea = toHTMLTextAreaElement(*element);
        return textarea.fastGetAttribute(HTMLNames::inputmodeAttr).lower();
    }

    return WebString();
}

bool WebViewImpl::selectionBounds(WebRect& anchor, WebRect& focus) const
{
    const Frame* frame = focusedCoreFrame();
    if (!frame || !frame->isLocalFrame())
        return false;

    const LocalFrame* localFrame = toLocalFrame(frame);
    if (!localFrame)
        return false;
    FrameSelection& selection = localFrame->selection();

    if (selection.isCaret()) {
        anchor = focus = selection.absoluteCaretBounds();
    } else {
        const EphemeralRange selectedRange = selection.selection().toNormalizedEphemeralRange();
        if (selectedRange.isNull())
            return false;
        anchor = localFrame->editor().firstRectForRange(EphemeralRange(selectedRange.startPosition()));
        focus = localFrame->editor().firstRectForRange(EphemeralRange(selectedRange.endPosition()));
    }

    anchor = localFrame->view()->contentsToViewport(anchor);
    focus = localFrame->view()->contentsToViewport(focus);

    if (!selection.selection().isBaseFirst())
        std::swap(anchor, focus);
    return true;
}

WebPlugin* WebViewImpl::focusedPluginIfInputMethodSupported(LocalFrame* frame)
{
    WebPluginContainerImpl* container = WebLocalFrameImpl::pluginContainerFromNode(frame, WebNode(focusedElement()));
    if (container && container->supportsInputMethod())
        return container->plugin();
    return nullptr;
}

bool WebViewImpl::selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const
{
    const Frame* frame = focusedCoreFrame();
    if (!frame || frame->isRemoteFrame())
        return false;
    FrameSelection& selection = toLocalFrame(frame)->selection();
    if (selection.selection().toNormalizedEphemeralRange().isNull())
        return false;
    start = toWebTextDirection(primaryDirectionOf(*selection.start().anchorNode()));
    end = toWebTextDirection(primaryDirectionOf(*selection.end().anchorNode()));
    return true;
}

bool WebViewImpl::isSelectionAnchorFirst() const
{
    const Frame* frame = focusedCoreFrame();
    if (!frame || frame->isRemoteFrame())
        return false;
    return toLocalFrame(frame)->selection().selection().isBaseFirst();
}

WebColor WebViewImpl::backgroundColor() const
{
    if (isTransparent())
        return Color::transparent;
    if (!m_page)
        return m_baseBackgroundColor;
    if (!m_page->mainFrame())
        return m_baseBackgroundColor;
    if (!m_page->mainFrame()->isLocalFrame())
        return m_baseBackgroundColor;
    FrameView* view = m_page->deprecatedLocalMainFrame()->view();
    return view->documentBackgroundColor().rgb();
}

WebPagePopup* WebViewImpl::pagePopup() const
{
    return m_pagePopup.get();
}

bool WebViewImpl::caretOrSelectionRange(size_t* location, size_t* length)
{
    const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
    if (!focused)
        return false;

    PlainTextRange selectionOffsets = focused->inputMethodController().getSelectionOffsets();
    if (selectionOffsets.isNull())
        return false;

    *location = selectionOffsets.start();
    *length = selectionOffsets.length();
    return true;
}

void WebViewImpl::setTextDirection(WebTextDirection direction)
{
    // The Editor::setBaseWritingDirection() function checks if we can change
    // the text direction of the selected node and updates its DOM "dir"
    // attribute and its CSS "direction" property.
    // So, we just call the function as Safari does.
    const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
    if (!focused)
        return;

    Editor& editor = focused->editor();
    if (!editor.canEdit())
        return;

    switch (direction) {
    case WebTextDirectionDefault:
        editor.setBaseWritingDirection(NaturalWritingDirection);
        break;

    case WebTextDirectionLeftToRight:
        editor.setBaseWritingDirection(LeftToRightWritingDirection);
        break;

    case WebTextDirectionRightToLeft:
        editor.setBaseWritingDirection(RightToLeftWritingDirection);
        break;

    default:
        notImplemented();
        break;
    }
}

bool WebViewImpl::isAcceleratedCompositingActive() const
{
    // For SPv2, accelerated compositing is managed by the
    // PaintArtifactCompositor.
    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
        return m_paintArtifactCompositor.rootLayer();

    return m_rootLayer;
}

void WebViewImpl::willCloseLayerTreeView()
{
    if (m_linkHighlightsTimeline) {
        m_linkHighlights.clear();
        detachCompositorAnimationTimeline(m_linkHighlightsTimeline.get());
        m_linkHighlightsTimeline.clear();
    }

    if (m_layerTreeView)
        page()->willCloseLayerTreeView(*m_layerTreeView);

    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
        detachPaintArtifactCompositor();
    else
        setRootGraphicsLayer(nullptr);

    m_layerTreeView = nullptr;
}

void WebViewImpl::didAcquirePointerLock()
{
    if (page())
        page()->pointerLockController().didAcquirePointerLock();
}

void WebViewImpl::didNotAcquirePointerLock()
{
    if (page())
        page()->pointerLockController().didNotAcquirePointerLock();
}

void WebViewImpl::didLosePointerLock()
{
    m_pointerLockGestureToken.clear();
    if (page())
        page()->pointerLockController().didLosePointerLock();
}

void WebViewImpl::didChangeWindowResizerRect()
{
    if (mainFrameImpl()->frameView())
        mainFrameImpl()->frameView()->windowResizerRectChanged();
}

// WebView --------------------------------------------------------------------

WebSettingsImpl* WebViewImpl::settingsImpl()
{
    if (!m_webSettings)
        m_webSettings = adoptPtr(new WebSettingsImpl(&m_page->settings(), m_devToolsEmulator.get()));
    ASSERT(m_webSettings);
    return m_webSettings.get();
}

WebSettings* WebViewImpl::settings()
{
    return settingsImpl();
}

WebString WebViewImpl::pageEncoding() const
{
    if (!m_page)
        return WebString();

    if (!m_page->mainFrame()->isLocalFrame())
        return WebString();

    // FIXME: Is this check needed?
    if (!m_page->deprecatedLocalMainFrame()->document()->loader())
        return WebString();

    return m_page->deprecatedLocalMainFrame()->document()->encodingName();
}

void WebViewImpl::setPageEncoding(const WebString& encodingName)
{
    if (!m_page)
        return;

    // Only change override encoding, don't change default encoding.
    // Note that the new encoding must be 0 if it isn't supposed to be set.
    AtomicString newEncodingName;
    if (!encodingName.isEmpty())
        newEncodingName = encodingName;
    m_page->frameHost().setOverrideEncoding(newEncodingName);

    if (m_page->mainFrame()->isLocalFrame()) {
        if (!m_page->deprecatedLocalMainFrame()->loader().currentItem())
            return;
        FrameLoadRequest request = FrameLoadRequest(
            nullptr,
            m_page->deprecatedLocalMainFrame()->loader().resourceRequestForReload(
                FrameLoadTypeReload, KURL(), ClientRedirect));
        request.setClientRedirect(ClientRedirect);
        m_page->deprecatedLocalMainFrame()->loader().load(request, FrameLoadTypeReload);
    }
}

WebFrame* WebViewImpl::mainFrame()
{
    return WebFrame::fromFrame(m_page ? m_page->mainFrame() : nullptr);
}

WebFrame* WebViewImpl::findFrameByName(
    const WebString& name, WebFrame* relativeToFrame)
{
    // FIXME: Either this should only deal with WebLocalFrames or it should move to WebFrame.
    if (!relativeToFrame)
        relativeToFrame = mainFrame();
    Frame* frame = toWebLocalFrameImpl(relativeToFrame)->frame();
    frame = frame->tree().find(name);
    if (!frame || !frame->isLocalFrame())
        return nullptr;
    return WebLocalFrameImpl::fromFrame(toLocalFrame(frame));
}

WebFrame* WebViewImpl::focusedFrame()
{
    return WebFrame::fromFrame(focusedCoreFrame());
}

void WebViewImpl::setFocusedFrame(WebFrame* frame)
{
    if (!frame) {
        // Clears the focused frame if any.
        Frame* focusedFrame = focusedCoreFrame();
        if (focusedFrame && focusedFrame->isLocalFrame())
            toLocalFrame(focusedFrame)->selection().setFocused(false);
        return;
    }
    LocalFrame* coreFrame = toWebLocalFrameImpl(frame)->frame();
    coreFrame->page()->focusController().setFocusedFrame(coreFrame);
}

void WebViewImpl::focusDocumentView(WebFrame* frame)
{
    // This is currently only used when replicating focus changes for
    // cross-process frames, and |notifyEmbedder| is disabled to avoid sending
    // duplicate frameFocused updates from FocusController to the browser
    // process, which already knows the latest focused frame.
    page()->focusController().focusDocumentView(frame->toImplBase()->frame(), false /* notifyEmbedder */);
}

void WebViewImpl::setInitialFocus(bool reverse)
{
    if (!m_page)
        return;
    Frame* frame = page()->focusController().focusedOrMainFrame();
    if (frame->isLocalFrame()) {
        if (Document* document = toLocalFrame(frame)->document())
            document->clearFocusedElement();
    }
    page()->focusController().setInitialFocus(reverse ? WebFocusTypeBackward : WebFocusTypeForward);
}

void WebViewImpl::clearFocusedElement()
{
    RefPtrWillBeRawPtr<Frame> frame = focusedCoreFrame();
    if (!frame || !frame->isLocalFrame())
        return;

    LocalFrame* localFrame = toLocalFrame(frame.get());

    RefPtrWillBeRawPtr<Document> document = localFrame->document();
    if (!document)
        return;

    RefPtrWillBeRawPtr<Element> oldFocusedElement = document->focusedElement();
    document->clearFocusedElement();
    if (!oldFocusedElement)
        return;

    // If a text field has focus, we need to make sure the selection controller
    // knows to remove selection from it. Otherwise, the text field is still
    // processing keyboard events even though focus has been moved to the page and
    // keystrokes get eaten as a result.
    if (oldFocusedElement->isContentEditable() || oldFocusedElement->isTextFormControl())
        localFrame->selection().clear();
}

bool WebViewImpl::scrollFocusedNodeIntoRect(const WebRect& rectInViewport)
{
    LocalFrame* frame = page()->mainFrame() && page()->mainFrame()->isLocalFrame()
        ? page()->deprecatedLocalMainFrame() : nullptr;
    Element* element = focusedElement();
    if (!frame || !frame->view() || !element)
        return false;

    element->document().updateLayoutIgnorePendingStylesheets();

    bool zoomInToLegibleScale = m_webSettings->autoZoomFocusedNodeToLegibleScale()
        && !page()->frameHost().visualViewport().shouldDisableDesktopWorkarounds();

    if (zoomInToLegibleScale) {
        // When deciding whether to zoom in on a focused text box, we should decide not to
        // zoom in if the user won't be able to zoom out. e.g if the textbox is within a
        // touch-action: none container the user can't zoom back out.
        TouchAction action = TouchActionUtil::computeEffectiveTouchAction(*element);
        if (!(action & TouchActionPinchZoom))
            zoomInToLegibleScale = false;
    }

    float scale;
    IntPoint scroll;
    bool needAnimation;
    computeScaleAndScrollForFocusedNode(element, zoomInToLegibleScale, scale, scroll, needAnimation);
    if (needAnimation)
        return startPageScaleAnimation(scroll, false, scale, scrollAndScaleAnimationDurationInSeconds);

    return false;
}

void WebViewImpl::smoothScroll(int targetX, int targetY, long durationMs)
{
    IntPoint targetPosition(targetX, targetY);
    startPageScaleAnimation(targetPosition, false, pageScaleFactor(), (double)durationMs / 1000);
}

void WebViewImpl::computeScaleAndScrollForFocusedNode(Node* focusedNode, bool zoomInToLegibleScale, float& newScale, IntPoint& newScroll, bool& needAnimation)
{
    VisualViewport& visualViewport = page()->frameHost().visualViewport();

    WebRect caretInViewport, unusedEnd;
    selectionBounds(caretInViewport, unusedEnd);

    // 'caretInDocument' is rect encompassing the blinking cursor relative to the root document.
    IntRect caretInDocument = mainFrameImpl()->frameView()->frameToContents(visualViewport.viewportToRootFrame(caretInViewport));
    IntRect textboxRectInDocument = mainFrameImpl()->frameView()->frameToContents(
        focusedNode->document().view()->contentsToRootFrame(pixelSnappedIntRect(focusedNode->Node::boundingBox())));

    if (!zoomInToLegibleScale) {
        newScale = pageScaleFactor();
    } else {
        // Pick a scale which is reasonably readable. This is the scale at which
        // the caret height will become minReadableCaretHeightForNode (adjusted
        // for dpi and font scale factor).
        const int minReadableCaretHeightForNode = textboxRectInDocument.height() >= 2 * caretInDocument.height() ? minReadableCaretHeightForTextArea : minReadableCaretHeight;
        newScale = clampPageScaleFactorToLimits(maximumLegiblePageScale() * minReadableCaretHeightForNode / caretInDocument.height());
        newScale = std::max(newScale, pageScaleFactor());
    }
    const float deltaScale = newScale / pageScaleFactor();

    needAnimation = false;

    // If we are at less than the target zoom level, zoom in.
    if (deltaScale > minScaleChangeToTriggerZoom)
        needAnimation = true;
    else
        newScale = pageScaleFactor();

    // If the caret is offscreen, then animate.
    if (!visualViewport.visibleRectInDocument().contains(caretInDocument))
        needAnimation = true;

    // If the box is partially offscreen and it's possible to bring it fully
    // onscreen, then animate.
    if (visualViewport.visibleRect().width() >= textboxRectInDocument.width()
        && visualViewport.visibleRect().height() >= textboxRectInDocument.height()
        && !visualViewport.visibleRectInDocument().contains(textboxRectInDocument))
        needAnimation = true;

    if (!needAnimation)
        return;

    FloatSize targetViewportSize(visualViewport.size());
    targetViewportSize.scale(1 / newScale);

    if (textboxRectInDocument.width() <= targetViewportSize.width()) {
        // Field is narrower than screen. Try to leave padding on left so field's
        // label is visible, but it's more important to ensure entire field is
        // onscreen.
        int idealLeftPadding = targetViewportSize.width() * leftBoxRatio;
        int maxLeftPaddingKeepingBoxOnscreen = targetViewportSize.width() - textboxRectInDocument.width();
        newScroll.setX(textboxRectInDocument.x() - std::min<int>(idealLeftPadding, maxLeftPaddingKeepingBoxOnscreen));
    } else {
        // Field is wider than screen. Try to left-align field, unless caret would
        // be offscreen, in which case right-align the caret.
        newScroll.setX(std::max<int>(textboxRectInDocument.x(), caretInDocument.x() + caretInDocument.width() + caretPadding - targetViewportSize.width()));
    }
    if (textboxRectInDocument.height() <= targetViewportSize.height()) {
        // Field is shorter than screen. Vertically center it.
        newScroll.setY(textboxRectInDocument.y() - (targetViewportSize.height() - textboxRectInDocument.height()) / 2);
    } else {
        // Field is taller than screen. Try to top align field, unless caret would
        // be offscreen, in which case bottom-align the caret.
        newScroll.setY(std::max<int>(textboxRectInDocument.y(), caretInDocument.y() + caretInDocument.height() + caretPadding - targetViewportSize.height()));
    }
}

void WebViewImpl::advanceFocus(bool reverse)
{
    page()->focusController().advanceFocus(reverse ? WebFocusTypeBackward : WebFocusTypeForward);
}

void WebViewImpl::advanceFocusAcrossFrames(WebFocusType type, WebRemoteFrame* from, WebLocalFrame* to)
{
    // TODO(alexmos): Pass in proper with sourceCapabilities.
    page()->focusController().advanceFocusAcrossFrames(
        type, toWebRemoteFrameImpl(from)->frame(), toWebLocalFrameImpl(to)->frame());
}

double WebViewImpl::zoomLevel()
{
    return m_zoomLevel;
}

double WebViewImpl::setZoomLevel(double zoomLevel)
{
    if (zoomLevel < m_minimumZoomLevel)
        m_zoomLevel = m_minimumZoomLevel;
    else if (zoomLevel > m_maximumZoomLevel)
        m_zoomLevel = m_maximumZoomLevel;
    else
        m_zoomLevel = zoomLevel;

    // TODO(nasko): Setting zoom level needs to be refactored to support
    // out-of-process iframes. See https://crbug.com/528407.
    if (mainFrame()->isWebRemoteFrame())
        return m_zoomLevel;

    LocalFrame* frame = mainFrameImpl()->frame();
    if (!WebLocalFrameImpl::pluginContainerFromFrame(frame)) {
        float zoomFactor = m_zoomFactorOverride ? m_zoomFactorOverride : static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel));
        zoomFactor *= m_zoomFactorForDeviceScaleFactor;
        frame->setPageZoomFactor(zoomFactor);
    }

    return m_zoomLevel;
}

void WebViewImpl::zoomLimitsChanged(double minimumZoomLevel,
                                    double maximumZoomLevel)
{
    m_minimumZoomLevel = minimumZoomLevel;
    m_maximumZoomLevel = maximumZoomLevel;
    m_client->zoomLimitsChanged(m_minimumZoomLevel, m_maximumZoomLevel);
}

float WebViewImpl::textZoomFactor()
{
    return mainFrameImpl()->frame()->textZoomFactor();
}

float WebViewImpl::setTextZoomFactor(float textZoomFactor)
{
    LocalFrame* frame = mainFrameImpl()->frame();
    if (WebLocalFrameImpl::pluginContainerFromFrame(frame))
        return 1;

    frame->setTextZoomFactor(textZoomFactor);

    return textZoomFactor;
}

double WebView::zoomLevelToZoomFactor(double zoomLevel)
{
    return pow(textSizeMultiplierRatio, zoomLevel);
}

double WebView::zoomFactorToZoomLevel(double factor)
{
    // Since factor = 1.2^level, level = log(factor) / log(1.2)
    return log(factor) / log(textSizeMultiplierRatio);
}

float WebViewImpl::pageScaleFactor() const
{
    if (!page())
        return 1;

    return page()->frameHost().visualViewport().scale();
}

float WebViewImpl::clampPageScaleFactorToLimits(float scaleFactor) const
{
    return pageScaleConstraintsSet().finalConstraints().clampToConstraints(scaleFactor);
}

void WebViewImpl::setVisualViewportOffset(const WebFloatPoint& offset)
{
    ASSERT(page());
    page()->frameHost().visualViewport().setLocation(offset);
}

WebFloatPoint WebViewImpl::visualViewportOffset() const
{
    ASSERT(page());
    return page()->frameHost().visualViewport().visibleRect().location();
}

WebFloatSize WebViewImpl::visualViewportSize() const
{
    ASSERT(page());
    return page()->frameHost().visualViewport().visibleRect().size();
}

void WebViewImpl::scrollAndRescaleViewports(float scaleFactor,
    const IntPoint& mainFrameOrigin,
    const FloatPoint& visualViewportOrigin)
{
    if (!page())
        return;

    if (!mainFrameImpl())
        return;

    FrameView * view = mainFrameImpl()->frameView();
    if (!view)
        return;

    // Order is important: visual viewport location is clamped based on
    // main frame scroll position and visual viewport scale.

    view->setScrollPosition(mainFrameOrigin, ProgrammaticScroll);

    setPageScaleFactor(scaleFactor);

    page()->frameHost().visualViewport().setLocation(visualViewportOrigin);
}

void WebViewImpl::setPageScaleFactorAndLocation(float scaleFactor, const FloatPoint& location)
{
    ASSERT(page());

    page()->frameHost().visualViewport().setScaleAndLocation(
        clampPageScaleFactorToLimits(scaleFactor),
        location);
}

void WebViewImpl::setPageScaleFactor(float scaleFactor)
{
    ASSERT(page());

    scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
    if (scaleFactor == pageScaleFactor())
        return;

    page()->frameHost().visualViewport().setScale(scaleFactor);
}

void WebViewImpl::setDeviceScaleFactor(float scaleFactor)
{
    if (!page())
        return;

    page()->setDeviceScaleFactor(scaleFactor);

    if (m_layerTreeView)
        updateLayerTreeDeviceScaleFactor();
}

void WebViewImpl::setZoomFactorForDeviceScaleFactor(float zoomFactorForDeviceScaleFactor)
{
    m_zoomFactorForDeviceScaleFactor = zoomFactorForDeviceScaleFactor;
    if (!m_layerTreeView)
        return;
    setZoomLevel(m_zoomLevel);
}

void WebViewImpl::setDeviceColorProfile(const WebVector<char>& colorProfile)
{
    if (!page())
        return;

    Vector<char> deviceProfile;
    deviceProfile.append(colorProfile.data(), colorProfile.size());

    page()->setDeviceColorProfile(deviceProfile);
}

void WebViewImpl::resetDeviceColorProfileForTesting()
{
    if (!page())
        return;

    page()->resetDeviceColorProfileForTesting();
}

void WebViewImpl::enableAutoResizeMode(const WebSize& minSize, const WebSize& maxSize)
{
    m_shouldAutoResize = true;
    m_minAutoSize = minSize;
    m_maxAutoSize = maxSize;
    configureAutoResizeMode();
}

void WebViewImpl::disableAutoResizeMode()
{
    m_shouldAutoResize = false;
    configureAutoResizeMode();
}

void WebViewImpl::setDefaultPageScaleLimits(float minScale, float maxScale)
{
    return page()->frameHost().setDefaultPageScaleLimits(minScale, maxScale);
}

void WebViewImpl::setInitialPageScaleOverride(float initialPageScaleFactorOverride)
{
    PageScaleConstraints constraints = pageScaleConstraintsSet().userAgentConstraints();
    constraints.initialScale = initialPageScaleFactorOverride;

    if (constraints == pageScaleConstraintsSet().userAgentConstraints())
        return;

    pageScaleConstraintsSet().setNeedsReset(true);
    page()->frameHost().setUserAgentPageScaleConstraints(constraints);
}

void WebViewImpl::setMaximumLegibleScale(float maximumLegibleScale)
{
    m_maximumLegibleScale = maximumLegibleScale;
}

void WebViewImpl::setIgnoreViewportTagScaleLimits(bool ignore)
{
    PageScaleConstraints constraints = pageScaleConstraintsSet().userAgentConstraints();
    if (ignore) {
        constraints.minimumScale = pageScaleConstraintsSet().defaultConstraints().minimumScale;
        constraints.maximumScale = pageScaleConstraintsSet().defaultConstraints().maximumScale;
    } else {
        constraints.minimumScale = -1;
        constraints.maximumScale = -1;
    }
    page()->frameHost().setUserAgentPageScaleConstraints(constraints);
}

IntSize WebViewImpl::mainFrameSize()
{
    // The frame size should match the viewport size at minimum scale, since the
    // viewport must always be contained by the frame.
    FloatSize frameSize(m_size);
    frameSize.scale(1 / minimumPageScaleFactor());
    return expandedIntSize(frameSize);
}

PageScaleConstraintsSet& WebViewImpl::pageScaleConstraintsSet() const
{
    return page()->frameHost().pageScaleConstraintsSet();
}

void WebViewImpl::refreshPageScaleFactorAfterLayout()
{
    if (!mainFrame() || !page() || !page()->mainFrame() || !page()->mainFrame()->isLocalFrame() || !page()->deprecatedLocalMainFrame()->view())
        return;
    FrameView* view = page()->deprecatedLocalMainFrame()->view();

    updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
    pageScaleConstraintsSet().computeFinalConstraints();

    int verticalScrollbarWidth = 0;
    if (view->verticalScrollbar() && !view->verticalScrollbar()->isOverlayScrollbar())
        verticalScrollbarWidth = view->verticalScrollbar()->width();
    pageScaleConstraintsSet().adjustFinalConstraintsToContentsSize(contentsSize(), verticalScrollbarWidth, settings()->shrinksViewportContentToFit());

    float newPageScaleFactor = pageScaleFactor();
    if (pageScaleConstraintsSet().needsReset() && pageScaleConstraintsSet().finalConstraints().initialScale != -1) {
        newPageScaleFactor = pageScaleConstraintsSet().finalConstraints().initialScale;
        pageScaleConstraintsSet().setNeedsReset(false);
    }
    setPageScaleFactor(newPageScaleFactor);

    updateLayerTreeViewport();

    // Changes to page-scale during layout may require an additional frame.
    // We can't update the lifecycle here because we may be in the middle of layout in the
    // caller of this method.
    // TODO(chrishtr): clean all this up. All layout should happen in one lifecycle run (crbug.com/578239).
    if (mainFrameImpl()->frameView()->needsLayout())
        scheduleAnimation();
}

void WebViewImpl::updatePageDefinedViewportConstraints(const ViewportDescription& description)
{
    // If we're not reading the viewport meta tag, allow GPU rasterization.
    if (!settingsImpl()->viewportMetaEnabled()) {
        m_matchesHeuristicsForGpuRasterization = true;
        if (m_layerTreeView)
            m_layerTreeView->heuristicsForGpuRasterizationUpdated(m_matchesHeuristicsForGpuRasterization);
    }

    if (!settings()->viewportEnabled() || !page() || (!m_size.width && !m_size.height) || !page()->mainFrame()->isLocalFrame())
        return;

    Document* document = page()->deprecatedLocalMainFrame()->document();

    m_matchesHeuristicsForGpuRasterization = description.matchesHeuristicsForGpuRasterization();
    if (m_layerTreeView)
        m_layerTreeView->heuristicsForGpuRasterizationUpdated(m_matchesHeuristicsForGpuRasterization);

    Length defaultMinWidth = document->viewportDefaultMinWidth();
    if (defaultMinWidth.isAuto())
        defaultMinWidth = Length(ExtendToZoom);

    ViewportDescription adjustedDescription = description;
    if (settingsImpl()->viewportMetaLayoutSizeQuirk() && adjustedDescription.type == ViewportDescription::ViewportMeta) {
        const int legacyWidthSnappingMagicNumber = 320;
        if (adjustedDescription.maxWidth.isFixed() && adjustedDescription.maxWidth.value() <= legacyWidthSnappingMagicNumber)
            adjustedDescription.maxWidth = Length(DeviceWidth);
        if (adjustedDescription.maxHeight.isFixed() && adjustedDescription.maxHeight.value() <= m_size.height)
            adjustedDescription.maxHeight = Length(DeviceHeight);
        adjustedDescription.minWidth = adjustedDescription.maxWidth;
        adjustedDescription.minHeight = adjustedDescription.maxHeight;
    }

    float oldInitialScale = pageScaleConstraintsSet().pageDefinedConstraints().initialScale;
    pageScaleConstraintsSet().updatePageDefinedConstraints(adjustedDescription, defaultMinWidth);

    if (settingsImpl()->clobberUserAgentInitialScaleQuirk()
        && pageScaleConstraintsSet().userAgentConstraints().initialScale != -1
        && pageScaleConstraintsSet().userAgentConstraints().initialScale * deviceScaleFactor() <= 1) {
        if (description.maxWidth == Length(DeviceWidth)
            || (description.maxWidth.type() == Auto && pageScaleConstraintsSet().pageDefinedConstraints().initialScale == 1.0f))
            setInitialPageScaleOverride(-1);
    }

    Settings& pageSettings = page()->settings();
    pageScaleConstraintsSet().adjustForAndroidWebViewQuirks(
        adjustedDescription,
        defaultMinWidth.intValue(),
        deviceScaleFactor(),
        settingsImpl()->supportDeprecatedTargetDensityDPI(),
        pageSettings.wideViewportQuirkEnabled(),
        pageSettings.useWideViewport(),
        pageSettings.loadWithOverviewMode(),
        settingsImpl()->viewportMetaNonUserScalableQuirk());
    float newInitialScale = pageScaleConstraintsSet().pageDefinedConstraints().initialScale;
    if (oldInitialScale != newInitialScale && newInitialScale != -1) {
        pageScaleConstraintsSet().setNeedsReset(true);
        if (mainFrameImpl() && mainFrameImpl()->frameView())
            mainFrameImpl()->frameView()->setNeedsLayout();
    }


    if (LocalFrame* frame = page()->deprecatedLocalMainFrame()) {
        if (TextAutosizer* textAutosizer = frame->document()->textAutosizer())
            textAutosizer->updatePageInfoInAllFrames();
    }

    updateMainFrameLayoutSize();
}

void WebViewImpl::updateMainFrameLayoutSize()
{
    if (m_shouldAutoResize || !mainFrameImpl())
        return;

    RefPtrWillBeRawPtr<FrameView> view = mainFrameImpl()->frameView();
    if (!view)
        return;

    WebSize layoutSize = m_size;

    if (settings()->viewportEnabled())
        layoutSize = pageScaleConstraintsSet().layoutSize();

    if (page()->settings().forceZeroLayoutHeight())
        layoutSize.height = 0;

    view->setLayoutSize(layoutSize);
}

IntSize WebViewImpl::contentsSize() const
{
    if (!page()->mainFrame()->isLocalFrame())
        return IntSize();
    LayoutView* root = page()->deprecatedLocalMainFrame()->contentLayoutObject();
    if (!root)
        return IntSize();
    return root->documentRect().size();
}

WebSize WebViewImpl::contentsPreferredMinimumSize()
{
    updateAllLifecyclePhases();

    Document* document = m_page->mainFrame()->isLocalFrame() ? m_page->deprecatedLocalMainFrame()->document() : nullptr;
    if (!document || !document->layoutView() || !document->documentElement() || !document->documentElement()->layoutBox())
        return WebSize();

    int widthScaled = document->layoutView()->minPreferredLogicalWidth().round(); // Already accounts for zoom.
    int heightScaled = document->documentElement()->layoutBox()->scrollHeight().round();
    return IntSize(widthScaled, heightScaled);
}

void WebViewImpl::enableViewport()
{
    settings()->setViewportEnabled(true);
}

void WebViewImpl::disableViewport()
{
    settings()->setViewportEnabled(false);
    pageScaleConstraintsSet().clearPageDefinedConstraints();
}

float WebViewImpl::defaultMinimumPageScaleFactor() const
{
    return pageScaleConstraintsSet().defaultConstraints().minimumScale;
}

float WebViewImpl::defaultMaximumPageScaleFactor() const
{
    return pageScaleConstraintsSet().defaultConstraints().maximumScale;
}

float WebViewImpl::minimumPageScaleFactor() const
{
    return pageScaleConstraintsSet().finalConstraints().minimumScale;
}

float WebViewImpl::maximumPageScaleFactor() const
{
    return pageScaleConstraintsSet().finalConstraints().maximumScale;
}

void WebViewImpl::resetScaleStateImmediately()
{
    page()->frameHost().visualViewport().setScale(1);
    pageScaleConstraintsSet().setNeedsReset(true);
}

void WebViewImpl::resetScrollAndScaleState()
{
    page()->frameHost().visualViewport().reset();

    if (!page()->mainFrame()->isLocalFrame())
        return;

    if (FrameView* frameView = toLocalFrame(page()->mainFrame())->view()) {
        ScrollableArea* scrollableArea = frameView->layoutViewportScrollableArea();

        if (scrollableArea->scrollPositionDouble() != DoublePoint::zero())
            scrollableArea->setScrollPosition(DoublePoint::zero(), ProgrammaticScroll);
    }

    pageScaleConstraintsSet().setNeedsReset(true);
}

void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
                                           const WebPoint& location)
{
    HitTestResult result = hitTestResultForViewportPos(location);
    RefPtrWillBeRawPtr<Node> node = result.innerNode();
    if (!isHTMLVideoElement(*node) && !isHTMLAudioElement(*node))
        return;

    RefPtrWillBeRawPtr<HTMLMediaElement> mediaElement = static_pointer_cast<HTMLMediaElement>(node);
    switch (action.type) {
    case WebMediaPlayerAction::Play:
        if (action.enable)
            mediaElement->play();
        else
            mediaElement->pause();
        break;
    case WebMediaPlayerAction::Mute:
        mediaElement->setMuted(action.enable);
        break;
    case WebMediaPlayerAction::Loop:
        mediaElement->setLoop(action.enable);
        break;
    case WebMediaPlayerAction::Controls:
        mediaElement->setBooleanAttribute(HTMLNames::controlsAttr, action.enable);
        break;
    default:
        ASSERT_NOT_REACHED();
    }
}

void WebViewImpl::performPluginAction(const WebPluginAction& action,
                                      const WebPoint& location)
{
    // FIXME: Location is probably in viewport coordinates
    HitTestResult result = hitTestResultForRootFramePos(location);
    RefPtrWillBeRawPtr<Node> node = result.innerNode();
    if (!isHTMLObjectElement(*node) && !isHTMLEmbedElement(*node))
        return;

    LayoutObject* object = node->layoutObject();
    if (object && object->isLayoutPart()) {
        Widget* widget = toLayoutPart(object)->widget();
        if (widget && widget->isPluginContainer()) {
            WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget);
            switch (action.type) {
            case WebPluginAction::Rotate90Clockwise:
                plugin->plugin()->rotateView(WebPlugin::RotationType90Clockwise);
                break;
            case WebPluginAction::Rotate90Counterclockwise:
                plugin->plugin()->rotateView(WebPlugin::RotationType90Counterclockwise);
                break;
            default:
                ASSERT_NOT_REACHED();
            }
        }
    }
}

WebHitTestResult WebViewImpl::hitTestResultAt(const WebPoint& point)
{
    return coreHitTestResultAt(point);
}

HitTestResult WebViewImpl::coreHitTestResultAt(const WebPoint& pointInViewport)
{
    FrameView* view = mainFrameImpl()->frameView();
    IntPoint pointInRootFrame = view->contentsToFrame(view->viewportToContents(pointInViewport));
    return hitTestResultForRootFramePos(pointInRootFrame);
}

void WebViewImpl::copyImageAt(const WebPoint& point)
{
    if (!m_page)
        return;

    HitTestResult result = hitTestResultForViewportPos(point);
    if (!isHTMLCanvasElement(result.innerNodeOrImageMapImage()) && result.absoluteImageURL().isEmpty()) {
        // There isn't actually an image at these coordinates.  Might be because
        // the window scrolled while the context menu was open or because the page
        // changed itself between when we thought there was an image here and when
        // we actually tried to retreive the image.
        //
        // FIXME: implement a cache of the most recent HitTestResult to avoid having
        //        to do two hit tests.
        return;
    }

    m_page->deprecatedLocalMainFrame()->editor().copyImage(result);
}

void WebViewImpl::saveImageAt(const WebPoint& point)
{
    if (!m_client)
        return;

    Node* node = hitTestResultForViewportPos(point).innerNodeOrImageMapImage();
    if (!node || !(isHTMLCanvasElement(*node) || isHTMLImageElement(*node)))
        return;

    String url = toElement(*node).imageSourceURL();
    if (!KURL(KURL(), url).protocolIsData())
        return;

    m_client->saveImageFromDataURL(url);
}

void WebViewImpl::dragSourceEndedAt(
    const WebPoint& clientPoint,
    const WebPoint& screenPoint,
    WebDragOperation operation)
{
    PlatformMouseEvent pme(clientPoint, screenPoint, LeftButton, PlatformEvent::MouseMoved,
        0, PlatformEvent::NoModifiers, PlatformMouseEvent::RealOrIndistinguishable, WTF::monotonicallyIncreasingTime());
    m_page->deprecatedLocalMainFrame()->eventHandler().dragSourceEndedAt(pme,
        static_cast<DragOperation>(operation));
}

void WebViewImpl::dragSourceSystemDragEnded()
{
    // It's possible for us to get this callback while not doing a drag if
    // it's from a previous page that got unloaded.
    if (m_doingDragAndDrop) {
        m_page->dragController().dragEnded();
        m_doingDragAndDrop = false;
    }
}

WebDragOperation WebViewImpl::dragTargetDragEnter(
    const WebDragData& webDragData,
    const WebPoint& clientPoint,
    const WebPoint& screenPoint,
    WebDragOperationsMask operationsAllowed,
    int modifiers)
{
    ASSERT(!m_currentDragData);

    m_currentDragData = DataObject::create(webDragData);
    m_operationsAllowed = operationsAllowed;

    return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragEnter, modifiers);
}

WebDragOperation WebViewImpl::dragTargetDragOver(
    const WebPoint& clientPoint,
    const WebPoint& screenPoint,
    WebDragOperationsMask operationsAllowed,
    int modifiers)
{
    m_operationsAllowed = operationsAllowed;

    return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragOver, modifiers);
}

void WebViewImpl::dragTargetDragLeave()
{
    ASSERT(m_currentDragData);

    DragData dragData(
        m_currentDragData.get(),
        IntPoint(),
        IntPoint(),
        static_cast<DragOperation>(m_operationsAllowed));

    m_page->dragController().dragExited(&dragData);

    // FIXME: why is the drag scroll timer not stopped here?

    m_dragOperation = WebDragOperationNone;
    m_currentDragData = nullptr;
}

void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
                                 const WebPoint& screenPoint,
                                 int modifiers)
{
    ASSERT(m_currentDragData);

    WebAutofillClient* autofillClient = mainFrameImpl() ? mainFrameImpl()->autofillClient() : 0;
    UserGestureNotifier notifier(autofillClient, &m_userGestureObserved);

    // If this webview transitions from the "drop accepting" state to the "not
    // accepting" state, then our IPC message reply indicating that may be in-
    // flight, or else delayed by javascript processing in this webview.  If a
    // drop happens before our IPC reply has reached the browser process, then
    // the browser forwards the drop to this webview.  So only allow a drop to
    // proceed if our webview m_dragOperation state is not DragOperationNone.

    if (m_dragOperation == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop.
        dragTargetDragLeave();
        return;
    }

    m_currentDragData->setModifiers(modifiers);
    DragData dragData(
        m_currentDragData.get(),
        clientPoint,
        screenPoint,
        static_cast<DragOperation>(m_operationsAllowed));

    UserGestureIndicator gesture(DefinitelyProcessingNewUserGesture);
    m_page->dragController().performDrag(&dragData);

    m_dragOperation = WebDragOperationNone;
    m_currentDragData = nullptr;
}

void WebViewImpl::spellingMarkers(WebVector<uint32_t>* markers)
{
    Vector<uint32_t> result;
    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
        if (!frame->isLocalFrame())
            continue;
        const DocumentMarkerVector& documentMarkers = toLocalFrame(frame)->document()->markers().markers();
        for (size_t i = 0; i < documentMarkers.size(); ++i)
            result.append(documentMarkers[i]->hash());
    }
    markers->assign(result);
}

void WebViewImpl::removeSpellingMarkersUnderWords(const WebVector<WebString>& words)
{
    Vector<String> convertedWords;
    convertedWords.append(words.data(), words.size());

    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
        if (frame->isLocalFrame())
            toLocalFrame(frame)->removeSpellingMarkersUnderWords(convertedWords);
    }
}

WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPoint, const WebPoint& screenPoint, DragAction dragAction, int modifiers)
{
    ASSERT(m_currentDragData);

    m_currentDragData->setModifiers(modifiers);
    DragData dragData(
        m_currentDragData.get(),
        clientPoint,
        screenPoint,
        static_cast<DragOperation>(m_operationsAllowed));

    DragSession dragSession;
    if (dragAction == DragEnter)
        dragSession = m_page->dragController().dragEntered(&dragData);
    else
        dragSession = m_page->dragController().dragUpdated(&dragData);

    DragOperation dropEffect = dragSession.operation;

    // Mask the drop effect operation against the drag source's allowed operations.
    if (!(dropEffect & dragData.draggingSourceOperationMask()))
        dropEffect = DragOperationNone;

     m_dragOperation = static_cast<WebDragOperation>(dropEffect);

    return m_dragOperation;
}

void WebViewImpl::sendResizeEventAndRepaint()
{
    // FIXME: This is wrong. The FrameView is responsible sending a resizeEvent
    // as part of layout. Layout is also responsible for sending invalidations
    // to the embedder. This method and all callers may be wrong. -- eseidel.
    if (mainFrameImpl()->frameView()) {
        // Enqueues the resize event.
        mainFrameImpl()->frame()->document()->enqueueResizeEvent();
    }

    if (m_client) {
        if (m_layerTreeView) {
            updateLayerTreeViewport();
        } else {
            WebRect damagedRect(0, 0, m_size.width, m_size.height);
            m_client->didInvalidateRect(damagedRect);
        }
    }
    updatePageOverlays();
}

void WebViewImpl::configureAutoResizeMode()
{
    if (!mainFrameImpl() || !mainFrameImpl()->frame() || !mainFrameImpl()->frame()->view())
        return;

    if (m_shouldAutoResize)
        mainFrameImpl()->frame()->view()->enableAutoSizeMode(m_minAutoSize, m_maxAutoSize);
    else
        mainFrameImpl()->frame()->view()->disableAutoSizeMode();
}

unsigned long WebViewImpl::createUniqueIdentifierForRequest()
{
    return createUniqueIdentifier();
}

void WebViewImpl::setCompositorDeviceScaleFactorOverride(float deviceScaleFactor)
{
    if (m_compositorDeviceScaleFactorOverride == deviceScaleFactor)
        return;
    m_compositorDeviceScaleFactorOverride = deviceScaleFactor;
    if (page() && m_layerTreeView)
        updateLayerTreeDeviceScaleFactor();
}

void WebViewImpl::setRootLayerTransform(const WebSize& rootLayerOffset, float rootLayerScale)
{
    if (m_rootLayerScale == rootLayerScale && m_rootLayerOffset == rootLayerOffset)
        return;
    m_rootLayerScale = rootLayerScale;
    m_rootLayerOffset = rootLayerOffset;
    if (mainFrameImpl())
        mainFrameImpl()->setInputEventsTransformForEmulation(m_rootLayerOffset, m_rootLayerScale);
    updateRootLayerTransform();
}

void WebViewImpl::enableDeviceEmulation(const WebDeviceEmulationParams& params)
{
    m_devToolsEmulator->enableDeviceEmulation(params);
}

void WebViewImpl::disableDeviceEmulation()
{
    m_devToolsEmulator->disableDeviceEmulation();
}

WebAXObject WebViewImpl::accessibilityObject()
{
    if (!mainFrameImpl())
        return WebAXObject();

    Document* document = mainFrameImpl()->frame()->document();
    return WebAXObject(toAXObjectCacheImpl(document->axObjectCache())->root());
}

void WebViewImpl::performCustomContextMenuAction(unsigned action)
{
    if (!m_page)
        return;
    ContextMenu* menu = m_page->contextMenuController().contextMenu();
    if (!menu)
        return;
    const ContextMenuItem* item = menu->itemWithAction(static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + action));
    if (item)
        m_page->contextMenuController().contextMenuItemSelected(item);
    m_page->contextMenuController().clearContextMenu();
}

void WebViewImpl::showContextMenu()
{
    if (!page())
        return;

    page()->contextMenuController().clearContextMenu();
    {
        ContextMenuAllowedScope scope;
        if (LocalFrame* focusedFrame = toLocalFrame(page()->focusController().focusedOrMainFrame()))
            focusedFrame->eventHandler().sendContextMenuEventForKey(nullptr);
    }
}

void WebViewImpl::didCloseContextMenu()
{
    LocalFrame* frame = m_page->focusController().focusedFrame();
    if (frame)
        frame->selection().setCaretBlinkingSuspended(false);
}

void WebViewImpl::extractSmartClipData(WebRect rectInViewport, WebString& clipText, WebString& clipHtml, WebRect& clipRectInViewport)
{
    LocalFrame* localFrame = toLocalFrame(focusedCoreFrame());
    if (!localFrame)
        return;
    SmartClipData clipData = SmartClip(localFrame).dataForRect(rectInViewport);
    clipText = clipData.clipData();
    clipRectInViewport = clipData.rectInViewport();

    WebLocalFrameImpl* frame = mainFrameImpl();
    if (!frame)
        return;
    WebPoint startPoint(rectInViewport.x, rectInViewport.y);
    WebPoint endPoint(rectInViewport.x + rectInViewport.width, rectInViewport.y + rectInViewport.height);
    VisiblePosition startVisiblePosition = frame->visiblePositionForViewportPoint(startPoint);
    VisiblePosition endVisiblePosition = frame->visiblePositionForViewportPoint(endPoint);

    Position startPosition = startVisiblePosition.deepEquivalent();
    Position endPosition = endVisiblePosition.deepEquivalent();

    // document() will return null if -webkit-user-select is set to none.
    if (!startPosition.document() || !endPosition.document())
        return;

    clipHtml = createMarkup(startPosition, endPosition, AnnotateForInterchange, ConvertBlocksToInlines::NotConvert, ResolveNonLocalURLs);
}

void WebViewImpl::hidePopups()
{
    cancelPagePopup();
}

void WebViewImpl::setIsTransparent(bool isTransparent)
{
    // Set any existing frames to be transparent.
    Frame* frame = m_page->mainFrame();
    while (frame) {
        if (frame->isLocalFrame())
            toLocalFrame(frame)->view()->setTransparent(isTransparent);
        frame = frame->tree().traverseNext();
    }

    // Future frames check this to know whether to be transparent.
    m_isTransparent = isTransparent;

    if (m_layerTreeView)
        m_layerTreeView->setHasTransparentBackground(this->isTransparent());
}

bool WebViewImpl::isTransparent() const
{
    return m_isTransparent;
}

void WebViewImpl::setBaseBackgroundColor(WebColor color)
{
    if (m_baseBackgroundColor == color)
        return;

    m_baseBackgroundColor = color;

    if (m_page->mainFrame() && m_page->mainFrame()->isLocalFrame())
        m_page->deprecatedLocalMainFrame()->view()->setBaseBackgroundColor(color);

    updateAllLifecyclePhases();
}

void WebViewImpl::setIsActive(bool active)
{
    if (page())
        page()->focusController().setActive(active);
}

bool WebViewImpl::isActive() const
{
    return page() ? page()->focusController().isActive() : false;
}

void WebViewImpl::setDomainRelaxationForbidden(bool forbidden, const WebString& scheme)
{
    SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme));
}

void WebViewImpl::setWindowFeatures(const WebWindowFeatures& features)
{
    m_page->chromeClient().setWindowFeatures(features);
}

void WebViewImpl::setOpenedByDOM()
{
    m_page->setOpenedByDOM();
}

void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor,
                                     unsigned activeForegroundColor,
                                     unsigned inactiveBackgroundColor,
                                     unsigned inactiveForegroundColor) {
#if USE(DEFAULT_RENDER_THEME)
    LayoutThemeDefault::setSelectionColors(activeBackgroundColor, activeForegroundColor, inactiveBackgroundColor, inactiveForegroundColor);
    LayoutTheme::theme().platformColorsDidChange();
#endif
}

void WebViewImpl::didCommitLoad(bool isNewNavigation, bool isNavigationWithinPage)
{
    if (!isNavigationWithinPage) {
        m_shouldDispatchFirstVisuallyNonEmptyLayout = true;
        m_shouldDispatchFirstLayoutAfterFinishedParsing = true;
        m_shouldDispatchFirstLayoutAfterFinishedLoading = true;

        if (isNewNavigation) {
            pageScaleConstraintsSet().setNeedsReset(true);
            m_pageImportanceSignals.onCommitLoad();
        }
    }

    // Give the visual viewport's scroll layer its initial size.
    page()->frameHost().visualViewport().mainFrameDidChangeSize();

    // Make sure link highlight from previous page is cleared.
    m_linkHighlights.clear();
    endActiveFlingAnimation();
    m_userGestureObserved = false;
}

void WebViewImpl::mainFrameDocumentElementAvailable()
{
    // This check is necessary to avoid provisional frames
    // (see WebLocalFrame::createProvisional) leaking
    // their calls into WebViewImpl.
    // See http://crbug.com/578349 for details.
    // TODO(dcheng): Remove this when the provisional frames
    // bite the dust.
    if (!mainFrameImpl())
        return;

    // For non-HTML documents the willInsertBody notification won't happen
    // so we resume as soon as we have a document element. Even for XHTML
    // documents there may never be a <body> (since the parser won't always
    // insert one), so we resume here too. That does mean XHTML documents make
    // frames when there's only a <head>, but such documents are pretty rare.
    if (!mainFrameImpl()->frame()->document()->isHTMLDocument())
        resumeTreeViewCommitsIfRenderingReady();
}

void WebViewImpl::willInsertMainFrameDocumentBody()
{
    // This check is necessary to avoid provisional frames
    // (see WebLocalFrame::createProvisional) leaking
    // their calls into WebViewImpl.
    // See http://crbug.com/578349 for details.
    // TODO(dcheng): Remove this when the provisional frames
    // bite the dust.
    if (!mainFrameImpl())
        return;

    // If we get to the <body> try to resume commits since we should have content
    // to paint now.
    // TODO(esprehn): Is this really optimal? We might start producing frames
    // for very little content, should we wait for some heuristic like
    // isVisuallyNonEmpty() ?
    resumeTreeViewCommitsIfRenderingReady();
}

void WebViewImpl::didFinishMainFrameDocumentLoad()
{
    resumeTreeViewCommitsIfRenderingReady();
#if OS(ANDROID)
    if (!isInternalURL(mainFrameImpl()->frame()->document()->baseURL()) && page()->settings().usesEncodingDetector()) {
        const Document& document = *mainFrameImpl()->frame()->document();

        // "AutodetectEncoding.Attempted" is of boolean type - either 0 or 1. Use 2 for the boundary value.
        Platform::current()->histogramEnumeration("AutodetectEncoding.Attempted", document.attemptedToDetermineEncodingFromContentSniffing(), 2);
        if (document.encodingWasDetectedFromContentSniffing()) {
            int encodingId = encodingToUmaId(document.encoding());
            Platform::current()->histogramEnumeration("AutodetectEncoding.Detected", encodingId, WTF_ARRAY_LENGTH(kEncodingNames) + 1);
        }
    }
#endif
}

void WebViewImpl::didRemoveAllPendingStylesheetsInMainFrameDocument()
{
    Document& document = *mainFrameImpl()->frame()->document();

    // For HTML if we have no more stylesheets to load and we're past the body
    // tag, we should have something to paint so resume.
    if (document.isHTMLDocument() && !document.body())
        return;

    // For non-HTML there is no body so resume as soon as the sheets are loaded.
    if (!document.isHTMLDocument() && !document.documentElement())
        return;

    resumeTreeViewCommitsIfRenderingReady();
}

void WebViewImpl::resumeTreeViewCommitsIfRenderingReady()
{
    LocalFrame* frame = mainFrameImpl()->frame();
    if (!frame->loader().stateMachine()->committedFirstRealDocumentLoad())
        return;
    if (!frame->document()->isRenderingReady())
        return;
    if (m_layerTreeView) {
        m_layerTreeView->setDeferCommits(false);
        m_layerTreeView->setNeedsBeginFrame();
    }
}

void WebViewImpl::postLayoutResize(WebLocalFrameImpl* webframe)
{
    FrameView* view = webframe->frame()->view();
    if (webframe == mainFrame())
        view->resize(mainFrameSize());
    else
        view->resize(webframe->frameView()->size());
}

void WebViewImpl::layoutUpdated(WebLocalFrameImpl* webframe)
{
    LocalFrame* frame = webframe->frame();
    if (!m_client || !frame->isLocalRoot())
        return;

    if (m_shouldAutoResize) {
        WebSize frameSize = frame->view()->frameRect().size();
        if (frameSize != m_size) {
            m_size = frameSize;

            page()->frameHost().visualViewport().setSize(m_size);
            pageScaleConstraintsSet().didChangeInitialContainingBlockSize(m_size);

            m_client->didAutoResize(m_size);
            sendResizeEventAndRepaint();
        }
    }

    if (pageScaleConstraintsSet().constraintsDirty())
        refreshPageScaleFactorAfterLayout();

    FrameView* view = webframe->frame()->view();

    postLayoutResize(webframe);

    // Relayout immediately to avoid violating the rule that needsLayout()
    // isn't set at the end of a layout.
    if (view->needsLayout())
        view->layout();

    // In case we didn't have a size when the top controls were updated.
    didUpdateTopControls();

    m_client->didUpdateLayout();
}

void WebViewImpl::didChangeContentsSize()
{
    pageScaleConstraintsSet().didChangeContentsSize(contentsSize(), pageScaleFactor());
}

void WebViewImpl::pageScaleFactorChanged()
{
    pageScaleConstraintsSet().setNeedsReset(false);
    updateLayerTreeViewport();
    m_client->pageScaleFactorChanged();
}

bool WebViewImpl::useExternalPopupMenus()
{
    return shouldUseExternalPopupMenus;
}

void WebViewImpl::startDragging(LocalFrame* frame,
                                const WebDragData& dragData,
                                WebDragOperationsMask mask,
                                const WebImage& dragImage,
                                const WebPoint& dragImageOffset)
{
    if (!m_client)
        return;
    ASSERT(!m_doingDragAndDrop);
    m_doingDragAndDrop = true;
    m_client->startDragging(WebLocalFrameImpl::fromFrame(frame), dragData, mask, dragImage, dragImageOffset);
}

void WebViewImpl::setIgnoreInputEvents(bool newValue)
{
    ASSERT(m_ignoreInputEvents != newValue);
    m_ignoreInputEvents = newValue;
}

void WebViewImpl::setBackgroundColorOverride(WebColor color)
{
    m_backgroundColorOverride = color;
    updateLayerTreeBackgroundColor();
}

void WebViewImpl::setZoomFactorOverride(float zoomFactor)
{
    m_zoomFactorOverride = zoomFactor;
    setZoomLevel(zoomLevel());
}

void WebViewImpl::setPageOverlayColor(WebColor color)
{
    if (m_pageColorOverlay)
        m_pageColorOverlay.clear();

    if (color == Color::transparent)
        return;

    m_pageColorOverlay = PageOverlay::create(this, new ColorOverlay(color));
    m_pageColorOverlay->update();
}

WebPageImportanceSignals* WebViewImpl::pageImportanceSignals()
{
    return &m_pageImportanceSignals;
}

Element* WebViewImpl::focusedElement() const
{
    LocalFrame* frame = m_page->focusController().focusedFrame();
    if (!frame)
        return nullptr;

    Document* document = frame->document();
    if (!document)
        return nullptr;

    return document->focusedElement();
}

HitTestResult WebViewImpl::hitTestResultForViewportPos(const IntPoint& posInViewport)
{
    IntPoint rootFramePoint(m_page->frameHost().visualViewport().viewportToRootFrame(posInViewport));
    return hitTestResultForRootFramePos(rootFramePoint);
}

HitTestResult WebViewImpl::hitTestResultForRootFramePos(const IntPoint& posInRootFrame)
{
    if (!m_page->mainFrame()->isLocalFrame())
        return HitTestResult();
    IntPoint docPoint(m_page->deprecatedLocalMainFrame()->view()->rootFrameToContents(posInRootFrame));
    HitTestResult result = m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
    result.setToShadowHostIfInUserAgentShadowRoot();
    return result;
}

WebHitTestResult WebViewImpl::hitTestResultForTap(const WebPoint& tapPointWindowPos, const WebSize& tapArea)
{
    if (!m_page->mainFrame()->isLocalFrame())
        return HitTestResult();

    WebGestureEvent tapEvent;
    tapEvent.x = tapPointWindowPos.x;
    tapEvent.y = tapPointWindowPos.y;
    tapEvent.type = WebInputEvent::GestureTap;
    // GestureTap is only ever from a touchscreen.
    tapEvent.sourceDevice = WebGestureDeviceTouchscreen;
    tapEvent.data.tap.tapCount = 1;
    tapEvent.data.tap.width = tapArea.width;
    tapEvent.data.tap.height = tapArea.height;

    PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), tapEvent);

    HitTestResult result = m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultForGestureEvent(platformEvent, HitTestRequest::ReadOnly | HitTestRequest::Active).hitTestResult();

    result.setToShadowHostIfInUserAgentShadowRoot();
    return result;
}

void WebViewImpl::setTabsToLinks(bool enable)
{
    m_tabsToLinks = enable;
}

bool WebViewImpl::tabsToLinks() const
{
    return m_tabsToLinks;
}

void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
{
    if (!m_layerTreeView)
        return;

    // In SPv2, we attach layers via PaintArtifactCompositor, rather than
    // supplying a root GraphicsLayer from PaintLayerCompositor.
    ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled());

    VisualViewport& visualViewport = page()->frameHost().visualViewport();
    visualViewport.attachToLayerTree(layer, graphicsLayerFactory());
    if (layer) {
        m_rootGraphicsLayer = visualViewport.rootGraphicsLayer();
        m_rootLayer = m_rootGraphicsLayer->platformLayer();
        updateRootLayerTransform();
        m_layerTreeView->setRootLayer(*m_rootLayer);
        // We register viewport layers here since there may not be a layer
        // tree view prior to this point.
        visualViewport.registerLayersWithTreeView(m_layerTreeView);
        updatePageOverlays();
        // TODO(enne): Work around page visibility changes not being
        // propagated to the WebView in some circumstances.  This needs to
        // be refreshed here when setting a new root layer to avoid being
        // stuck in a presumed incorrectly invisible state.
        m_layerTreeView->setVisible(page()->isPageVisible());
    } else {
        m_rootGraphicsLayer = nullptr;
        m_rootLayer = nullptr;
        // This means that we're transitioning to a new page. Suppress
        // commits until Blink generates invalidations so we don't
        // attempt to paint too early in the next page load.
        m_layerTreeView->setDeferCommits(true);
        m_layerTreeView->clearRootLayer();
        visualViewport.clearLayersForTreeView(m_layerTreeView);
    }
}

void WebViewImpl::invalidateRect(const IntRect& rect)
{
    if (m_layerTreeView)
        updateLayerTreeViewport();
    else if (m_client)
        m_client->didInvalidateRect(rect);
}

GraphicsLayerFactory* WebViewImpl::graphicsLayerFactory() const
{
    return m_graphicsLayerFactory.get();
}

PaintLayerCompositor* WebViewImpl::compositor() const
{
    WebLocalFrameImpl* frame = mainFrameImpl();
    if (!frame)
        return nullptr;

    Document* document = frame->frame()->document();
    if (!document || !document->layoutView())
        return nullptr;

    return document->layoutView()->compositor();
}

void WebViewImpl::registerForAnimations(WebLayer* layer)
{
    if (m_layerTreeView)
        m_layerTreeView->registerForAnimations(layer);
}

GraphicsLayer* WebViewImpl::rootGraphicsLayer()
{
    return m_rootGraphicsLayer;
}

void WebViewImpl::scheduleAnimation()
{
    if (m_layerTreeView) {
        m_layerTreeView->setNeedsBeginFrame();
        return;
    }
    if (m_client)
        m_client->scheduleAnimation();
}

void WebViewImpl::attachCompositorAnimationTimeline(WebCompositorAnimationTimeline* timeline)
{
    if (m_layerTreeView)
        m_layerTreeView->attachCompositorAnimationTimeline(timeline);
}

void WebViewImpl::detachCompositorAnimationTimeline(WebCompositorAnimationTimeline* timeline)
{
    if (m_layerTreeView)
        m_layerTreeView->detachCompositorAnimationTimeline(timeline);
}

void WebViewImpl::initializeLayerTreeView()
{
    if (m_client) {
        m_client->initializeLayerTreeView();
        m_layerTreeView = m_client->layerTreeView();
    }

    if (WebDevToolsAgentImpl* devTools = mainFrameDevToolsAgentImpl())
        devTools->layerTreeViewChanged(m_layerTreeView);

    m_page->settings().setAcceleratedCompositingEnabled(m_layerTreeView);
    if (m_layerTreeView)
        m_page->layerTreeViewInitialized(*m_layerTreeView);

    // FIXME: only unittests, click to play, Android printing, and printing (for headers and footers)
    // make this assert necessary. We should make them not hit this code and then delete allowsBrokenNullLayerTreeView.
    ASSERT(m_layerTreeView || !m_client || m_client->allowsBrokenNullLayerTreeView());

    if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled() && Platform::current()->isThreadedAnimationEnabled() && m_layerTreeView) {
        ASSERT(Platform::current()->compositorSupport());
        m_linkHighlightsTimeline = adoptPtr(Platform::current()->compositorSupport()->createAnimationTimeline());
        attachCompositorAnimationTimeline(m_linkHighlightsTimeline.get());
    }

    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
        attachPaintArtifactCompositor();
}

void WebViewImpl::applyViewportDeltas(
    const WebFloatSize& visualViewportDelta,
    const WebFloatSize& layoutViewportDelta,
    const WebFloatSize& elasticOverscrollDelta,
    float pageScaleDelta,
    float topControlsShownRatioDelta)
{
    if (!mainFrameImpl())
        return;
    FrameView* frameView = mainFrameImpl()->frameView();
    if (!frameView)
        return;

    topControls().setShownRatio(topControls().shownRatio() + topControlsShownRatioDelta);

    FloatPoint visualViewportOffset = page()->frameHost().visualViewport().visibleRect().location();
    visualViewportOffset.move(visualViewportDelta.width, visualViewportDelta.height);
    setPageScaleFactorAndLocation(pageScaleFactor() * pageScaleDelta, visualViewportOffset);

    if (pageScaleDelta != 1) {
        m_doubleTapZoomPending = false;
        page()->frameHost().visualViewport().userDidChangeScale();
    }

    m_elasticOverscroll += elasticOverscrollDelta;
    frameView->didUpdateElasticOverscroll();

    ScrollableArea* layoutViewport = frameView->layoutViewportScrollableArea();

    DoublePoint layoutViewportPosition = layoutViewport->scrollPositionDouble()
        + DoubleSize(layoutViewportDelta.width, layoutViewportDelta.height);

    if (layoutViewport->scrollPositionDouble() != layoutViewportPosition) {
        layoutViewport->setScrollPosition(layoutViewportPosition, CompositorScroll);
        if (DocumentLoader* documentLoader = mainFrameImpl()->frame()->loader().documentLoader())
            documentLoader->initialScrollState().wasScrolledByUser = true;
    }
}

void WebViewImpl::recordFrameTimingEvent(FrameTimingEventType eventType, int64_t FrameId, const WebVector<WebFrameTimingEvent>& events)
{
    Frame* frame = m_page ? m_page->mainFrame() : 0;

    while (frame && frame->frameID() != FrameId) {
        frame = frame->tree().traverseNext();
    }

    if (!frame || !frame->domWindow() || !frame->domWindow()->document())
        return; // Can't find frame, it may have been cleaned up from the DOM.

    blink::DOMWindow* domWindow = frame->domWindow();
    blink::Performance* performance = DOMWindowPerformance::performance(*domWindow);
    for (size_t i = 0; i < events.size(); ++i) {
        if (eventType == CompositeEvent)
            performance->addCompositeTiming(domWindow->document(), events[i].sourceFrame, events[i].startTime);
        else if (eventType == RenderEvent)
            performance->addRenderTiming(domWindow->document(), events[i].sourceFrame, events[i].startTime, events[i].finishTime);
    }
}

void WebViewImpl::updateLayerTreeViewport()
{
    if (!page() || !m_layerTreeView)
        return;

    m_layerTreeView->setPageScaleFactorAndLimits(pageScaleFactor(), minimumPageScaleFactor(), maximumPageScaleFactor());
}

void WebViewImpl::updateLayerTreeBackgroundColor()
{
    if (!m_layerTreeView)
        return;

    m_layerTreeView->setBackgroundColor(alphaChannel(m_backgroundColorOverride) ? m_backgroundColorOverride : backgroundColor());
}

void WebViewImpl::updateLayerTreeDeviceScaleFactor()
{
    ASSERT(page());
    ASSERT(m_layerTreeView);

    float deviceScaleFactor = m_compositorDeviceScaleFactorOverride ? m_compositorDeviceScaleFactorOverride : page()->deviceScaleFactor();
    m_layerTreeView->setDeviceScaleFactor(deviceScaleFactor);
}

void WebViewImpl::updateRootLayerTransform()
{
    if (m_rootGraphicsLayer) {
        TransformationMatrix transform;
        transform.translate(m_rootLayerOffset.width, m_rootLayerOffset.height);
        transform = transform.scale(m_rootLayerScale);
        m_rootGraphicsLayer->setTransform(transform);
    }
}

bool WebViewImpl::detectContentOnTouch(const GestureEventWithHitTestResults& targetedEvent)
{
    if (!m_page->mainFrame()->isLocalFrame())
        return false;

    // Need a local copy of the hit test as setToShadowHostIfInUserAgentShadowRoot() will modify it.
    HitTestResult touchHit = targetedEvent.hitTestResult();
    touchHit.setToShadowHostIfInUserAgentShadowRoot();

    if (touchHit.isContentEditable())
        return false;

    Node* node = touchHit.innerNode();
    if (!node || !node->isTextNode())
        return false;

    // Ignore when tapping on links or nodes listening to click events, unless the click event is on the
    // body element, in which case it's unlikely that the original node itself was intended to be clickable.
    for (; node && !isHTMLBodyElement(*node); node = LayoutTreeBuilderTraversal::parent(*node)) {
        if (node->isLink() || node->willRespondToTouchEvents() || node->willRespondToMouseClickEvents())
            return false;
    }

    WebContentDetectionResult content = m_client->detectContentAround(touchHit);
    if (!content.isValid())
        return false;

    // This code is called directly after hit test code, with no user code running in between,
    // thus it is assumed that the frame pointer is non-null.
    bool isMainFrame = node ? node->document().frame()->isMainFrame() : true;
    m_client->scheduleContentIntent(content.intent(), isMainFrame);
    return true;
}

void WebViewImpl::setVisibilityState(WebPageVisibilityState visibilityState,
                                     bool isInitialState) {
    ASSERT(visibilityState == WebPageVisibilityStateVisible || visibilityState == WebPageVisibilityStateHidden || visibilityState == WebPageVisibilityStatePrerender);

    if (page())
        m_page->setVisibilityState(static_cast<PageVisibilityState>(static_cast<int>(visibilityState)), isInitialState);

    bool visible = visibilityState == WebPageVisibilityStateVisible;
    if (m_layerTreeView)
        m_layerTreeView->setVisible(visible);
    m_scheduler->setPageVisible(visible);
}

bool WebViewImpl::requestPointerLock()
{
    return m_client && m_client->requestPointerLock();
}

void WebViewImpl::requestPointerUnlock()
{
    if (m_client)
        m_client->requestPointerUnlock();
}

bool WebViewImpl::isPointerLocked()
{
    return m_client && m_client->isPointerLocked();
}

void WebViewImpl::pointerLockMouseEvent(const WebInputEvent& event)
{
    OwnPtr<UserGestureIndicator> gestureIndicator;
    AtomicString eventType;
    switch (event.type) {
    case WebInputEvent::MouseDown:
        eventType = EventTypeNames::mousedown;
        gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture));
        m_pointerLockGestureToken = gestureIndicator->currentToken();
        break;
    case WebInputEvent::MouseUp:
        eventType = EventTypeNames::mouseup;
        gestureIndicator = adoptPtr(new UserGestureIndicator(m_pointerLockGestureToken.release()));
        break;
    case WebInputEvent::MouseMove:
        eventType = EventTypeNames::mousemove;
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    const WebMouseEvent& mouseEvent = static_cast<const WebMouseEvent&>(event);

    if (page())
        page()->pointerLockController().dispatchLockedMouseEvent(
            PlatformMouseEventBuilder(mainFrameImpl()->frameView(), mouseEvent),
            eventType);
}

void WebViewImpl::forceNextWebGLContextCreationToFail()
{
    WebGLRenderingContext::forceNextWebGLContextCreationToFail();
}

void WebViewImpl::forceNextDrawingBufferCreationToFail()
{
    DrawingBuffer::forceNextDrawingBufferCreationToFail();
}

void WebViewImpl::updatePageOverlays()
{
    if (m_pageColorOverlay)
        m_pageColorOverlay->update();
    if (InspectorOverlay* overlay = inspectorOverlay()) {
        PageOverlay* inspectorPageOverlay = overlay->pageOverlay();
        if (inspectorPageOverlay)
            inspectorPageOverlay->update();
    }
}

void WebViewImpl::attachPaintArtifactCompositor()
{
    if (!m_layerTreeView)
        return;

    // Otherwise, PaintLayerCompositor is expected to supply a root
    // GraphicsLayer via setRootGraphicsLayer.
    ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());

    // TODO(jbroman): This should probably have hookups for overlays, visual
    // viewport, etc.

    m_paintArtifactCompositor.initializeIfNeeded();
    WebLayer* rootLayer = m_paintArtifactCompositor.webLayer();
    ASSERT(rootLayer);
    m_layerTreeView->setRootLayer(*rootLayer);

    // TODO(jbroman): This is cargo-culted from setRootGraphicsLayer. Is it
    // necessary?
    m_layerTreeView->setVisible(page()->isPageVisible());
}

void WebViewImpl::detachPaintArtifactCompositor()
{
    if (!m_layerTreeView)
        return;

    m_layerTreeView->setDeferCommits(true);
    m_layerTreeView->clearRootLayer();
}

float WebViewImpl::deviceScaleFactor() const
{
    // TODO(oshima): Investigate if this should return the ScreenInfo's scale factor rather than
    // page's scale factor, which can be 1 in use-zoom-for-dsf mode.
    if (!page())
        return 1;

    return page()->deviceScaleFactor();
}

} // namespace blink
