Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / WebViewImpl.cpp
index 4c709a0..2c16122 100644 (file)
  */
 
 #include "config.h"
-#include "WebViewImpl.h"
-
-#include "CSSValueKeywords.h"
-#include "CompositionUnderlineVectorBuilder.h"
-#include "ContextFeaturesClientImpl.h"
-#include "DatabaseClientImpl.h"
-#include "FullscreenController.h"
-#include "GeolocationClientProxy.h"
-#include "GraphicsLayerFactoryChromium.h"
-#include "HTMLNames.h"
-#include "LinkHighlight.h"
-#include "LocalFileSystemClient.h"
-#include "MIDIClientProxy.h"
-#include "PopupContainer.h"
-#include "PrerendererClientImpl.h"
-#include "RuntimeEnabledFeatures.h"
-#include "SpeechInputClientImpl.h"
-#include "SpeechRecognitionClientProxy.h"
-#include "StorageQuotaClientImpl.h"
-#include "ValidationMessageClientImpl.h"
-#include "ViewportAnchor.h"
-#include "WebAXObject.h"
-#include "WebActiveWheelFlingParameters.h"
-#include "WebAutofillClient.h"
-#include "WebDevToolsAgentImpl.h"
-#include "WebDevToolsAgentPrivate.h"
-#include "WebFrameImpl.h"
-#include "WebHitTestResult.h"
-#include "WebInputElement.h"
-#include "WebInputEventConversion.h"
-#include "WebMediaPlayerAction.h"
-#include "WebNode.h"
-#include "WebPagePopupImpl.h"
-#include "WebPlugin.h"
-#include "WebPluginAction.h"
-#include "WebPluginContainerImpl.h"
-#include "WebPopupMenuImpl.h"
-#include "WebRange.h"
-#include "WebSettingsImpl.h"
-#include "WebTextInputInfo.h"
-#include "WebViewClient.h"
-#include "WebWindowFeatures.h"
-#include "WorkerGlobalScopeProxyProviderImpl.h"
+#include "web/WebViewImpl.h"
+
+#include "core/CSSValueKeywords.h"
+#include "core/HTMLNames.h"
 #include "core/accessibility/AXObjectCache.h"
 #include "core/clipboard/DataObject.h"
 #include "core/dom/Document.h"
 #include "core/dom/DocumentMarkerController.h"
 #include "core/dom/Text.h"
-#include "core/dom/WheelController.h"
 #include "core/editing/Editor.h"
 #include "core/editing/FrameSelection.h"
+#include "core/editing/HTMLInterchange.h"
 #include "core/editing/InputMethodController.h"
 #include "core/editing/TextIterator.h"
+#include "core/editing/markup.h"
 #include "core/events/KeyboardEvent.h"
 #include "core/events/WheelEvent.h"
+#include "core/frame/EventHandlerRegistry.h"
 #include "core/frame/FrameHost.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/LocalFrame.h"
 #include "core/page/PointerLockController.h"
 #include "core/page/ScopedPageLoadDeferrer.h"
 #include "core/page/TouchDisambiguation.h"
+#include "core/rendering/FastTextAutosizer.h"
 #include "core/rendering/RenderView.h"
 #include "core/rendering/RenderWidget.h"
 #include "core/rendering/TextAutosizer.h"
 #include "core/rendering/compositing/RenderLayerCompositor.h"
 #include "modules/device_orientation/DeviceOrientationInspectorAgent.h"
 #include "modules/encryptedmedia/MediaKeysController.h"
-#include "modules/geolocation/GeolocationController.h"
+#include "modules/filesystem/InspectorFileSystemAgent.h"
 #include "modules/indexeddb/InspectorIndexedDBAgent.h"
-#include "modules/notifications/NotificationController.h"
-#include "painting/ContinuousPainter.h"
+#include "modules/push_messaging/PushController.h"
 #include "platform/ContextMenu.h"
 #include "platform/ContextMenuItem.h"
 #include "platform/Cursor.h"
 #include "platform/PlatformMouseEvent.h"
 #include "platform/PlatformWheelEvent.h"
 #include "platform/PopupMenuClient.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/TraceEvent.h"
 #include "platform/UserGestureIndicator.h"
 #include "platform/exported/WebActiveGestureAnimation.h"
 #include "public/platform/WebImage.h"
 #include "public/platform/WebLayerTreeView.h"
 #include "public/platform/WebVector.h"
+#include "public/web/WebAXObject.h"
+#include "public/web/WebActiveWheelFlingParameters.h"
+#include "public/web/WebAutofillClient.h"
+#include "public/web/WebFrameClient.h"
+#include "public/web/WebHitTestResult.h"
+#include "public/web/WebInputElement.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/WebTextInputInfo.h"
+#include "public/web/WebViewClient.h"
+#include "public/web/WebWindowFeatures.h"
+#include "web/CompositionUnderlineVectorBuilder.h"
+#include "web/ContextFeaturesClientImpl.h"
+#include "web/DatabaseClientImpl.h"
+#include "web/FullscreenController.h"
+#include "web/GraphicsLayerFactoryChromium.h"
+#include "web/LinkHighlight.h"
+#include "web/NavigatorContentUtilsClientImpl.h"
+#include "web/PopupContainer.h"
+#include "web/PrerendererClientImpl.h"
+#include "web/SpeechRecognitionClientProxy.h"
+#include "web/StorageQuotaClientImpl.h"
+#include "web/ValidationMessageClientImpl.h"
+#include "web/ViewportAnchor.h"
+#include "web/WebDevToolsAgentImpl.h"
+#include "web/WebDevToolsAgentPrivate.h"
+#include "web/WebInputEventConversion.h"
+#include "web/WebLocalFrameImpl.h"
+#include "web/WebPagePopupImpl.h"
+#include "web/WebPluginContainerImpl.h"
+#include "web/WebPopupMenuImpl.h"
+#include "web/WebRemoteFrameImpl.h"
+#include "web/WebSettingsImpl.h"
+#include "web/WorkerGlobalScopeProxyProviderImpl.h"
+#include "web/painting/ContinuousPainter.h"
 #include "wtf/CurrentTime.h"
 #include "wtf/RefPtr.h"
 #include "wtf/TemporaryChange.h"
 #include <cmath> // for std::pow
 
 using namespace WebCore;
-using namespace std;
 
 // 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
@@ -237,6 +238,41 @@ static int webInputEventKeyStateToPlatformEventKeyState(int webInputEventKeyStat
     return platformEventKeyState;
 }
 
+namespace {
+
+class UserGestureNotifier {
+public:
+    // If a UserGestureIndicator is created for a user gesture during the
+    // lifetime of a UserGestureNotifier and *userGestureObserved is false,
+    // the object 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);
+    if (m_client)
+        UserGestureIndicator::clearProcessedUserGestureInPast();
+}
+
+UserGestureNotifier::~UserGestureNotifier()
+{
+    if (!*m_userGestureObserved && UserGestureIndicator::processedUserGestureInPast()) {
+        *m_userGestureObserved = true;
+        if (m_client)
+            m_client->firstUserGestureObserved();
+    }
+}
+
+} // namespace
+
 // WebView ----------------------------------------------------------------
 
 WebView* WebView::create(WebViewClient* client)
@@ -281,7 +317,10 @@ void WebView::didExitModalLoop()
 
 void WebViewImpl::setMainFrame(WebFrame* frame)
 {
-    toWebFrameImpl(frame)->initializeAsMainFrame(page());
+    if (frame->isWebLocalFrame())
+        toWebLocalFrameImpl(frame)->initializeAsMainFrame(page());
+    else
+        toWebRemoteFrameImpl(frame)->initializeAsMainFrame(page());
 }
 
 void WebViewImpl::setAutofillClient(WebAutofillClient* autofillClient)
@@ -308,16 +347,10 @@ void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient)
     m_spellCheckClient = spellCheckClient;
 }
 
-void WebViewImpl::setPasswordGeneratorClient(WebPasswordGeneratorClient* client)
-{
-    m_passwordGeneratorClient = client;
-}
-
 WebViewImpl::WebViewImpl(WebViewClient* client)
     : m_client(client)
     , m_autofillClient(0)
     , m_spellCheckClient(0)
-    , m_passwordGeneratorClient(0)
     , m_chromeClientImpl(this)
     , m_contextMenuClientImpl(this)
     , m_dragClientImpl(this)
@@ -331,7 +364,6 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
     , m_zoomLevel(0)
     , m_minimumZoomLevel(zoomFactorToZoomLevel(minTextSizeMultiplier))
     , m_maximumZoomLevel(zoomFactorToZoomLevel(maxTextSizeMultiplier))
-    , m_savedPageScaleFactor(0)
     , m_doubleTapZoomPageScaleFactor(0)
     , m_doubleTapZoomPending(false)
     , m_enableFakePageScaleAnimationForTesting(false)
@@ -346,7 +378,6 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
     , m_imeAcceptEvents(true)
     , m_operationsAllowed(WebDragOperationNone)
     , m_dragOperation(WebDragOperationNone)
-    , m_featureSwitchClient(adoptPtr(new ContextFeaturesClientImpl()))
     , m_isTransparent(false)
     , m_tabsToLinks(false)
     , m_layerTreeView(0)
@@ -356,16 +387,8 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
     , m_graphicsLayerFactory(adoptPtr(new GraphicsLayerFactoryChromium(this)))
     , m_isAcceleratedCompositingActive(false)
     , m_layerTreeViewCommitsDeferred(false)
-    , m_compositorCreationFailed(false)
+    , m_matchesHeuristicsForGpuRasterization(false)
     , m_recreatingGraphicsContext(false)
-#if ENABLE(INPUT_SPEECH)
-    , m_speechInputClient(SpeechInputClientImpl::create(client))
-#endif
-    , m_speechRecognitionClient(SpeechRecognitionClientProxy::create(client ? client->speechRecognizer() : 0))
-    , m_geolocationClientProxy(adoptPtr(new GeolocationClientProxy(client ? client->geolocationClient() : 0)))
-    , m_userMediaClientImpl(this)
-    , m_midiClientProxy(adoptPtr(new MIDIClientProxy(client ? client->webMIDIClient() : 0)))
-    , m_navigatorContentUtilsClient(NavigatorContentUtilsClientImpl::create(this))
     , m_flingModifier(0)
     , m_flingSourceDevice(false)
     , m_fullscreenController(FullscreenController::create(this))
@@ -377,6 +400,7 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
     , m_baseBackgroundColor(Color::white)
     , m_backgroundColorOverride(Color::transparent)
     , m_zoomFactorOverride(0)
+    , m_userGestureObserved(false)
 {
     Page::PageClients pageClients;
     pageClients.chromeClient = &m_chromeClientImpl;
@@ -388,34 +412,25 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
     pageClients.spellCheckerClient = &m_spellCheckerClientImpl;
     pageClients.storageClient = &m_storageClientImpl;
 
-    m_page = adoptPtr(new Page(pageClients));
-    provideUserMediaTo(*m_page, &m_userMediaClientImpl);
+    m_page = adoptPtrWillBeNoop(new Page(pageClients));
     MediaKeysController::provideMediaKeysTo(*m_page, &m_mediaKeysClientImpl);
-    provideMIDITo(*m_page, m_midiClientProxy.get());
-#if ENABLE(INPUT_SPEECH)
-    provideSpeechInputTo(*m_page, m_speechInputClient.get());
-#endif
-    provideSpeechRecognitionTo(*m_page, m_speechRecognitionClient.get());
-    provideNotification(*m_page, notificationPresenterImpl());
-    provideNavigatorContentUtilsTo(*m_page, m_navigatorContentUtilsClient.get());
+    provideSpeechRecognitionTo(*m_page, SpeechRecognitionClientProxy::create(client ? client->speechRecognizer() : 0));
+    provideNavigatorContentUtilsTo(*m_page, NavigatorContentUtilsClientImpl::create(this));
 
-    provideContextFeaturesTo(*m_page, m_featureSwitchClient.get());
-    if (RuntimeEnabledFeatures::deviceOrientationEnabled())
-        DeviceOrientationInspectorAgent::provideTo(*m_page);
-    provideGeolocationTo(*m_page, m_geolocationClientProxy.get());
-    m_geolocationClientProxy->setController(GeolocationController::from(m_page.get()));
+    provideContextFeaturesTo(*m_page, ContextFeaturesClientImpl::create());
+    DeviceOrientationInspectorAgent::provideTo(*m_page);
 
-    provideLocalFileSystemTo(*m_page, LocalFileSystemClient::create());
+    m_page->inspectorController().registerModuleAgent(InspectorFileSystemAgent::create(m_page.get()));
     provideDatabaseClientTo(*m_page, DatabaseClientImpl::create());
     InspectorIndexedDBAgent::provideTo(m_page.get());
     provideStorageQuotaClientTo(*m_page, StorageQuotaClientImpl::create());
-    m_validationMessage = ValidationMessageClientImpl::create(*this);
-    m_page->setValidationMessageClient(m_validationMessage.get());
+    m_page->setValidationMessageClient(ValidationMessageClientImpl::create(*this));
     provideWorkerGlobalScopeProxyProviderTo(*m_page, WorkerGlobalScopeProxyProviderImpl::create());
 
     m_page->makeOrdinary();
 
     if (m_client) {
+        providePushControllerTo(*m_page, m_client->webPushClient());
         setDeviceScaleFactor(m_client->screenInfo().deviceScaleFactor);
         setVisibilityState(m_client->visibilityState(), true);
     }
@@ -428,9 +443,9 @@ WebViewImpl::~WebViewImpl()
     ASSERT(!m_page);
 }
 
-WebFrameImpl* WebViewImpl::mainFrameImpl()
+WebLocalFrameImpl* WebViewImpl::mainFrameImpl()
 {
-    return m_page ? WebFrameImpl::fromFrame(m_page->mainFrame()) : 0;
+    return m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() ? WebLocalFrameImpl::fromFrame(m_page->deprecatedLocalMainFrame()) : 0;
 }
 
 bool WebViewImpl::tabKeyCyclesThroughElements() const
@@ -468,14 +483,16 @@ void WebViewImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEvent& ev
 
     m_lastMouseDownPoint = WebPoint(event.x, event.y);
 
-    if (event.button == WebMouseEvent::ButtonLeft) {
-        IntPoint point(event.x, event.y);
-        point = m_page->mainFrame()->view()->windowToContents(point);
-        HitTestResult result(m_page->mainFrame()->eventHandler().hitTestResultAtPoint(point));
+    // 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() && !m_page->deprecatedLocalMainFrame()->view()->scrollbarAtPoint(point)) {
+        point = m_page->deprecatedLocalMainFrame()->view()->windowToContents(point);
+        HitTestResult result(m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(point));
         Node* hitNode = result.innerNonSharedNode();
 
-        // Take capture on a mouse down on a plugin so we can send it mouse events.
-        if (hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject()) {
+        if (!result.scrollbar() && hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject()) {
             m_mouseCaptureNode = hitNode;
             TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
         }
@@ -525,18 +542,23 @@ void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
 
     // Find the right target frame. See issue 1186900.
     HitTestResult result = hitTestResultForWindowPos(pme.position());
-    LocalFrame* targetFrame;
+    Frame* targetFrame;
     if (result.innerNonSharedNode())
         targetFrame = result.innerNonSharedNode()->document().frame();
     else
         targetFrame = m_page->focusController().focusedOrMainFrame();
 
+    if (!targetFrame->isLocalFrame())
+        return;
+
+    LocalFrame* targetLocalFrame = toLocalFrame(targetFrame);
+
 #if OS(WIN)
-    targetFrame->view()->setCursor(pointerCursor());
+    targetLocalFrame->view()->setCursor(pointerCursor());
 #endif
 
     m_contextMenuAllowed = true;
-    targetFrame->eventHandler().sendContextMenuEvent(pme);
+    targetLocalFrame->eventHandler().sendContextMenuEvent(pme);
     m_contextMenuAllowed = false;
     // Actually showing the context menu is handled by the ContextMenuClient
     // implementation...
@@ -560,9 +582,9 @@ bool WebViewImpl::handleMouseWheel(LocalFrame& mainFrame, const WebMouseWheelEve
     return PageWidgetEventHandler::handleMouseWheel(mainFrame, event);
 }
 
-void WebViewImpl::scrollBy(const WebFloatSize& delta)
+bool WebViewImpl::scrollBy(const WebFloatSize& delta, const WebFloatSize& velocity)
 {
-    if (m_flingSourceDevice == WebGestureEvent::Touchpad) {
+    if (m_flingSourceDevice == WebGestureDeviceTouchpad) {
         WebMouseWheelEvent syntheticWheel;
         const float tickDivisor = WebCore::WheelEvent::TickMultiplier;
 
@@ -577,8 +599,8 @@ void WebViewImpl::scrollBy(const WebFloatSize& delta)
         syntheticWheel.globalY = m_globalPositionOnFlingStart.y;
         syntheticWheel.modifiers = m_flingModifier;
 
-        if (m_page && m_page->mainFrame() && m_page->mainFrame()->view())
-            handleMouseWheel(*m_page->mainFrame(), syntheticWheel);
+        if (m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() && m_page->deprecatedLocalMainFrame()->view())
+            return handleMouseWheel(*m_page->deprecatedLocalMainFrame(), syntheticWheel);
     } else {
         WebGestureEvent syntheticGestureEvent;
 
@@ -590,11 +612,12 @@ void WebViewImpl::scrollBy(const WebFloatSize& delta)
         syntheticGestureEvent.globalX = m_globalPositionOnFlingStart.x;
         syntheticGestureEvent.globalY = m_globalPositionOnFlingStart.y;
         syntheticGestureEvent.modifiers = m_flingModifier;
-        syntheticGestureEvent.sourceDevice = WebGestureEvent::Touchscreen;
+        syntheticGestureEvent.sourceDevice = WebGestureDeviceTouchscreen;
 
-        if (m_page && m_page->mainFrame() && m_page->mainFrame()->view())
-            handleGestureEvent(syntheticGestureEvent);
+        if (m_page && m_page->mainFrame() && m_page->mainFrame()->isLocalFrame() && m_page->deprecatedLocalMainFrame()->view())
+            return handleGestureEvent(syntheticGestureEvent);
     }
+    return false;
 }
 
 bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event)
@@ -613,6 +636,7 @@ bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event)
         m_flingModifier = event.modifiers;
         m_flingSourceDevice = event.sourceDevice;
         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();
         eventSwallowed = true;
@@ -675,7 +699,7 @@ bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event)
             scaledEvent.data.tap.height = event.data.tap.height / pageScaleFactor();
             IntRect boundingBox(scaledEvent.x - scaledEvent.data.tap.width / 2, scaledEvent.y - scaledEvent.data.tap.height / 2, scaledEvent.data.tap.width, scaledEvent.data.tap.height);
             Vector<IntRect> goodTargets;
-            Vector<Node*> highlightNodes;
+            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
@@ -760,6 +784,7 @@ void WebViewImpl::transferActiveWheelFlingAnimation(const WebActiveWheelFlingPar
     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);
     scheduleAnimation();
 }
@@ -849,11 +874,11 @@ void WebViewImpl::setShowScrollBottleneckRects(bool show)
 
 void WebViewImpl::getSelectionRootBounds(WebRect& bounds) const
 {
-    const LocalFrame* frame = focusedWebCoreFrame();
-    if (!frame)
+    const Frame* frame = focusedWebCoreFrame();
+    if (!frame || !frame->isLocalFrame())
         return;
 
-    Element* root = frame->selection().rootEditableElementOrDocumentElement();
+    Element* root = toLocalFrame(frame)->selection().rootEditableElementOrDocumentElement();
     if (!root)
         return;
 
@@ -877,6 +902,14 @@ void WebViewImpl::getSelectionRootBounds(WebRect& bounds) const
     bounds = boundingBox;
 }
 
+void WebViewImpl::acceptLanguagesChanged()
+{
+    if (!page())
+        return;
+
+    page()->acceptLanguagesChanged();
+}
+
 bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
 {
     ASSERT((event.type == WebInputEvent::RawKeyDown)
@@ -907,10 +940,31 @@ bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
         return true;
     }
 
-    RefPtr<LocalFrame> frame = focusedWebCoreFrame();
-    if (!frame)
+    RefPtr<Frame> focusedFrame = focusedWebCoreFrame();
+    if (focusedFrame && focusedFrame->isRemoteFrameTemporary()) {
+        WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(toLocalFrameTemporary(focusedFrame.get()));
+        webFrame->client()->forwardInputEvent(&event);
+        return true;
+    }
+
+    if (!focusedFrame || !focusedFrame->isLocalFrame())
         return false;
 
+    RefPtr<LocalFrame> frame = toLocalFrame(focusedFrame.get());
+
+    PlatformKeyboardEventBuilder evt(event);
+
+    if (frame->eventHandler().keyEvent(evt)) {
+        if (WebInputEvent::RawKeyDown == event.type) {
+            // Suppress the next keypress event unless the focused node is a plug-in node.
+            // (Flash needs these keypress events to handle non-US keyboards.)
+            Element* element = focusedElement();
+            if (!element || !element->renderer() || !element->renderer()->isEmbeddedObject())
+                m_suppressNextKeypressEvent = true;
+        }
+        return true;
+    }
+
 #if !OS(MACOSX)
     const WebInputEvent::Type contextMenuTriggeringEventType =
 #if OS(WIN)
@@ -927,19 +981,6 @@ bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
     }
 #endif // !OS(MACOSX)
 
-    PlatformKeyboardEventBuilder evt(event);
-
-    if (frame->eventHandler().keyEvent(evt)) {
-        if (WebInputEvent::RawKeyDown == event.type) {
-            // Suppress the next keypress event unless the focused node is a plug-in node.
-            // (Flash needs these keypress events to handle non-US keyboards.)
-            Element* element = focusedElement();
-            if (!element || !element->renderer() || !element->renderer()->isEmbeddedObject())
-                m_suppressNextKeypressEvent = true;
-        }
-        return true;
-    }
-
     return keyEventDefault(event);
 }
 
@@ -962,7 +1003,7 @@ bool WebViewImpl::handleCharEvent(const WebKeyboardEvent& event)
     if (m_pagePopup)
         return m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
 
-    LocalFrame* frame = focusedWebCoreFrame();
+    LocalFrame* frame = toLocalFrame(focusedWebCoreFrame());
     if (!frame)
         return suppress;
 
@@ -1030,13 +1071,13 @@ WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int target
     const int absoluteSourceX = source.x + scrollOffset.width();
     if (leftMargin > absoluteSourceX) {
         leftMargin = absoluteSourceX;
-        rightMargin = max(leftMargin, minimumMargin);
+        rightMargin = std::max(leftMargin, minimumMargin);
     }
 
     const int maximumRightMargin = maxSize.width - (source.width + absoluteSourceX);
     if (rightMargin > maximumRightMargin) {
         rightMargin = maximumRightMargin;
-        leftMargin = min(leftMargin, max(rightMargin, minimumMargin));
+        leftMargin = std::min(leftMargin, std::max(rightMargin, minimumMargin));
     }
 
     const int newWidth = source.width + leftMargin + rightMargin;
@@ -1081,9 +1122,9 @@ void WebViewImpl::computeScaleAndScrollForBlockRect(const WebPoint& hitPoint, co
                 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 = min(scale, legibleScale());
+        scale = std::min(scale, legibleScale());
         if (pageScaleFactor() < defaultScaleWhenAlreadyLegible)
-            scale = max(scale, defaultScaleWhenAlreadyLegible);
+            scale = std::max(scale, defaultScaleWhenAlreadyLegible);
         scale = clampPageScaleFactorToLimits(scale);
     }
 
@@ -1104,14 +1145,14 @@ void WebViewImpl::computeScaleAndScrollForBlockRect(const WebPoint& hitPoint, co
     } else {
         // Ensure position we're zooming to (+ padding) isn't off the bottom of
         // the screen.
-        rect.y = max<float>(rect.y, hitPoint.y + padding - screenHeight);
+        rect.y = std::max<float>(rect.y, hitPoint.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 = max<float>(rect.x, hitPoint.x + padding - screenWidth);
+        rect.x = std::max<float>(rect.x, hitPoint.x + padding - screenWidth);
     scroll.x = rect.x;
     scroll.y = rect.y;
 
@@ -1120,28 +1161,28 @@ void WebViewImpl::computeScaleAndScrollForBlockRect(const WebPoint& hitPoint, co
     scroll = clampOffsetAtScale(scroll, scale);
 }
 
-static bool invokesHandCursor(Node* node, bool shiftKey, LocalFrame* frame)
+static bool invokesHandCursor(Node* node, LocalFrame* frame)
 {
     if (!node || !node->renderer())
         return false;
 
     ECursor cursor = node->renderer()->style()->cursor();
     return cursor == CURSOR_POINTER
-        || (cursor == CURSOR_AUTO && frame->eventHandler().useHandCursor(node, node->isLink(), shiftKey));
+        || (cursor == CURSOR_AUTO && frame->eventHandler().useHandCursor(node, node->isLink()));
 }
 
 Node* WebViewImpl::bestTapNode(const PlatformGestureEvent& tapEvent)
 {
-    if (!m_page || !m_page->mainFrame())
+    if (!m_page || !m_page->mainFrame() || !m_page->mainFrame()->isLocalFrame())
         return 0;
 
     Node* bestTouchNode = 0;
 
     IntPoint touchEventLocation(tapEvent.position());
-    m_page->mainFrame()->eventHandler().adjustGesturePosition(tapEvent, touchEventLocation);
+    m_page->deprecatedLocalMainFrame()->eventHandler().adjustGesturePosition(tapEvent, touchEventLocation);
 
-    IntPoint hitTestPoint = m_page->mainFrame()->view()->windowToContents(touchEventLocation);
-    HitTestResult result = m_page->mainFrame()->eventHandler().hitTestResultAtPoint(hitTestPoint, HitTestRequest::TouchEvent | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
+    IntPoint hitTestPoint = m_page->deprecatedLocalMainFrame()->view()->windowToContents(touchEventLocation);
+    HitTestResult result = m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(hitTestPoint, HitTestRequest::TouchEvent | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
     bestTouchNode = result.targetNode();
 
     // We might hit something like an image map that has no renderer on it
@@ -1151,14 +1192,14 @@ Node* WebViewImpl::bestTapNode(const PlatformGestureEvent& tapEvent)
 
     // Check if we're in the subtree of a node with a hand cursor
     // this is the heuristic we use to determine if we show a highlight on tap
-    while (bestTouchNode && !invokesHandCursor(bestTouchNode, false, m_page->mainFrame()))
+    while (bestTouchNode && !invokesHandCursor(bestTouchNode, m_page->deprecatedLocalMainFrame()))
         bestTouchNode = bestTouchNode->parentNode();
 
     if (!bestTouchNode)
         return 0;
 
     // We should pick the largest enclosing node with hand cursor set.
-    while (bestTouchNode->parentNode() && invokesHandCursor(bestTouchNode->parentNode(), false, m_page->mainFrame()))
+    while (bestTouchNode->parentNode() && invokesHandCursor(bestTouchNode->parentNode(), toLocalFrame(m_page->mainFrame())))
         bestTouchNode = bestTouchNode->parentNode();
 
     return bestTouchNode;
@@ -1168,13 +1209,13 @@ void WebViewImpl::enableTapHighlightAtPoint(const PlatformGestureEvent& tapEvent
 {
     Node* touchNode = bestTapNode(tapEvent);
 
-    Vector<Node*> highlightNodes;
+    WillBeHeapVector<RawPtrWillBeMember<Node> > highlightNodes;
     highlightNodes.append(touchNode);
 
     enableTapHighlights(highlightNodes);
 }
 
-void WebViewImpl::enableTapHighlights(Vector<Node*>& highlightNodes)
+void WebViewImpl::enableTapHighlights(WillBeHeapVector<RawPtrWillBeMember<Node> >& highlightNodes)
 {
     if (highlightNodes.isEmpty())
         return;
@@ -1276,12 +1317,6 @@ bool WebViewImpl::zoomToMultipleTargetsRect(const WebRect& rect)
     return true;
 }
 
-void WebViewImpl::numberOfWheelEventHandlersChanged(unsigned numberOfWheelHandlers)
-{
-    if (m_client)
-        m_client->numberOfWheelEventHandlersChanged(numberOfWheelHandlers);
-}
-
 void WebViewImpl::hasTouchEventHandlers(bool hasTouchHandlers)
 {
     if (m_client)
@@ -1307,8 +1342,10 @@ bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
     page()->contextMenuController().clearContextMenu();
 
     m_contextMenuAllowed = true;
-    LocalFrame* focusedFrame = page()->focusController().focusedOrMainFrame();
-    bool handled = focusedFrame->eventHandler().sendContextMenuEventForKey();
+    Frame* focusedFrame = page()->focusController().focusedOrMainFrame();
+    if (!focusedFrame->isLocalFrame())
+        return false;
+    bool handled = toLocalFrame(focusedFrame)->eventHandler().sendContextMenuEventForKey();
     m_contextMenuAllowed = false;
     return handled;
 }
@@ -1316,7 +1353,7 @@ bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
 
 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
 {
-    LocalFrame* frame = focusedWebCoreFrame();
+    LocalFrame* frame = toLocalFrame(focusedWebCoreFrame());
     if (!frame)
         return false;
 
@@ -1429,7 +1466,7 @@ void WebViewImpl::hideSelectPopup()
 
 bool WebViewImpl::bubblingScroll(ScrollDirection scrollDirection, ScrollGranularity scrollGranularity)
 {
-    LocalFrame* frame = focusedWebCoreFrame();
+    LocalFrame* frame = toLocalFrame(focusedWebCoreFrame());
     if (!frame)
         return false;
 
@@ -1442,7 +1479,7 @@ void WebViewImpl::popupOpened(PopupContainer* popupContainer)
     m_selectPopup = popupContainer;
     ASSERT(mainFrameImpl()->frame()->document());
     Document& document = *mainFrameImpl()->frame()->document();
-    WheelController::from(document)->didAddWheelEventHandler(document);
+    page()->frameHost().eventHandlerRegistry().didAddEventHandler(document, EventHandlerRegistry::WheelEvent);
 }
 
 void WebViewImpl::popupClosed(PopupContainer* popupContainer)
@@ -1451,7 +1488,11 @@ void WebViewImpl::popupClosed(PopupContainer* popupContainer)
     m_selectPopup = nullptr;
     ASSERT(mainFrameImpl()->frame()->document());
     Document& document = *mainFrameImpl()->frame()->document();
-    WheelController::from(document)->didRemoveWheelEventHandler(document);
+    // Remove the handler we added in |popupOpened| conditionally, because the
+    // Document may have already removed it, for instance, due to a navigation.
+    EventHandlerRegistry* registry = &document.frameHost()->eventHandlerRegistry();
+    if (registry->eventHandlerTargets(EventHandlerRegistry::WheelEvent)->contains(&document))
+        registry->didRemoveEventHandler(document, EventHandlerRegistry::WheelEvent);
 }
 
 PagePopup* WebViewImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
@@ -1482,7 +1523,7 @@ void WebViewImpl::closePagePopup(PagePopup* popup)
     m_pagePopup = nullptr;
 }
 
-LocalFrame* WebViewImpl::focusedWebCoreFrame() const
+Frame* WebViewImpl::focusedWebCoreFrame() const
 {
     return m_page ? m_page->focusController().focusedOrMainFrame() : 0;
 }
@@ -1501,9 +1542,7 @@ void WebViewImpl::close()
     if (m_page) {
         // Initiate shutdown for the entire frameset.  This will cause a lot of
         // notifications to be sent.
-        if (m_page->mainFrame())
-            m_page->mainFrame()->loader().frameDetached();
-
+        m_page->willBeDestroyed();
         m_page.clear();
     }
 
@@ -1524,7 +1563,7 @@ void WebViewImpl::willStartLiveResize()
         mainFrameImpl()->frameView()->willStartLiveResize();
 
     LocalFrame* frame = mainFrameImpl()->frame();
-    WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
+    WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
     if (pluginContainer)
         pluginContainer->willStartLiveResize();
 }
@@ -1534,6 +1573,14 @@ WebSize WebViewImpl::size()
     return m_size;
 }
 
+void WebViewImpl::resizePinchViewport(const WebSize& newSize)
+{
+    if (!pinchVirtualViewportEnabled())
+        return;
+
+    page()->frameHost().pinchViewport().setSize(newSize);
+}
+
 void WebViewImpl::resize(const WebSize& newSize)
 {
     if (m_shouldAutoResize || m_size == newSize)
@@ -1550,7 +1597,7 @@ void WebViewImpl::resize(const WebSize& newSize)
     m_size = newSize;
 
     bool shouldAnchorAndRescaleViewport = settings()->mainFrameResizesAreOrientationChanges()
-        && oldSize.width && oldContentsWidth && newSize.width != oldSize.width;
+        && oldSize.width && oldContentsWidth && newSize.width != oldSize.width && !m_fullscreenController->isFullscreen();
 
     ViewportAnchor viewportAnchor(&mainFrameImpl()->frame()->eventHandler());
     if (shouldAnchorAndRescaleViewport) {
@@ -1558,17 +1605,32 @@ void WebViewImpl::resize(const WebSize& newSize)
                                  FloatSize(viewportAnchorXCoord, viewportAnchorYCoord));
     }
 
-    updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
-    updateMainFrameLayoutSize();
+    {
+        // Avoids unnecessary invalidations while various bits of state in FastTextAutosizer are updated.
+        FastTextAutosizer::DeferUpdatePageInfo deferUpdatePageInfo(page());
+
+        m_pageScaleConstraintsSet.didChangeViewSize(m_size);
 
-    WebDevToolsAgentPrivate* agentPrivate = devToolsAgentPrivate();
-    if (agentPrivate)
-        agentPrivate->webViewResized(newSize);
-    WebFrameImpl* webFrame = mainFrameImpl();
-    if (webFrame->frameView()) {
-        webFrame->frameView()->resize(m_size);
-        if (page()->settings().pinchVirtualViewportEnabled())
+        updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
+        updateMainFrameLayoutSize();
+
+        // If the virtual viewport pinch mode is enabled, the main frame will be resized
+        // after layout so it can be sized to the contentsSize.
+        if (!pinchVirtualViewportEnabled() && mainFrameImpl()->frameView())
+            mainFrameImpl()->frameView()->resize(m_size);
+
+        if (pinchVirtualViewportEnabled())
             page()->frameHost().pinchViewport().setSize(m_size);
+
+        // When device emulation is enabled, device size values may change - they are
+        // usually set equal to the view size. These values are not considered viewport-dependent
+        // (see MediaQueryExp::isViewportDependent), since they are only viewport-dependent in emulation mode,
+        // and thus will not be invalidated in |FrameView::performPreLayoutTasks|.
+        // Therefore we should force explicit media queries invalidation here.
+        if (page()->inspectorController().deviceEmulationEnabled()) {
+            if (Document* document = mainFrameImpl()->frame()->document())
+                document->mediaQueryAffectingValueChanged();
+        }
     }
 
     if (settings()->viewportEnabled() && !m_fixedLayoutSizeLock) {
@@ -1603,7 +1665,7 @@ void WebViewImpl::willEndLiveResize()
         mainFrameImpl()->frameView()->willEndLiveResize();
 
     LocalFrame* frame = mainFrameImpl()->frame();
-    WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
+    WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
     if (pluginContainer)
         pluginContainer->willEndLiveResize();
 }
@@ -1672,94 +1734,61 @@ void WebViewImpl::layout()
         m_linkHighlights[i]->updateGeometry();
 }
 
-void WebViewImpl::enterForceCompositingMode(bool enter)
+void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
 {
-    if (page()->settings().forceCompositingMode() == enter)
-        return;
+    // 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());
 
-    TRACE_EVENT1("webkit", "WebViewImpl::enterForceCompositingMode", "enter", enter);
-    settingsImpl()->setForceCompositingMode(enter);
-    if (enter) {
-        if (!m_page)
-            return;
-        LocalFrame* mainFrame = m_page->mainFrame();
-        if (!mainFrame)
-            return;
-        mainFrame->view()->updateCompositingLayersAfterStyleChange();
-    }
+    double paintStart = currentTime();
+    PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
+    double paintEnd = currentTime();
+    double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart);
+    blink::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
+    blink::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
 }
 
-void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect)
+#if OS(ANDROID)
+void WebViewImpl::paintCompositedDeprecated(WebCanvas* canvas, const WebRect& rect)
 {
-    ASSERT(m_layerTreeView);
-
-    SkBitmap target;
-    target.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height(), rect.width() * 4);
-    target.allocPixels();
-    m_layerTreeView->compositeAndReadback(target.getPixels(), rect);
-#if (!SK_R32_SHIFT && SK_B32_SHIFT == 16)
-    // The compositor readback always gives back pixels in BGRA order, but for
-    // example Android's Skia uses RGBA ordering so the red and blue channels
-    // need to be swapped.
-    uint8_t* pixels = reinterpret_cast<uint8_t*>(target.getPixels());
-    for (size_t i = 0; i < target.getSize(); i += 4)
-        std::swap(pixels[i], pixels[i + 2]);
-#endif
-    canvas->writePixels(target, rect.x(), rect.y());
-}
+    // Note: This method exists on OS(ANDROID) and will hopefully be
+    //       removed once the link disambiguation feature renders using
+    //       the compositor.
+    ASSERT(isAcceleratedCompositingActive());
 
-void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions option)
-{
-#if !OS(ANDROID)
-    // ReadbackFromCompositorIfAvailable is the only option available on non-Android.
-    // Ideally, Android would always use ReadbackFromCompositorIfAvailable as well.
-    ASSERT(option == ReadbackFromCompositorIfAvailable);
-#endif
+    FrameView* view = page()->deprecatedLocalMainFrame()->view();
+    PaintBehavior oldPaintBehavior = view->paintBehavior();
+    view->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers);
 
-    if (option == ReadbackFromCompositorIfAvailable && isAcceleratedCompositingActive()) {
-        // If a canvas was passed in, we use it to grab a copy of the
-        // freshly-rendered pixels.
-        if (canvas) {
-            // Clip rect to the confines of the rootLayerTexture.
-            IntRect resizeRect(rect);
-            resizeRect.intersect(IntRect(IntPoint(0, 0), m_layerTreeView->deviceViewportSize()));
-            doPixelReadbackToCanvas(canvas, resizeRect);
-        }
-    } else {
-        FrameView* view = page()->mainFrame()->view();
-        PaintBehavior oldPaintBehavior = view->paintBehavior();
-        if (isAcceleratedCompositingActive()) {
-            ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);
-            view->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers);
-        }
+    PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
 
-        double paintStart = currentTime();
-        PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
-        double paintEnd = currentTime();
-        double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart);
-        blink::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
-        blink::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
+    view->setPaintBehavior(oldPaintBehavior);
+}
+#endif
 
-        if (isAcceleratedCompositingActive()) {
-            ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);
-            view->setPaintBehavior(oldPaintBehavior);
-        }
-    }
+void WebViewImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
+{
+    ASSERT(isAcceleratedCompositingActive());
+    m_layerTreeView->compositeAndReadbackAsync(callback);
 }
 
 bool WebViewImpl::isTrackingRepaints() const
 {
     if (!page())
         return false;
-    FrameView* view = page()->mainFrame()->view();
-    return view->isTrackingRepaints();
+    if (!page()->mainFrame()->isLocalFrame())
+        return false;
+    FrameView* view = page()->deprecatedLocalMainFrame()->view();
+    return view->isTrackingPaintInvalidations();
 }
 
 void WebViewImpl::themeChanged()
 {
     if (!page())
         return;
-    FrameView* view = page()->mainFrame()->view();
+    if (!page()->mainFrame()->isLocalFrame())
+        return;
+    FrameView* view = page()->deprecatedLocalMainFrame()->view();
 
     WebRect damagedRect(0, 0, m_size.width, m_size.height);
     view->invalidateRect(damagedRect);
@@ -1787,9 +1816,65 @@ bool WebViewImpl::hasVerticalScrollbar()
 
 const WebInputEvent* WebViewImpl::m_currentInputEvent = 0;
 
+// FIXME: autogenerate this kind of code, and use it throughout Blink rather than
+// the one-offs for subsets of these values.
+static const AtomicString* inputTypeToName(WebInputEvent::Type type)
+{
+    switch (type) {
+    case WebInputEvent::MouseDown:
+        return &EventTypeNames::mousedown;
+    case WebInputEvent::MouseUp:
+        return &EventTypeNames::mouseup;
+    case WebInputEvent::MouseMove:
+        return &EventTypeNames::mousemove;
+    case WebInputEvent::MouseEnter:
+        return &EventTypeNames::mouseenter;
+    case WebInputEvent::MouseLeave:
+        return &EventTypeNames::mouseleave;
+    case WebInputEvent::ContextMenu:
+        return &EventTypeNames::contextmenu;
+    case WebInputEvent::MouseWheel:
+        return &EventTypeNames::mousewheel;
+    case WebInputEvent::KeyDown:
+        return &EventTypeNames::keydown;
+    case WebInputEvent::KeyUp:
+        return &EventTypeNames::keyup;
+    case WebInputEvent::GestureScrollBegin:
+        return &EventTypeNames::gesturescrollstart;
+    case WebInputEvent::GestureScrollEnd:
+        return &EventTypeNames::gesturescrollend;
+    case WebInputEvent::GestureScrollUpdate:
+        return &EventTypeNames::gesturescrollupdate;
+    case WebInputEvent::TouchStart:
+        return &EventTypeNames::touchstart;
+    case WebInputEvent::TouchMove:
+        return &EventTypeNames::touchmove;
+    case WebInputEvent::TouchEnd:
+        return &EventTypeNames::touchend;
+    case WebInputEvent::TouchCancel:
+        return &EventTypeNames::touchcancel;
+    default:
+        return 0;
+    }
+}
+
 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
 {
-    TRACE_EVENT0("input", "WebViewImpl::handleInputEvent");
+    UserGestureNotifier notifier(m_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 && m_autofillClient) {
+        m_userGestureObserved = true;
+        m_autofillClient->firstUserGestureObserved();
+    }
+
+    const AtomicString* inputEventName = inputTypeToName(inputEvent.type);
+    TRACE_EVENT1("input", "WebViewImpl::handleInputEvent", "type", inputEventName ? inputEventName->ascii() : "unknown");
     // If we've started a drag and drop operation, ignore input events until
     // we're done.
     if (m_doingDragAndDrop)
@@ -1812,7 +1897,7 @@ bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
     if (m_mouseCaptureNode && WebInputEvent::isMouseEventType(inputEvent.type)) {
         TRACE_EVENT1("input", "captured mouse event", "type", inputEvent.type);
         // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
-        RefPtr<Node> node = m_mouseCaptureNode;
+        RefPtrWillBeRawPtr<Node> node = m_mouseCaptureNode;
 
         // Not all platforms call mouseCaptureLost() directly.
         if (inputEvent.type == WebInputEvent::MouseUp)
@@ -1867,10 +1952,11 @@ void WebViewImpl::setFocus(bool enable)
     m_page->focusController().setFocused(enable);
     if (enable) {
         m_page->focusController().setActive(true);
-        RefPtr<LocalFrame> focusedFrame = m_page->focusController().focusedFrame();
-        if (focusedFrame) {
-            Element* element = focusedFrame->document()->focusedElement();
-            if (element && focusedFrame->selection().selection().isNone()) {
+        RefPtr<Frame> focusedFrame = m_page->focusController().focusedFrame();
+        if (focusedFrame && focusedFrame->isLocalFrame()) {
+            LocalFrame* localFrame = toLocalFrame(focusedFrame.get());
+            Element* element = localFrame->document()->focusedElement();
+            if (element && localFrame->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.
@@ -1882,7 +1968,7 @@ void WebViewImpl::setFocus(bool enable)
                     // instead. Note that this has the side effect of moving the
                     // caret back to the beginning of the text.
                     Position position(element, 0, Position::PositionIsOffsetInAnchor);
-                    focusedFrame->selection().setSelection(VisibleSelection(position, SEL_DEFAULT_AFFINITY));
+                    localFrame->selection().setSelection(VisibleSelection(position, SEL_DEFAULT_AFFINITY));
                 }
             }
         }
@@ -1894,18 +1980,19 @@ void WebViewImpl::setFocus(bool enable)
         if (!m_page)
             return;
 
-        LocalFrame* frame = m_page->mainFrame();
+        LocalFrame* frame = m_page->mainFrame() && m_page->mainFrame()->isLocalFrame()
+            ? m_page->deprecatedLocalMainFrame() : 0;
         if (!frame)
             return;
 
-        RefPtr<LocalFrame> focusedFrame = m_page->focusController().focusedFrame();
-        if (focusedFrame) {
+        RefPtr<Frame> focusedFrame = m_page->focusController().focusedFrame();
+        if (focusedFrame && focusedFrame->isLocalFrame()) {
             // Finish an ongoing composition to delete the composition node.
-            if (focusedFrame->inputMethodController().hasComposition()) {
+            if (toLocalFrame(focusedFrame.get())->inputMethodController().hasComposition()) {
                 if (m_autofillClient)
                     m_autofillClient->setIgnoreTextChanges(true);
 
-                focusedFrame->inputMethodController().confirmComposition();
+                toLocalFrame(focusedFrame.get())->inputMethodController().confirmComposition();
 
                 if (m_autofillClient)
                     m_autofillClient->setIgnoreTextChanges(false);
@@ -1921,7 +2008,7 @@ bool WebViewImpl::setComposition(
     int selectionStart,
     int selectionEnd)
 {
-    LocalFrame* focused = focusedWebCoreFrame();
+    LocalFrame* focused = toLocalFrame(focusedWebCoreFrame());
     if (!focused || !m_imeAcceptEvents)
         return false;
 
@@ -1939,7 +2026,7 @@ bool WebViewImpl::setComposition(
     // 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.
-    RefPtr<Range> range = inputMethodController.compositionRange();
+    RefPtrWillBeRawPtr<Range> range = inputMethodController.compositionRange();
     if (range) {
         Node* node = range->startContainer();
         if (!node || !node->isContentEditable())
@@ -1987,7 +2074,7 @@ bool WebViewImpl::confirmComposition(const WebString& text)
 
 bool WebViewImpl::confirmComposition(const WebString& text, ConfirmCompositionBehavior selectionBehavior)
 {
-    LocalFrame* focused = focusedWebCoreFrame();
+    LocalFrame* focused = toLocalFrame(focusedWebCoreFrame());
     if (!focused || !m_imeAcceptEvents)
         return false;
 
@@ -1999,11 +2086,11 @@ bool WebViewImpl::confirmComposition(const WebString& text, ConfirmCompositionBe
 
 bool WebViewImpl::compositionRange(size_t* location, size_t* length)
 {
-    LocalFrame* focused = focusedWebCoreFrame();
+    LocalFrame* focused = toLocalFrame(focusedWebCoreFrame());
     if (!focused || !m_imeAcceptEvents)
         return false;
 
-    RefPtr<Range> range = focused->inputMethodController().compositionRange();
+    RefPtrWillBeRawPtr<Range> range = focused->inputMethodController().compositionRange();
     if (!range)
         return false;
 
@@ -2021,7 +2108,7 @@ WebTextInputInfo WebViewImpl::textInputInfo()
 {
     WebTextInputInfo info;
 
-    LocalFrame* focused = focusedWebCoreFrame();
+    LocalFrame* focused = toLocalFrame(focusedWebCoreFrame());
     if (!focused)
         return info;
 
@@ -2039,12 +2126,14 @@ WebTextInputInfo WebViewImpl::textInputInfo()
     if (!focused->editor().canEdit())
         return info;
 
-    info.value = plainText(rangeOfContents(node).get());
+    // 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(rangeOfContents(node).get(), TextIteratorEmitsObjectReplacementCharacter);
 
     if (info.value.isEmpty())
         return info;
 
-    if (RefPtr<Range> range = selection.selection().firstRange()) {
+    if (RefPtrWillBeRawPtr<Range> range = selection.selection().firstRange()) {
         PlainTextRange plainTextRange(PlainTextRange::create(*node, *range.get()));
         if (plainTextRange.isNotNull()) {
             info.selectionStart = plainTextRange.start();
@@ -2052,7 +2141,7 @@ WebTextInputInfo WebViewImpl::textInputInfo()
         }
     }
 
-    if (RefPtr<Range> range = focused->inputMethodController().compositionRange()) {
+    if (RefPtrWillBeRawPtr<Range> range = focused->inputMethodController().compositionRange()) {
         PlainTextRange plainTextRange(PlainTextRange::create(*node, *range.get()));
         if (plainTextRange.isNotNull()) {
             info.compositionStart = plainTextRange.start();
@@ -2147,7 +2236,7 @@ WebString WebViewImpl::inputModeOfFocusedElement()
 
 bool WebViewImpl::selectionBounds(WebRect& anchor, WebRect& focus) const
 {
-    const LocalFrame* frame = focusedWebCoreFrame();
+    const LocalFrame* frame = toLocalFrame(focusedWebCoreFrame());
     if (!frame)
         return false;
     FrameSelection& selection = frame->selection();
@@ -2155,11 +2244,11 @@ bool WebViewImpl::selectionBounds(WebRect& anchor, WebRect& focus) const
     if (selection.isCaret()) {
         anchor = focus = selection.absoluteCaretBounds();
     } else {
-        RefPtr<Range> selectedRange = selection.toNormalizedRange();
+        RefPtrWillBeRawPtr<Range> selectedRange = selection.toNormalizedRange();
         if (!selectedRange)
             return false;
 
-        RefPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
+        RefPtrWillBeRawPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
             selectedRange->startContainer(),
             selectedRange->startOffset(),
             selectedRange->startContainer(),
@@ -2176,6 +2265,17 @@ bool WebViewImpl::selectionBounds(WebRect& anchor, WebRect& focus) const
 
     IntRect scaledAnchor(frame->view()->contentsToWindow(anchor));
     IntRect scaledFocus(frame->view()->contentsToWindow(focus));
+
+    if (pinchVirtualViewportEnabled()) {
+        // FIXME(http://crbug.com/371902) - We shouldn't have to do this
+        // manually, the contentsToWindow methods above should be fixed to do
+        // this.
+        IntPoint pinchViewportOffset =
+            roundedIntPoint(page()->frameHost().pinchViewport().visibleRect().location());
+        scaledAnchor.moveBy(-pinchViewportOffset);
+        scaledFocus.moveBy(-pinchViewportOffset);
+    }
+
     scaledAnchor.scale(pageScaleFactor());
     scaledFocus.scale(pageScaleFactor());
     anchor = scaledAnchor;
@@ -2191,7 +2291,7 @@ InputMethodContext* WebViewImpl::inputMethodContext()
     if (!m_imeAcceptEvents)
         return 0;
 
-    LocalFrame* focusedFrame = focusedWebCoreFrame();
+    LocalFrame* focusedFrame = toLocalFrame(focusedWebCoreFrame());
     if (!focusedFrame)
         return 0;
 
@@ -2204,7 +2304,7 @@ InputMethodContext* WebViewImpl::inputMethodContext()
 
 WebPlugin* WebViewImpl::focusedPluginIfInputMethodSupported(LocalFrame* frame)
 {
-    WebPluginContainerImpl* container = WebFrameImpl::pluginContainerFromNode(frame, WebNode(focusedElement()));
+    WebPluginContainerImpl* container = WebLocalFrameImpl::pluginContainerFromNode(frame, WebNode(focusedElement()));
     if (container && container->supportsInputMethod())
         return container->plugin();
     return 0;
@@ -2230,7 +2330,7 @@ void WebViewImpl::didHideCandidateWindow()
 
 bool WebViewImpl::selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const
 {
-    const LocalFrame* frame = focusedWebCoreFrame();
+    const LocalFrame* frame = toLocalFrame(focusedWebCoreFrame());
     if (!frame)
         return false;
     FrameSelection& selection = frame->selection();
@@ -2243,21 +2343,21 @@ bool WebViewImpl::selectionTextDirection(WebTextDirection& start, WebTextDirecti
 
 bool WebViewImpl::isSelectionAnchorFirst() const
 {
-    if (const LocalFrame* frame = focusedWebCoreFrame())
+    if (const LocalFrame* frame = toLocalFrame(focusedWebCoreFrame()))
         return frame->selection().selection().isBaseFirst();
     return false;
 }
 
 WebVector<WebCompositionUnderline> WebViewImpl::compositionUnderlines() const
 {
-    const LocalFrame* focused = focusedWebCoreFrame();
+    const LocalFrame* focused = toLocalFrame(focusedWebCoreFrame());
     if (!focused)
         return WebVector<WebCompositionUnderline>();
     const Vector<CompositionUnderline>& underlines = focused->inputMethodController().customCompositionUnderlines();
     WebVector<WebCompositionUnderline> results(underlines.size());
     for (size_t index = 0; index < underlines.size(); ++index) {
         CompositionUnderline underline = underlines[index];
-        results[index] = WebCompositionUnderline(underline.startOffset, underline.endOffset, static_cast<WebColor>(underline.color.rgb()), underline.thick);
+        results[index] = WebCompositionUnderline(underline.startOffset, underline.endOffset, static_cast<WebColor>(underline.color.rgb()), underline.thick, static_cast<WebColor>(underline.backgroundColor.rgb()));
     }
     return results;
 }
@@ -2270,13 +2370,15 @@ WebColor WebViewImpl::backgroundColor() const
         return m_baseBackgroundColor;
     if (!m_page->mainFrame())
         return m_baseBackgroundColor;
-    FrameView* view = m_page->mainFrame()->view();
+    if (!m_page->mainFrame()->isLocalFrame())
+        return m_baseBackgroundColor;
+    FrameView* view = m_page->deprecatedLocalMainFrame()->view();
     return view->documentBackgroundColor().rgb();
 }
 
 bool WebViewImpl::caretOrSelectionRange(size_t* location, size_t* length)
 {
-    const LocalFrame* focused = focusedWebCoreFrame();
+    const LocalFrame* focused = toLocalFrame(focusedWebCoreFrame());
     if (!focused)
         return false;
 
@@ -2295,7 +2397,7 @@ void WebViewImpl::setTextDirection(WebTextDirection direction)
     // 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 = focusedWebCoreFrame();
+    const LocalFrame* focused = toLocalFrame(focusedWebCoreFrame());
     if (!focused)
         return;
 
@@ -2377,11 +2479,14 @@ WebString WebViewImpl::pageEncoding() const
     if (!m_page)
         return WebString();
 
+    if (!m_page->mainFrame()->isLocalFrame())
+        return WebString();
+
     // FIXME: Is this check needed?
-    if (!m_page->mainFrame()->document()->loader())
+    if (!m_page->deprecatedLocalMainFrame()->document()->loader())
         return WebString();
 
-    return m_page->mainFrame()->document()->encodingName();
+    return m_page->deprecatedLocalMainFrame()->document()->encodingName();
 }
 
 void WebViewImpl::setPageEncoding(const WebString& encodingName)
@@ -2389,61 +2494,50 @@ void WebViewImpl::setPageEncoding(const WebString& encodingName)
     if (!m_page)
         return;
 
+    if (!m_page->mainFrame()->isLocalFrame())
+        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->mainFrame()->loader().reload(NormalReload, KURL(), newEncodingName);
-}
-
-bool WebViewImpl::dispatchBeforeUnloadEvent()
-{
-    // FIXME: This should really cause a recursive depth-first walk of all
-    // frames in the tree, calling each frame's onbeforeunload.  At the moment,
-    // we're consistent with Safari 3.1, not IE/FF.
-    LocalFrame* frame = m_page->mainFrame();
-    if (!frame)
-        return true;
-
-    return frame->loader().shouldClose();
-}
-
-void WebViewImpl::dispatchUnloadEvent()
-{
-    // Run unload handlers.
-    m_page->mainFrame()->loader().closeURL();
+    m_page->deprecatedLocalMainFrame()->loader().reload(NormalReload, KURL(), newEncodingName);
 }
 
 WebFrame* WebViewImpl::mainFrame()
 {
-    return mainFrameImpl();
+    return WebFrame::fromFrame(m_page ? m_page->mainFrame() : 0);
 }
 
 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();
-    LocalFrame* frame = toWebFrameImpl(relativeToFrame)->frame();
+    Frame* frame = toWebLocalFrameImpl(relativeToFrame)->frame();
     frame = frame->tree().find(name);
-    return WebFrameImpl::fromFrame(frame);
+    if (!frame || !frame->isLocalFrame())
+        return 0;
+    return WebLocalFrameImpl::fromFrame(toLocalFrame(frame));
 }
 
 WebFrame* WebViewImpl::focusedFrame()
 {
-    return WebFrameImpl::fromFrame(focusedWebCoreFrame());
+    return WebLocalFrameImpl::fromFrame(toLocalFrame(focusedWebCoreFrame()));
 }
 
 void WebViewImpl::setFocusedFrame(WebFrame* frame)
 {
     if (!frame) {
         // Clears the focused frame if any.
-        if (LocalFrame* focusedFrame = focusedWebCoreFrame())
-            focusedFrame->selection().setFocused(false);
+        Frame* focusedFrame = focusedWebCoreFrame();
+        if (focusedFrame && focusedFrame->isLocalFrame())
+            toLocalFrame(focusedFrame)->selection().setFocused(false);
         return;
     }
-    LocalFrame* webcoreFrame = toWebFrameImpl(frame)->frame();
+    LocalFrame* webcoreFrame = toWebLocalFrameImpl(frame)->frame();
     webcoreFrame->page()->focusController().setFocusedFrame(webcoreFrame);
 }
 
@@ -2451,23 +2545,27 @@ void WebViewImpl::setInitialFocus(bool reverse)
 {
     if (!m_page)
         return;
-    LocalFrame* frame = page()->focusController().focusedOrMainFrame();
-    if (Document* document = frame->document())
-        document->setFocusedElement(nullptr);
+    Frame* frame = page()->focusController().focusedOrMainFrame();
+    if (frame->isLocalFrame()) {
+        if (Document* document = toLocalFrame(frame)->document())
+            document->setFocusedElement(nullptr);
+    }
     page()->focusController().setInitialFocus(reverse ? FocusTypeBackward : FocusTypeForward);
 }
 
 void WebViewImpl::clearFocusedElement()
 {
-    RefPtr<LocalFrame> frame = focusedWebCoreFrame();
-    if (!frame)
+    RefPtr<Frame> frame = focusedWebCoreFrame();
+    if (!frame || !frame->isLocalFrame())
         return;
 
-    RefPtr<Document> document = frame->document();
+    LocalFrame* localFrame = toLocalFrame(frame.get());
+
+    RefPtrWillBeRawPtr<Document> document = localFrame->document();
     if (!document)
         return;
 
-    RefPtr<Element> oldFocusedElement = document->focusedElement();
+    RefPtrWillBeRawPtr<Element> oldFocusedElement = document->focusedElement();
 
     // Clear the focused node.
     document->setFocusedElement(nullptr);
@@ -2480,18 +2578,13 @@ void WebViewImpl::clearFocusedElement()
     // processing keyboard events even though focus has been moved to the page and
     // keystrokes get eaten as a result.
     if (oldFocusedElement->isContentEditable() || oldFocusedElement->isTextFormControl())
-        frame->selection().clear();
-}
-
-void WebViewImpl::scrollFocusedNodeIntoView()
-{
-    if (Element* element = focusedElement())
-        element->scrollIntoViewIfNeeded(true);
+        localFrame->selection().clear();
 }
 
 void WebViewImpl::scrollFocusedNodeIntoRect(const WebRect& rect)
 {
-    LocalFrame* frame = page()->mainFrame();
+    LocalFrame* frame = page()->mainFrame() && page()->mainFrame()->isLocalFrame()
+        ? page()->deprecatedLocalMainFrame() : 0;
     Element* element = focusedElement();
     if (!frame || !frame->view() || !element)
         return;
@@ -2542,11 +2635,11 @@ void WebViewImpl::computeScaleAndScrollForFocusedNode(Node* focusedNode, float&
         // onscreen.
         int idealLeftPadding = viewWidth * leftBoxRatio;
         int maxLeftPaddingKeepingBoxOnscreen = viewWidth - textboxRectInDocumentCoordinates.width();
-        newScroll.setX(textboxRectInDocumentCoordinates.x() - min<int>(idealLeftPadding, maxLeftPaddingKeepingBoxOnscreen));
+        newScroll.setX(textboxRectInDocumentCoordinates.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(max<int>(textboxRectInDocumentCoordinates.x(), caretInDocumentCoordinates.x() + caretInDocumentCoordinates.width() + caretPadding - viewWidth));
+        newScroll.setX(std::max<int>(textboxRectInDocumentCoordinates.x(), caretInDocumentCoordinates.x() + caretInDocumentCoordinates.width() + caretPadding - viewWidth));
     }
     if (textboxRectInDocumentCoordinates.height() <= viewHeight) {
         // Field is shorter than screen. Vertically center it.
@@ -2554,7 +2647,7 @@ void WebViewImpl::computeScaleAndScrollForFocusedNode(Node* focusedNode, float&
     } 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(max<int>(textboxRectInDocumentCoordinates.y(), caretInDocumentCoordinates.y() + caretInDocumentCoordinates.height() + caretPadding - viewHeight));
+        newScroll.setY(std::max<int>(textboxRectInDocumentCoordinates.y(), caretInDocumentCoordinates.y() + caretInDocumentCoordinates.height() + caretPadding - viewHeight));
     }
 
     needAnimation = false;
@@ -2591,7 +2684,7 @@ double WebViewImpl::setZoomLevel(double zoomLevel)
         m_zoomLevel = zoomLevel;
 
     LocalFrame* frame = mainFrameImpl()->frame();
-    WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
+    WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
     if (pluginContainer)
         pluginContainer->plugin()->setZoomLevel(m_zoomLevel, false);
     else {
@@ -2618,7 +2711,7 @@ float WebViewImpl::textZoomFactor()
 float WebViewImpl::setTextZoomFactor(float textZoomFactor)
 {
     LocalFrame* frame = mainFrameImpl()->frame();
-    if (WebFrameImpl::pluginContainerFromFrame(frame))
+    if (WebLocalFrameImpl::pluginContainerFromFrame(frame))
         return 1;
 
     frame->setTextZoomFactor(textZoomFactor);
@@ -2631,7 +2724,7 @@ void WebViewImpl::fullFramePluginZoomLevelChanged(double zoomLevel)
     if (zoomLevel == m_zoomLevel)
         return;
 
-    m_zoomLevel = max(min(zoomLevel, m_maximumZoomLevel), m_minimumZoomLevel);
+    m_zoomLevel = std::max(std::min(zoomLevel, m_maximumZoomLevel), m_minimumZoomLevel);
     m_client->zoomLevelChanged();
 }
 
@@ -2651,7 +2744,10 @@ float WebViewImpl::pageScaleFactor() const
     if (!page())
         return 1;
 
-    return page()->pageScaleFactor();
+    if (!pinchVirtualViewportEnabled())
+        return page()->pageScaleFactor();
+
+    return page()->frameHost().pinchViewport().scale();
 }
 
 float WebViewImpl::clampPageScaleFactorToLimits(float scaleFactor) const
@@ -2668,27 +2764,75 @@ IntPoint WebViewImpl::clampOffsetAtScale(const IntPoint& offset, float scale)
     return view->clampOffsetAtScale(offset, scale);
 }
 
-void WebViewImpl::setPageScaleFactor(float scaleFactor, const WebPoint& origin)
+bool WebViewImpl::pinchVirtualViewportEnabled() const
 {
-    if (!page())
+    ASSERT(page());
+    return page()->settings().pinchVirtualViewportEnabled();
+}
+
+void WebViewImpl::setPinchViewportOffset(const WebFloatPoint& offset)
+{
+    ASSERT(page());
+
+    if (!pinchVirtualViewportEnabled())
         return;
 
-    IntPoint newScrollOffset = origin;
+    page()->frameHost().pinchViewport().setLocation(offset);
+}
+
+WebFloatPoint WebViewImpl::pinchViewportOffset() const
+{
+    ASSERT(page());
+
+    if (!pinchVirtualViewportEnabled())
+        return WebFloatPoint();
+
+    return page()->frameHost().pinchViewport().visibleRect().location();
+}
+
+void WebViewImpl::setPageScaleFactor(float scaleFactor)
+{
+    ASSERT(page());
+
     scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
-    newScrollOffset = clampOffsetAtScale(newScrollOffset, scaleFactor);
+    if (scaleFactor == pageScaleFactor())
+        return;
+
+    // TODO(bokan): Old-style pinch path. Remove when we're migrated to
+    // virtual viewport pinch.
+    if (!pinchVirtualViewportEnabled()) {
+        IntPoint scrollOffset(mainFrame()->scrollOffset().width, mainFrame()->scrollOffset().height);
+        setPageScaleFactor(scaleFactor, scrollOffset);
+        return;
+    }
+
+    page()->frameHost().pinchViewport().setScale(scaleFactor);
+    deviceOrPageScaleFactorChanged();
+}
 
-    page()->setPageScaleFactor(scaleFactor, newScrollOffset);
+void WebViewImpl::setMainFrameScrollOffset(const WebPoint& origin)
+{
+    updateMainFrameScrollPosition(origin, false);
 }
 
-void WebViewImpl::setPageScaleFactorPreservingScrollOffset(float scaleFactor)
+void WebViewImpl::setPageScaleFactor(float scaleFactor, const WebPoint& origin)
 {
-    if (clampPageScaleFactorToLimits(scaleFactor) == pageScaleFactor())
+    if (!page())
         return;
 
-    IntPoint scrollOffset(mainFrame()->scrollOffset().width, mainFrame()->scrollOffset().height);
-    setPageScaleFactor(scaleFactor, scrollOffset);
+    IntPoint newScrollOffset = origin;
+    scaleFactor = clampPageScaleFactorToLimits(scaleFactor);
+    newScrollOffset = clampOffsetAtScale(newScrollOffset, scaleFactor);
+
+    if (pinchVirtualViewportEnabled())
+        setPageScaleFactor(scaleFactor);
+        // Note, we don't set the offset in the new path. This method is going
+        // away for the new pinch model so that's ok.
+    else
+        page()->setPageScaleFactor(scaleFactor, newScrollOffset);
 }
 
+
 float WebViewImpl::deviceScaleFactor() const
 {
     if (!page())
@@ -2770,26 +2914,29 @@ void WebViewImpl::setIgnoreViewportTagScaleLimits(bool ignore)
 
 void WebViewImpl::refreshPageScaleFactorAfterLayout()
 {
-    if (!mainFrame() || !page() || !page()->mainFrame() || !page()->mainFrame()->view())
+    if (!mainFrame() || !page() || !page()->mainFrame() || !page()->mainFrame()->isLocalFrame() || !page()->deprecatedLocalMainFrame()->view())
         return;
-    FrameView* view = page()->mainFrame()->view();
+    FrameView* view = page()->deprecatedLocalMainFrame()->view();
 
     updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
     m_pageScaleConstraintsSet.computeFinalConstraints();
 
-    if (settings()->viewportEnabled() && !m_fixedLayoutSizeLock) {
+    if (settings()->shrinksViewportContentToFit() && !m_fixedLayoutSizeLock) {
         int verticalScrollbarWidth = 0;
         if (view->verticalScrollbar() && !view->verticalScrollbar()->isOverlayScrollbar())
             verticalScrollbarWidth = view->verticalScrollbar()->width();
-        m_pageScaleConstraintsSet.adjustFinalConstraintsToContentsSize(m_size, contentsSize(), verticalScrollbarWidth);
+        m_pageScaleConstraintsSet.adjustFinalConstraintsToContentsSize(contentsSize(), verticalScrollbarWidth);
     }
 
+    if (pinchVirtualViewportEnabled())
+        mainFrameImpl()->frameView()->resize(m_pageScaleConstraintsSet.mainFrameSize(contentsSize()));
+
     float newPageScaleFactor = pageScaleFactor();
     if (m_pageScaleConstraintsSet.needsReset() && m_pageScaleConstraintsSet.finalConstraints().initialScale != -1) {
         newPageScaleFactor = m_pageScaleConstraintsSet.finalConstraints().initialScale;
         m_pageScaleConstraintsSet.setNeedsReset(false);
     }
-    setPageScaleFactorPreservingScrollOffset(newPageScaleFactor);
+    setPageScaleFactor(newPageScaleFactor);
 
     updateLayerTreeViewport();
 
@@ -2801,13 +2948,33 @@ void WebViewImpl::refreshPageScaleFactorAfterLayout()
 
 void WebViewImpl::updatePageDefinedViewportConstraints(const ViewportDescription& description)
 {
-    if (!settings()->viewportEnabled() || !page() || (!m_size.width && !m_size.height))
+    if (!settings()->viewportEnabled() || !page() || (!m_size.width && !m_size.height) || !page()->mainFrame()->isLocalFrame())
         return;
 
+    Document* document = page()->deprecatedLocalMainFrame()->document();
+
+    if (settingsImpl()->useExpandedHeuristicsForGpuRasterization()) {
+        m_matchesHeuristicsForGpuRasterization = description.maxWidth == Length(DeviceWidth)
+            && description.minZoom == 1.0
+            && description.minZoomIsExplicit;
+    } else {
+        m_matchesHeuristicsForGpuRasterization = description.maxWidth == Length(DeviceWidth)
+            && description.minZoom == 1.0
+            && description.minZoomIsExplicit
+            && description.zoom == 1.0
+            && description.zoomIsExplicit
+            && description.userZoom
+            && description.userZoomIsExplicit;
+    }
+    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) {
-        if (adjustedDescription.maxWidth.type() == ExtendToZoom)
-            adjustedDescription.maxWidth = Length(); // auto
         const int legacyWidthSnappingMagicNumber = 320;
         if (adjustedDescription.maxWidth.isFixed() && adjustedDescription.maxWidth.value() <= legacyWidthSnappingMagicNumber)
             adjustedDescription.maxWidth = Length(DeviceWidth);
@@ -2816,17 +2983,19 @@ void WebViewImpl::updatePageDefinedViewportConstraints(const ViewportDescription
         adjustedDescription.minWidth = adjustedDescription.maxWidth;
         adjustedDescription.minHeight = adjustedDescription.maxHeight;
     }
+
     float oldInitialScale = m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale;
-    m_pageScaleConstraintsSet.updatePageDefinedConstraints(adjustedDescription, m_size);
+    m_pageScaleConstraintsSet.updatePageDefinedConstraints(adjustedDescription, defaultMinWidth);
 
     if (settingsImpl()->clobberUserAgentInitialScaleQuirk()
         && m_pageScaleConstraintsSet.userAgentConstraints().initialScale != -1
         && m_pageScaleConstraintsSet.userAgentConstraints().initialScale * deviceScaleFactor() <= 1) {
         if (description.maxWidth == Length(DeviceWidth)
-            || (description.maxWidth.type() == ExtendToZoom && m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale == 1.0f))
+            || (description.maxWidth.type() == Auto && m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale == 1.0f))
             setInitialPageScaleOverride(-1);
     }
-    m_pageScaleConstraintsSet.adjustForAndroidWebViewQuirks(adjustedDescription, m_size, page()->settings().layoutFallbackWidth(), deviceScaleFactor(), settingsImpl()->supportDeprecatedTargetDensityDPI(), page()->settings().wideViewportQuirkEnabled(), page()->settings().useWideViewport(), page()->settings().loadWithOverviewMode(), settingsImpl()->viewportMetaNonUserScalableQuirk());
+
+    m_pageScaleConstraintsSet.adjustForAndroidWebViewQuirks(adjustedDescription, defaultMinWidth.intValue(), deviceScaleFactor(), settingsImpl()->supportDeprecatedTargetDensityDPI(), page()->settings().wideViewportQuirkEnabled(), page()->settings().useWideViewport(), page()->settings().loadWithOverviewMode(), settingsImpl()->viewportMetaNonUserScalableQuirk());
     float newInitialScale = m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale;
     if (oldInitialScale != newInitialScale && newInitialScale != -1) {
         m_pageScaleConstraintsSet.setNeedsReset(true);
@@ -2835,11 +3004,16 @@ void WebViewImpl::updatePageDefinedViewportConstraints(const ViewportDescription
     }
 
     updateMainFrameLayoutSize();
+
+    if (LocalFrame* frame = page()->deprecatedLocalMainFrame()) {
+        if (FastTextAutosizer* textAutosizer = frame->document()->fastTextAutosizer())
+            textAutosizer->updatePageInfoInAllFrames();
+    }
 }
 
 void WebViewImpl::updateMainFrameLayoutSize()
 {
-    if (m_fixedLayoutSizeLock || !mainFrameImpl())
+    if (m_fixedLayoutSizeLock || m_shouldAutoResize || !mainFrameImpl())
         return;
 
     RefPtr<FrameView> view = mainFrameImpl()->frameView();
@@ -2853,18 +3027,22 @@ void WebViewImpl::updateMainFrameLayoutSize()
 
         bool textAutosizingEnabled = page()->settings().textAutosizingEnabled();
         if (textAutosizingEnabled && layoutSize.width != view->layoutSize().width()) {
-            TextAutosizer* textAutosizer = page()->mainFrame()->document()->textAutosizer();
-            if (textAutosizer)
+            if (TextAutosizer* textAutosizer = page()->deprecatedLocalMainFrame()->document()->textAutosizer())
                 textAutosizer->recalculateMultipliers();
         }
     }
 
+    if (page()->settings().forceZeroLayoutHeight())
+        layoutSize.height = 0;
+
     view->setLayoutSize(layoutSize);
 }
 
 IntSize WebViewImpl::contentsSize() const
 {
-    RenderView* root = page()->mainFrame()->contentRenderer();
+    if (!page()->mainFrame()->isLocalFrame())
+        return IntSize();
+    RenderView* root = page()->deprecatedLocalMainFrame()->contentRenderer();
     if (!root)
         return IntSize();
     return root->documentRect().size();
@@ -2872,7 +3050,7 @@ IntSize WebViewImpl::contentsSize() const
 
 WebSize WebViewImpl::contentsPreferredMinimumSize()
 {
-    Document* document = m_page->mainFrame()->document();
+    Document* document = m_page->mainFrame()->isLocalFrame() ? m_page->deprecatedLocalMainFrame()->document() : 0;
     if (!document || !document->renderView() || !document->documentElement())
         return WebSize();
 
@@ -2893,48 +3071,33 @@ float WebViewImpl::maximumPageScaleFactor() const
     return m_pageScaleConstraintsSet.finalConstraints().maximumScale;
 }
 
-void WebViewImpl::saveScrollAndScaleState()
+void WebViewImpl::resetScrollAndScaleState()
 {
-    m_savedPageScaleFactor = pageScaleFactor();
-    m_savedScrollOffset = mainFrame()->scrollOffset();
-}
+    // TODO: This is done by the pinchViewport().reset() call below and can be removed when
+    // the new pinch path is the only one.
+    setPageScaleFactor(1);
+    updateMainFrameScrollPosition(IntPoint(), true);
+    page()->frameHost().pinchViewport().reset();
 
-void WebViewImpl::restoreScrollAndScaleState()
-{
-    if (!m_savedPageScaleFactor)
+    if (!page()->mainFrame()->isLocalFrame())
         return;
 
-    startPageScaleAnimation(IntPoint(m_savedScrollOffset), false, m_savedPageScaleFactor, scrollAndScaleAnimationDurationInSeconds);
-    resetSavedScrollAndScaleState();
-}
-
-void WebViewImpl::resetSavedScrollAndScaleState()
-{
-    m_savedPageScaleFactor = 0;
-    m_savedScrollOffset = IntSize();
-}
-
-void WebViewImpl::resetScrollAndScaleState()
-{
-    page()->setPageScaleFactor(1, IntPoint());
-
     // Clear out the values for the current history item. This will prevent the history item from clobbering the
     // value determined during page scale initialization, which may be less than 1.
-    page()->mainFrame()->loader().clearScrollPositionAndViewState();
+    page()->deprecatedLocalMainFrame()->loader().clearScrollPositionAndViewState();
     m_pageScaleConstraintsSet.setNeedsReset(true);
 
     // Clobber saved scales and scroll offsets.
-    if (FrameView* view = page()->mainFrame()->document()->view())
+    if (FrameView* view = page()->deprecatedLocalMainFrame()->document()->view())
         view->cacheCurrentScrollPosition();
-    resetSavedScrollAndScaleState();
 }
 
 void WebViewImpl::setFixedLayoutSize(const WebSize& layoutSize)
 {
-    if (!page())
+    if (!page() || !page()->mainFrame()->isLocalFrame())
         return;
 
-    LocalFrame* frame = page()->mainFrame();
+    LocalFrame* frame = page()->deprecatedLocalMainFrame();
     if (!frame)
         return;
 
@@ -2954,12 +3117,11 @@ void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
                                            const WebPoint& location)
 {
     HitTestResult result = hitTestResultForWindowPos(location);
-    RefPtr<Node> node = result.innerNonSharedNode();
+    RefPtrWillBeRawPtr<Node> node = result.innerNonSharedNode();
     if (!isHTMLVideoElement(*node) && !isHTMLAudioElement(*node))
         return;
 
-    RefPtr<HTMLMediaElement> mediaElement =
-        static_pointer_cast<HTMLMediaElement>(node);
+    RefPtrWillBeRawPtr<HTMLMediaElement> mediaElement = static_pointer_cast<HTMLMediaElement>(node);
     switch (action.type) {
     case WebMediaPlayerAction::Play:
         if (action.enable)
@@ -2985,7 +3147,7 @@ void WebViewImpl::performPluginAction(const WebPluginAction& action,
                                       const WebPoint& location)
 {
     HitTestResult result = hitTestResultForWindowPos(location);
-    RefPtr<Node> node = result.innerNonSharedNode();
+    RefPtrWillBeRawPtr<Node> node = result.innerNonSharedNode();
     if (!isHTMLObjectElement(*node) && !isHTMLEmbedElement(*node))
         return;
 
@@ -3022,7 +3184,7 @@ void WebViewImpl::copyImageAt(const WebPoint& point)
 
     HitTestResult result = hitTestResultForWindowPos(point);
 
-    if (result.absoluteImageURL().isEmpty()) {
+    if (result.absoluteImageURLIncludingCanvasDataURL().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
@@ -3033,7 +3195,22 @@ void WebViewImpl::copyImageAt(const WebPoint& point)
         return;
     }
 
-    m_page->mainFrame()->editor().copyImage(result);
+    m_page->deprecatedLocalMainFrame()->editor().copyImage(result);
+}
+
+void WebViewImpl::saveImageAt(const WebPoint& point)
+{
+    if (!m_page)
+        return;
+
+    KURL url = hitTestResultForWindowPos(point).absoluteImageURLIncludingCanvasDataURL();
+
+    if (url.isEmpty())
+        return;
+
+    ResourceRequest request(url);
+    m_page->deprecatedLocalMainFrame()->loader().client()->loadURLExternally(
+        request, NavigationPolicyDownloadTo, WebString());
 }
 
 void WebViewImpl::dragSourceEndedAt(
@@ -3045,17 +3222,10 @@ void WebViewImpl::dragSourceEndedAt(
                            screenPoint,
                            LeftButton, PlatformEvent::MouseMoved, 0, false, false, false,
                            false, 0);
-    m_page->mainFrame()->eventHandler().dragSourceEndedAt(pme,
+    m_page->deprecatedLocalMainFrame()->eventHandler().dragSourceEndedAt(pme,
         static_cast<DragOperation>(operation));
 }
 
-void WebViewImpl::dragSourceMovedTo(
-    const WebPoint& clientPoint,
-    const WebPoint& screenPoint,
-    WebDragOperation operation)
-{
-}
-
 void WebViewImpl::dragSourceSystemDragEnded()
 {
     // It's possible for us to get this callback while not doing a drag if
@@ -3116,6 +3286,8 @@ void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
 {
     ASSERT(m_currentDragData);
 
+    UserGestureNotifier notifier(m_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
@@ -3145,8 +3317,10 @@ void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
 void WebViewImpl::spellingMarkers(WebVector<uint32_t>* markers)
 {
     Vector<uint32_t> result;
-    for (LocalFrame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
-        const Vector<DocumentMarker*>& documentMarkers = frame->document()->markers().markers();
+    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        if (!frame->isLocalFrame())
+            continue;
+        const WillBeHeapVector<DocumentMarker*>& documentMarkers = toLocalFrame(frame)->document()->markers().markers();
         for (size_t i = 0; i < documentMarkers.size(); ++i)
             result.append(documentMarkers[i]->hash());
     }
@@ -3224,18 +3398,19 @@ void WebViewImpl::inspectElementAt(const WebPoint& point)
     if (point.x == -1 || point.y == -1) {
         m_page->inspectorController().inspect(0);
     } else {
-        HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnorePointerEventsNone;
+        HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::AllowChildFrameContent;
         HitTestRequest request(hitType);
 
-        FrameView* frameView = m_page->mainFrame()->view();
-        IntPoint transformedPoint(point);
-        transformedPoint = transformedPoint - frameView->inputEventsOffsetForEmulation();
-        transformedPoint.scale(1 / frameView->inputEventsScaleFactor(), 1 / frameView->inputEventsScaleFactor());
-        HitTestResult result(m_page->mainFrame()->view()->windowToContents(transformedPoint));
-        m_page->mainFrame()->contentRenderer()->hitTest(request, result);
+        WebMouseEvent dummyEvent;
+        dummyEvent.type = WebInputEvent::MouseDown;
+        dummyEvent.x = point.x;
+        dummyEvent.y = point.y;
+        IntPoint transformedPoint = PlatformMouseEventBuilder(m_page->deprecatedLocalMainFrame()->view(), dummyEvent).position();
+        HitTestResult result(m_page->deprecatedLocalMainFrame()->view()->windowToContents(transformedPoint));
+        m_page->deprecatedLocalMainFrame()->contentRenderer()->hitTest(request, result);
         Node* node = result.innerNode();
-        if (!node && m_page->mainFrame()->document())
-            node = m_page->mainFrame()->document()->documentElement();
+        if (!node && m_page->deprecatedLocalMainFrame()->document())
+            node = m_page->deprecatedLocalMainFrame()->document()->documentElement();
         m_page->inspectorController().inspect(node);
     }
 }
@@ -3267,6 +3442,8 @@ void WebViewImpl::setInspectorSetting(const WebString& key,
 
 void WebViewImpl::setCompositorDeviceScaleFactorOverride(float deviceScaleFactor)
 {
+    if (m_compositorDeviceScaleFactorOverride == deviceScaleFactor)
+        return;
     m_compositorDeviceScaleFactorOverride = deviceScaleFactor;
     if (page() && m_layerTreeView)
         updateLayerTreeDeviceScaleFactor();
@@ -3274,6 +3451,8 @@ void WebViewImpl::setCompositorDeviceScaleFactorOverride(float deviceScaleFactor
 
 void WebViewImpl::setRootLayerTransform(const WebSize& rootLayerOffset, float rootLayerScale)
 {
+    if (m_rootLayerScale == rootLayerScale && m_rootLayerOffset == rootLayerOffset)
+        return;
     m_rootLayerScale = rootLayerScale;
     m_rootLayerOffset = rootLayerOffset;
     if (mainFrameImpl())
@@ -3293,7 +3472,7 @@ WebAXObject WebViewImpl::accessibilityObject()
 
     Document* document = mainFrameImpl()->frame()->document();
     return WebAXObject(
-        document->axObjectCache()->getOrCreate(document->renderer()));
+        document->axObjectCache()->getOrCreate(document->renderView()));
 }
 
 void WebViewImpl::performCustomContextMenuAction(unsigned action)
@@ -3316,17 +3495,53 @@ void WebViewImpl::showContextMenu()
 
     page()->contextMenuController().clearContextMenu();
     m_contextMenuAllowed = true;
-    if (LocalFrame* focusedFrame = page()->focusController().focusedOrMainFrame())
+    if (LocalFrame* focusedFrame = toLocalFrame(page()->focusController().focusedOrMainFrame()))
         focusedFrame->eventHandler().sendContextMenuEventForKey();
     m_contextMenuAllowed = false;
 }
 
+// FIXME: This should be removed when the chromium side patch lands
+// http://codereview.chromium.org/260623004
 WebString WebViewImpl::getSmartClipData(WebRect rect)
 {
-    LocalFrame* frame = focusedWebCoreFrame();
+    return WebString();
+}
+
+void WebViewImpl::getSmartClipData(WebRect rect, WebString& clipText, WebRect& clipRect)
+{
+    LocalFrame* frame = toLocalFrame(focusedWebCoreFrame());
     if (!frame)
-        return WebString();
-    return WebCore::SmartClip(frame).dataForRect(rect).toString();
+        return;
+    SmartClipData clipData = WebCore::SmartClip(frame).dataForRect(rect);
+    clipText = clipData.clipData();
+    clipRect = clipData.rect();
+}
+
+void WebViewImpl::extractSmartClipData(WebRect rect, WebString& clipText, WebString& clipHtml, WebRect& clipRect)
+{
+    LocalFrame* localFrame = toLocalFrame(focusedWebCoreFrame());
+    if (!localFrame)
+        return;
+    SmartClipData clipData = WebCore::SmartClip(localFrame).dataForRect(rect);
+    clipText = clipData.clipData();
+    clipRect = clipData.rect();
+
+    WebLocalFrameImpl* frame = mainFrameImpl();
+    if (!frame)
+        return;
+    WebPoint startPoint(rect.x, rect.y);
+    WebPoint endPoint(rect.x + rect.width, rect.y + rect.height);
+    VisiblePosition startVisiblePosition = frame->visiblePositionForWindowPoint(startPoint);
+    VisiblePosition endVisiblePosition = frame->visiblePositionForWindowPoint(endPoint);
+
+    Position startPosition = startVisiblePosition.deepEquivalent();
+    Position endPosition = endVisiblePosition.deepEquivalent();
+
+    RefPtr<Range> range = Range::create(*startPosition.document(), startPosition, endPosition);
+    if (!range)
+        return;
+
+    clipHtml = createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
 }
 
 void WebViewImpl::hidePopups()
@@ -3339,9 +3554,10 @@ void WebViewImpl::hidePopups()
 void WebViewImpl::setIsTransparent(bool isTransparent)
 {
     // Set any existing frames to be transparent.
-    LocalFrame* frame = m_page->mainFrame();
+    Frame* frame = m_page->mainFrame();
     while (frame) {
-        frame->view()->setTransparent(isTransparent);
+        if (frame->isLocalFrame())
+            toLocalFrame(frame)->view()->setTransparent(isTransparent);
         frame = frame->tree().traverseNext();
     }
 
@@ -3363,8 +3579,8 @@ void WebViewImpl::setBaseBackgroundColor(WebColor color)
 
     m_baseBackgroundColor = color;
 
-    if (m_page->mainFrame())
-        m_page->mainFrame()->view()->setBaseBackgroundColor(color);
+    if (m_page->mainFrame() && m_page->mainFrame()->isLocalFrame())
+        m_page->deprecatedLocalMainFrame()->view()->setBaseBackgroundColor(color);
 
     updateLayerTreeBackgroundColor();
 }
@@ -3390,6 +3606,11 @@ void WebViewImpl::setWindowFeatures(const WebWindowFeatures& features)
     m_page->chrome().setWindowFeatures(features);
 }
 
+void WebViewImpl::setOpenedByDOM()
+{
+    m_page->setOpenedByDOM();
+}
+
 void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor,
                                      unsigned activeForegroundColor,
                                      unsigned inactiveBackgroundColor,
@@ -3422,18 +3643,21 @@ void WebViewImpl::didCommitLoad(bool isNewNavigation, bool isNavigationWithinPag
     // Make sure link highlight from previous page is cleared.
     m_linkHighlights.clear();
     endActiveFlingAnimation();
-    resetSavedScrollAndScaleState();
+    m_userGestureObserved = false;
 }
 
-void WebViewImpl::willInsertBody(WebFrameImpl* webframe)
+void WebViewImpl::willInsertBody(WebLocalFrameImpl* webframe)
 {
     if (webframe != mainFrameImpl())
         return;
 
-    // If we get to the <body> tag and we have no pending stylesheet loads, we
+    if (!m_page->mainFrame()->isLocalFrame())
+        return;
+
+    // If we get to the <body> tag and we have no pending stylesheet and import load, we
     // can be fairly confident we'll have something sensible to paint soon and
     // can turn off deferred commits.
-    if (m_page->mainFrame()->document()->haveStylesheetsLoaded())
+    if (m_page->deprecatedLocalMainFrame()->document()->isRenderingReady())
         resumeTreeViewCommits();
 }
 
@@ -3446,7 +3670,7 @@ void WebViewImpl::resumeTreeViewCommits()
     }
 }
 
-void WebViewImpl::layoutUpdated(WebFrameImpl* webframe)
+void WebViewImpl::layoutUpdated(WebLocalFrameImpl* webframe)
 {
     if (!m_client || webframe != mainFrameImpl())
         return;
@@ -3459,6 +3683,10 @@ void WebViewImpl::layoutUpdated(WebFrameImpl* webframe)
         WebSize frameSize = mainFrameImpl()->frame()->view()->frameRect().size();
         if (frameSize != m_size) {
             m_size = frameSize;
+
+            page()->frameHost().pinchViewport().setSize(m_size);
+            m_pageScaleConstraintsSet.didChangeViewSize(m_size);
+
             m_client->didAutoResize(m_size);
             sendResizeEventAndRepaint();
         }
@@ -3477,8 +3705,6 @@ void WebViewImpl::didChangeContentsSize()
 
 void WebViewImpl::deviceOrPageScaleFactorChanged()
 {
-    if (pageScaleFactor() && pageScaleFactor() != 1)
-        enterForceCompositingMode(true);
     m_pageScaleConstraintsSet.setNeedsReset(false);
     updateLayerTreeViewport();
 }
@@ -3498,7 +3724,7 @@ void WebViewImpl::startDragging(LocalFrame* frame,
         return;
     ASSERT(!m_doingDragAndDrop);
     m_doingDragAndDrop = true;
-    m_client->startDragging(WebFrameImpl::fromFrame(frame), dragData, mask, dragImage, dragImageOffset);
+    m_client->startDragging(WebLocalFrameImpl::fromFrame(frame), dragData, mask, dragImage, dragImageOffset);
 }
 
 void WebViewImpl::setIgnoreInputEvents(bool newValue)
@@ -3538,8 +3764,17 @@ void WebViewImpl::setOverlayLayer(WebCore::GraphicsLayer* layer)
     if (!m_rootGraphicsLayer)
         return;
 
+    if (!m_page->mainFrame()->isLocalFrame())
+        return;
+
+    if (pinchVirtualViewportEnabled()) {
+        m_page->deprecatedLocalMainFrame()->view()->renderView()->compositor()->setOverlayLayer(layer);
+        return;
+    }
+
+    // FIXME(bokan): This path goes away after virtual viewport pinch is enabled everywhere.
     if (!m_rootTransformLayer)
-        m_rootTransformLayer = m_page->mainFrame()->view()->renderView()->compositor()->ensureRootTransformLayer();
+        m_rootTransformLayer = m_page->deprecatedLocalMainFrame()->view()->renderView()->compositor()->ensureRootTransformLayer();
 
     if (m_rootTransformLayer) {
         if (layer->parent() != m_rootTransformLayer)
@@ -3547,20 +3782,13 @@ void WebViewImpl::setOverlayLayer(WebCore::GraphicsLayer* layer)
     }
 }
 
-NotificationPresenterImpl* WebViewImpl::notificationPresenterImpl()
-{
-    if (!m_notificationPresenter.isInitialized() && m_client)
-        m_notificationPresenter.initialize(m_client->notificationPresenter());
-    return &m_notificationPresenter;
-}
-
 Element* WebViewImpl::focusedElement() const
 {
-    LocalFrame* frame = m_page->focusController().focusedFrame();
-    if (!frame)
+    Frame* frame = m_page->focusController().focusedFrame();
+    if (!frame || !frame->isLocalFrame())
         return 0;
 
-    Document* document = frame->document();
+    Document* document = toLocalFrame(frame)->document();
     if (!document)
         return 0;
 
@@ -3569,8 +3797,10 @@ Element* WebViewImpl::focusedElement() const
 
 HitTestResult WebViewImpl::hitTestResultForWindowPos(const IntPoint& pos)
 {
-    IntPoint docPoint(m_page->mainFrame()->view()->windowToContents(pos));
-    return m_page->mainFrame()->eventHandler().hitTestResultAtPoint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
+    if (!m_page->mainFrame()->isLocalFrame())
+        return HitTestResult();
+    IntPoint docPoint(m_page->deprecatedLocalMainFrame()->view()->windowToContents(pos));
+    return m_page->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
 }
 
 void WebViewImpl::setTabsToLinks(bool enable)
@@ -3589,24 +3819,17 @@ void WebViewImpl::suppressInvalidations(bool enable)
         m_client->suppressCompositorScheduling(enable);
 }
 
-bool WebViewImpl::allowsAcceleratedCompositing()
-{
-    return !m_compositorCreationFailed;
-}
-
 void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
 {
-    bool pinchVirtualViewportEnabled = page()->settings().pinchVirtualViewportEnabled();
     suppressInvalidations(true);
 
-    if (pinchVirtualViewportEnabled) {
+    if (pinchVirtualViewportEnabled()) {
         PinchViewport& pinchViewport = page()->frameHost().pinchViewport();
         pinchViewport.attachToLayerTree(layer, graphicsLayerFactory());
-        pinchViewport.setSize(mainFrameImpl()->frame()->view()->frameRect().size());
         if (layer) {
             m_rootGraphicsLayer = pinchViewport.rootGraphicsLayer();
             m_rootLayer = pinchViewport.rootGraphicsLayer()->platformLayer();
-            m_rootTransformLayer = 0;
+            m_rootTransformLayer = pinchViewport.rootGraphicsLayer();
         } else {
             m_rootGraphicsLayer = 0;
             m_rootLayer = 0;
@@ -3627,7 +3850,7 @@ void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
             m_layerTreeView->setRootLayer(*m_rootLayer);
             // We register viewport layers here since there may not be a layer
             // tree view prior to this point.
-            if (pinchVirtualViewportEnabled) {
+            if (pinchVirtualViewportEnabled()) {
                 page()->frameHost().pinchViewport().registerLayersWithTreeView(m_layerTreeView);
             } else {
                 GraphicsLayer* rootScrollLayer = compositor()->scrollLayer();
@@ -3637,7 +3860,7 @@ void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
             }
         } else {
             m_layerTreeView->clearRootLayer();
-            if (pinchVirtualViewportEnabled)
+            if (pinchVirtualViewportEnabled())
                 page()->frameHost().pinchViewport().clearLayersForTreeView(m_layerTreeView);
             else
                 m_layerTreeView->clearViewportLayers();
@@ -3675,10 +3898,11 @@ WebCore::RenderLayerCompositor* WebViewImpl::compositor() const
 {
     if (!page()
         || !page()->mainFrame()
-        || !page()->mainFrame()->document()
-        || !page()->mainFrame()->document()->renderView())
+        || !page()->mainFrame()->isLocalFrame()
+        || !page()->deprecatedLocalMainFrame()->document()
+        || !page()->deprecatedLocalMainFrame()->document()->renderView())
         return 0;
-    return page()->mainFrame()->document()->renderView()->compositor();
+    return page()->deprecatedLocalMainFrame()->document()->renderView()->compositor();
 }
 
 void WebViewImpl::registerForAnimations(WebLayer* layer)
@@ -3710,14 +3934,11 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
     if (m_isAcceleratedCompositingActive == active)
         return;
 
+    if (!m_client)
+        return;
+
     if (!active) {
         m_isAcceleratedCompositingActive = false;
-        // We need to finish all GL rendering before sending didDeactivateCompositor() to prevent
-        // flickering when compositing turns off. This is only necessary if we're not in
-        // force-compositing-mode.
-        if (m_layerTreeView && !page()->settings().forceCompositingMode())
-            m_layerTreeView->finishAllRendering();
-        m_client->didDeactivateCompositor();
         if (!m_layerTreeViewCommitsDeferred
             && blink::Platform::current()->isThreadedCompositingEnabled()) {
             ASSERT(m_layerTreeView);
@@ -3732,8 +3953,6 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
         updateLayerTreeViewport();
         if (m_pageOverlays)
             m_pageOverlays->update();
-
-        m_client->didActivateCompositor(0);
     } else {
         TRACE_EVENT0("webkit", "WebViewImpl::setIsAcceleratedCompositingActive(true)");
 
@@ -3750,13 +3969,11 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
             m_layerTreeView->setHasTransparentBackground(isTransparent());
 #if USE(RUBBER_BANDING)
             RefPtr<Image> overhangImage = OverscrollTheme::theme()->getOverhangImage();
-            if (overhangImage)
+            if (overhangImage && overhangImage->nativeImageForCurrentFrame())
                 m_layerTreeView->setOverhangBitmap(overhangImage->nativeImageForCurrentFrame()->bitmap());
 #endif
             updateLayerTreeViewport();
-            m_client->didActivateCompositor(0);
             m_isAcceleratedCompositingActive = true;
-            m_compositorCreationFailed = false;
             if (m_pageOverlays)
                 m_pageOverlays->update();
             m_layerTreeView->setShowFPSCounter(m_showFPSCounter);
@@ -3764,19 +3981,28 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
             m_layerTreeView->setShowDebugBorders(m_showDebugBorders);
             m_layerTreeView->setContinuousPaintingEnabled(m_continuousPaintingEnabled);
             m_layerTreeView->setShowScrollBottleneckRects(m_showScrollBottleneckRects);
+            m_layerTreeView->heuristicsForGpuRasterizationUpdated(m_matchesHeuristicsForGpuRasterization);
         } else {
+            // FIXME: It appears that only unittests, <webview> and android webview
+            // printing can hit this code. We should make them not hit this code and
+            // then delete this else clause and allowsBrokenNullLayerTreeView.
+            // crbug.com/322276 and crbug.com/364716.
+            ASSERT(m_client->allowsBrokenNullLayerTreeView());
             m_isAcceleratedCompositingActive = false;
-            m_client->didDeactivateCompositor();
-            m_compositorCreationFailed = true;
+            m_page->settings().setAcceleratedCompositingEnabled(false);
+            m_page->updateAcceleratedCompositingSettings();
         }
     }
-    if (page())
-        page()->mainFrame()->view()->setClipsRepaints(!m_isAcceleratedCompositingActive);
+    if (page() && page()->mainFrame()->isLocalFrame())
+        page()->deprecatedLocalMainFrame()->view()->setClipsRepaints(!m_isAcceleratedCompositingActive);
 }
 
 void WebViewImpl::updateMainFrameScrollPosition(const IntPoint& scrollPosition, bool programmaticScroll)
 {
-    FrameView* frameView = page()->mainFrame()->view();
+    if (!page()->mainFrame()->isLocalFrame())
+        return;
+
+    FrameView* frameView = page()->deprecatedLocalMainFrame()->view();
     if (!frameView)
         return;
 
@@ -3794,12 +4020,13 @@ void WebViewImpl::applyScrollAndScale(const WebSize& scrollDelta, float pageScal
     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
         return;
 
-    // With virtual viewport we need only set the scale (see TODO below).
-    if (page()->settings().pinchVirtualViewportEnabled()) {
-        WebSize scrollOffset = mainFrame()->scrollOffset();
-        WebPoint scrollPoint(scrollOffset.width, scrollOffset.height);
-        setPageScaleFactor(pageScaleFactor() * pageScaleDelta, scrollPoint);
-        m_doubleTapZoomPending = false;
+    if (pinchVirtualViewportEnabled()) {
+        if (pageScaleDelta != 1) {
+            // When the virtual viewport is enabled, offsets are already set for us.
+            setPageScaleFactor(pageScaleFactor() * pageScaleDelta);
+            m_doubleTapZoomPending = false;
+        }
+
         return;
     }
 
@@ -3823,20 +4050,6 @@ void WebViewImpl::applyScrollAndScale(const WebSize& scrollDelta, float pageScal
     }
 }
 
-void WebViewImpl::didExitCompositingMode()
-{
-    ASSERT(m_isAcceleratedCompositingActive);
-    setIsAcceleratedCompositingActive(false);
-    m_compositorCreationFailed = true;
-    m_client->didInvalidateRect(IntRect(0, 0, m_size.width, m_size.height));
-
-    // Force a style recalc to remove all the composited layers.
-    m_page->mainFrame()->document()->setNeedsStyleRecalc(SubtreeStyleChange);
-
-    if (m_pageOverlays)
-        m_pageOverlays->update();
-}
-
 void WebViewImpl::updateLayerTreeViewport()
 {
     if (!page() || !m_layerTreeView)
@@ -3869,8 +4082,10 @@ void WebViewImpl::updateRootLayerTransform()
     if (!m_rootGraphicsLayer)
         return;
 
-    if (!m_rootTransformLayer)
-        m_rootTransformLayer = m_page->mainFrame()->view()->renderView()->compositor()->ensureRootTransformLayer();
+    // FIXME(bokan): m_rootTransformLayer is always set here in pinch virtual viewport. This can go away once
+    // that's default everywhere.
+    if (!m_rootTransformLayer && m_page->mainFrame()->isLocalFrame())
+        m_rootTransformLayer = m_page->deprecatedLocalMainFrame()->view()->renderView()->compositor()->ensureRootTransformLayer();
 
     if (m_rootTransformLayer) {
         WebCore::TransformationMatrix transform;