Reverting changes that made window.scroll properties relative to the layout viewport.

Reason for revert:
Broke a bunch of sites that relied on visual viewport coordinates
(see www.crbug.com/571297). Reverting temporary until a new api that provides visual
viewport coordinates is made available to developers.

Revert "Make window.scroll properties relative to the layout viewport by default."

This reverts commit f75faf53de4a5c59269143b6edbfc6dc40c7fb33.

Revert "Remove plumbing for the inert-visual-viewport flag."

This reverts commit 58d42ae1d6690a9f625e23f160b346e9cebeab01.

TBR=avi@chromium.org,kenrb@chromium.org
BUG=571297

Review URL: https://codereview.chromium.org/1712743002

Cr-Commit-Position: refs/heads/master@{#376742}
(cherry picked from commit 835268c26a1f84e944b70d69703a54c4cb50bc5b)

Review URL: https://codereview.chromium.org/1724103002 .

Cr-Commit-Position: refs/branch-heads/2623@{#475}
Cr-Branched-From: 92d77538a86529ca35f9220bd3cd512cbea1f086-refs/heads/master@{#369907}
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 73a9ea8..b967f10 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5318,6 +5318,12 @@
       <message name="IDS_FLAGS_IGNORE_GPU_BLACKLIST_DESCRIPTION" desc="Description of the 'Ignore GPU blacklist' lab.">
         Overrides the built-in software rendering list and enables GPU-acceleration on unsupported system configurations.
       </message>
+      <message name="IDS_FLAGS_INERT_VISUAL_VIEWPORT_NAME" desc="Title of the flag to enable the inert visual viewport experiment.">
+        Inert visual viewport.
+      </message>
+      <message name="IDS_FLAGS_INERT_VISUAL_VIEWPORT_DESCRIPTION" desc="Description of the flag to enable the inert visual viewport experiment.">
+        Experiment to have all APIs reflect the layout viewport. This will make window.scroll properties relative to the layout viewport.
+      </message>
       <message name="IDS_FLAGS_THREADED_COMPOSITING_MODE_NAME" desc="Name of the 'Threaded compositing mode' lab.">
         Threaded compositing
       </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a134d9f..65ef0f7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1520,6 +1520,11 @@
      kOsDesktop,
      ENABLE_DISABLE_VALUE_TYPE(switches::kEnableSettingsWindow,
                                switches::kDisableSettingsWindow)},
+    {"inert-visual-viewport",
+     IDS_FLAGS_INERT_VISUAL_VIEWPORT_NAME,
+     IDS_FLAGS_INERT_VISUAL_VIEWPORT_DESCRIPTION,
+     kOsAll,
+     SINGLE_VALUE_TYPE(switches::kInertVisualViewport)},
 #if defined(OS_MACOSX)
     {"enable-save-password-bubble",
      IDS_FLAGS_SAVE_PASSWORD_BUBBLE_NAME,
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 67f45e6..bfba388 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1430,6 +1430,7 @@
     switches::kForceDisplayList2dCanvas,
     switches::kForceOverlayFullscreenVideo,
     switches::kFullMemoryCrashReport,
+    switches::kInertVisualViewport,
     switches::kIPCConnectionTimeout,
     switches::kJavaScriptFlags,
     switches::kLoggingLevel,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 5916c11..f8175ab 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -441,6 +441,9 @@
       atoi(command_line.GetSwitchValueASCII(
       switches::kAcceleratedCanvas2dMSAASampleCount).c_str());
 
+  prefs.inert_visual_viewport =
+      command_line.HasSwitch(switches::kInertVisualViewport);
+
   prefs.pinch_overlay_scrollbar_thickness = 10;
   prefs.use_solid_color_scrollbars = ui::IsOverlayScrollbarEnabled();
 
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index e3efceb..a1917f5 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -145,6 +145,7 @@
   IPC_STRUCT_TRAITS_MEMBER(webaudio_enabled)
   IPC_STRUCT_TRAITS_MEMBER(experimental_webgl_enabled)
   IPC_STRUCT_TRAITS_MEMBER(pepper_3d_enabled)
+  IPC_STRUCT_TRAITS_MEMBER(inert_visual_viewport)
   IPC_STRUCT_TRAITS_MEMBER(pinch_overlay_scrollbar_thickness)
   IPC_STRUCT_TRAITS_MEMBER(use_solid_color_scrollbars)
   IPC_STRUCT_TRAITS_MEMBER(flash_3d_enabled)
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index b7d4010e..1fe03b0 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -573,6 +573,9 @@
 // Ignores GPU blacklist.
 const char kIgnoreGpuBlacklist[]            = "ignore-gpu-blacklist";
 
+// Makes all APIs reflect the layout viewport.
+const char kInertVisualViewport[]           = "inert-visual-viewport";
+
 // Run the GPU process as a thread in the browser process.
 const char kInProcessGPU[]                  = "in-process-gpu";
 
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 45297bb..1174c61d 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -167,6 +167,7 @@
 CONTENT_EXPORT extern const char kHostResolverRules[];
 CONTENT_EXPORT extern const char kIgnoreCertificateErrors[];
 CONTENT_EXPORT extern const char kIgnoreGpuBlacklist[];
+CONTENT_EXPORT extern const char kInertVisualViewport[];
 CONTENT_EXPORT extern const char kInProcessGPU[];
 CONTENT_EXPORT extern const char kIPCConnectionTimeout[];
 CONTENT_EXPORT extern const char kJavaScriptFlags[];
diff --git a/content/public/common/web_preferences.cc b/content/public/common/web_preferences.cc
index 8ec979c..68ccbb4a 100644
--- a/content/public/common/web_preferences.cc
+++ b/content/public/common/web_preferences.cc
@@ -173,6 +173,7 @@
       use_solid_color_scrollbars(false),
       navigate_on_drag_drop(true),
       v8_cache_options(V8_CACHE_OPTIONS_DEFAULT),
+      inert_visual_viewport(false),
       cookie_enabled(true),
       pepper_accelerated_video_decode_enabled(false),
       animation_policy(IMAGE_ANIMATION_POLICY_ALLOWED),
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h
index 9926fc6a..b7844432 100644
--- a/content/public/common/web_preferences.h
+++ b/content/public/common/web_preferences.h
@@ -174,6 +174,7 @@
   bool use_solid_color_scrollbars;
   bool navigate_on_drag_drop;
   V8CacheOptions v8_cache_options;
+  bool inert_visual_viewport;
 
   // This flags corresponds to a Page's Settings' setCookieEnabled state. It
   // only controls whether or not the "document.cookie" field is properly
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 2f80795..c2c266c 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1037,6 +1037,8 @@
 
   settings->setSupportsMultipleWindows(prefs.supports_multiple_windows);
 
+  settings->setInertVisualViewport(prefs.inert_visual_viewport);
+
   settings->setSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled);
 
   settings->setSpatialNavigationEnabled(prefs.spatial_navigation_enabled);
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties-expected.txt
index 33e001e7..6550e91 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties-expected.txt
@@ -3,41 +3,25 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-===Initial Scale===
+===Unscaled===
 
-PASS window.innerWidth is 1600
-PASS window.innerHeight is 1200
-PASS internals.visualViewportWidth() is 1600
-PASS internals.visualViewportHeight() is 1200
+PASS window.innerWidth is 800
+PASS window.innerHeight is 600
 
 ===Pinch Zoom in to 2X===
 
-PASS window.innerWidth is 1600
-PASS window.innerHeight is 1200
+PASS window.innerWidth is 400
+PASS window.innerHeight is 300
 PASS window.scrollX is 0
 PASS window.scrollY is 0
-PASS internals.visualViewportWidth() is 400
-PASS internals.visualViewportHeight() is 300
-===ScrollBy===
-PASS window.scrollX is 100
-PASS window.scrollY is 200
-PASS internals.visualViewportScrollX() is 100
-PASS internals.visualViewportScrollY() is 200
-PASS window.scrollX is 400
-PASS window.scrollY is 300
-PASS internals.visualViewportScrollX() is 400
-PASS internals.visualViewportScrollY() is 300
+PASS window.scrollX is 10
+PASS window.scrollY is 20
+PASS window.scrollX is 1600
+PASS window.scrollY is 1200
 PASS window.scrollX is 0
 PASS window.scrollY is 0
-===ScrollTo===
-PASS window.scrollX is 100
-PASS window.scrollY is 200
-PASS internals.visualViewportScrollX() is 100
-PASS internals.visualViewportScrollY() is 200
-PASS window.scrollX is 400
-PASS window.scrollY is 300
-PASS internals.visualViewportScrollX() is 400
-PASS internals.visualViewportScrollY() is 300
+PASS window.scrollX is 1600
+PASS window.scrollY is 1200
 PASS window.scrollX is 0
 PASS window.scrollY is 0
 
@@ -47,30 +31,28 @@
 PASS window.innerHeight is 1200
 PASS window.scrollX is 0
 PASS window.scrollY is 0
-PASS internals.visualViewportWidth() is 1600
-PASS internals.visualViewportHeight() is 1200
-===ScrollBy===
-PASS window.scrollX is 100
-PASS window.scrollY is 200
-PASS internals.visualViewportScrollX() is 100
-PASS internals.visualViewportScrollY() is 200
+PASS window.scrollX is 10
+PASS window.scrollY is 20
 PASS window.scrollX is 400
 PASS window.scrollY is 300
-PASS internals.visualViewportScrollX() is 400
-PASS internals.visualViewportScrollY() is 300
 PASS window.scrollX is 0
 PASS window.scrollY is 0
-===ScrollTo===
-PASS window.scrollX is 100
-PASS window.scrollY is 200
-PASS internals.visualViewportScrollX() is 100
-PASS internals.visualViewportScrollY() is 200
 PASS window.scrollX is 400
 PASS window.scrollY is 300
-PASS internals.visualViewportScrollX() is 400
-PASS internals.visualViewportScrollY() is 300
 PASS window.scrollX is 0
 PASS window.scrollY is 0
+
+===Test OnScroll===
+
+PASS window.innerWidth is 800
+PASS window.innerHeight is 600
+PASS window.scrollX is 0
+PASS window.scrollY is 0
+PASS OnScroll called for scroll #1
+PASS OnScroll called for scroll #2
+PASS OnScroll called for scroll #3
+PASS OnScroll called for scroll #4
+
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties.html b/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties.html
index 36b0d5a..790c0bf 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/window-scaled-viewport-properties.html
@@ -1,12 +1,9 @@
-<!DOCTYPE html>
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
 <script src="../../../resources/js-test.js"></script>
 <style>
   body {
     padding: 0px;
     margin: 0px;
-    /* Overflow hidden so that the size of the scrollbar is not added to
-    the innerHeight/Width properties. */
-    overflow: hidden;
   }
 
   .spacer {
@@ -21,78 +18,45 @@
 </style>
 <script language="JavaScript" type="text/javascript">
     if (window.testRunner && window.internals) {
-        // Note that the layout viewport is based on the minimum page scale.
-        // Thus, the minimum scale of 0.5 causes the layout viewport to become
-        // twice of what we would normally expect.
         window.internals.setPageScaleFactorLimits(0.5, 4.0);
         window.jsTestIsAsync = true;
         testRunner.dumpAsText();
         testRunner.waitUntilDone();
-        setPrintTestResultsLazily();
     }
 
     description("This test makes sure the window properties related to the\
         viewport remain correct under pinch-to-zoom.");
 
-
-    function testInitialScale () {
-        debug('===Initial Scale===');
-        debug('');
-        shouldBe('window.innerWidth', '1600');
-        shouldBe('window.innerHeight', '1200');
-        shouldBe('internals.visualViewportWidth()', '1600');
-        shouldBe('internals.visualViewportHeight()', '1200');
-    }
-
-    function jsScrollTo(x, y) {
-        window.scrollTo(x, y);
-    }
-
-    function jsScrollBy(x, y) {
-        window.scrollBy(x, y);
-    }
-
-    function testScrolls(jsScroll) {
-        // Test that the layout and visual viewport viewport scroll.
-        jsScroll(100, 200);
-        shouldBe('window.scrollX', '100');
-        shouldBe('window.scrollY', '200');
-        shouldBe('internals.visualViewportScrollX()', '100');
-        shouldBe('internals.visualViewportScrollY()', '200');
-
-        // Test that the scroll doesn't bubble to the visual viewport.
-        jsScroll(1500, 1100);
-        shouldBe('window.scrollX', '400');
-        shouldBe('window.scrollY', '300');
-        shouldBe('internals.visualViewportScrollX()', '400');
-        shouldBe('internals.visualViewportScrollY()', '300');
-
-        // Reset.
-        window.scrollTo(0, 0);
-        shouldBe('window.scrollX', '0');
-        shouldBe('window.scrollY', '0');
-    }
+    debug('===Unscaled===');
+    debug('');
+    shouldBe('window.innerWidth', '800');
+    shouldBe('window.innerHeight', '600');
 
     function testPinchedIn() {
         debug('');
         debug('===Pinch Zoom in to 2X===');
         debug('');
         window.internals.setPageScaleFactor(2.0);
-        // Test that the innerWidth, innerHeight, scrollX, scrollY are relative
-        // to the layout viewport after page scale.
-        shouldBe('window.innerWidth', '1600');
-        shouldBe('window.innerHeight', '1200');
+        shouldBe('window.innerWidth', '400');
+        shouldBe('window.innerHeight', '300');
         shouldBe('window.scrollX', '0');
         shouldBe('window.scrollY', '0');
 
-        // Test that the visual viewport size changes after page scale.
-        shouldBe('internals.visualViewportWidth()', '400');
-        shouldBe('internals.visualViewportHeight()', '300');
-
-        debug('===ScrollBy===');
-        testScrolls(jsScrollBy);
-        debug('===ScrollTo===');
-        testScrolls(jsScrollTo);
+        window.scrollBy(10, 20);
+        shouldBe('window.scrollX', '10');
+        shouldBe('window.scrollY', '20');
+        window.scrollBy(1590, 1180);
+        shouldBe('window.scrollX', '1600');
+        shouldBe('window.scrollY', '1200');
+        window.scrollBy(-1600, -1200);
+        shouldBe('window.scrollX', '0');
+        shouldBe('window.scrollY', '0');
+        window.scrollTo(1600, 1200);
+        shouldBe('window.scrollX', '1600');
+        shouldBe('window.scrollY', '1200');
+        window.scrollTo(0, 0);
+        shouldBe('window.scrollX', '0');
+        shouldBe('window.scrollY', '0');
     }
 
     function testMaximallyPinchedOut() {
@@ -104,28 +68,86 @@
         shouldBe('window.innerHeight', '1200');
         shouldBe('window.scrollX', '0');
         shouldBe('window.scrollY', '0');
-        shouldBe('internals.visualViewportWidth()', '1600');
-        shouldBe('internals.visualViewportHeight()', '1200');
 
-        debug('===ScrollBy===');
-        testScrolls(jsScrollBy);
-        debug('===ScrollTo===');
-        testScrolls(jsScrollTo);
+        window.scrollBy(10, 20);
+        shouldBe('window.scrollX', '10');
+        shouldBe('window.scrollY', '20');
+        window.scrollBy(390, 280);
+        shouldBe('window.scrollX', '400');
+        shouldBe('window.scrollY', '300');
+        window.scrollBy(-400, -300);
+        shouldBe('window.scrollX', '0');
+        shouldBe('window.scrollY', '0');
+        window.scrollTo(400, 300);
+        shouldBe('window.scrollX', '400');
+        shouldBe('window.scrollY', '300');
+        window.scrollTo(0, 0);
+        shouldBe('window.scrollX', '0');
+        shouldBe('window.scrollY', '0');
+    }
+
+    function testOnScroll() {
+        debug('');
+        debug('===Test OnScroll===');
+        debug('');
+        window.internals.setPageScaleFactor(1.0);
+        shouldBe('window.innerWidth', '800');
+        shouldBe('window.innerHeight', '600');
+        shouldBe('window.scrollX', '0');
+        shouldBe('window.scrollY', '0');
+
+        // First scroll scrolls only the outer viewport.
+        // Second scrolls the outer and the inner.
+        // Third scrolls only the inner.
+        var scrolls = [100, 400, 100];
+        var numScrollsReceived = 0;
+        var numRAFCalls = 0;
+
+        document.onscroll = function() {
+            if (numRAFCalls == 0)
+                return;
+
+            ++numScrollsReceived;
+            debug('PASS OnScroll called for scroll #' + numScrollsReceived);
+            if (numScrollsReceived < scrolls.length) {
+                var scrollAmount = scrolls[numScrollsReceived];
+                window.scrollBy(scrollAmount, 0);
+            } else if (numScrollsReceived == scrolls.length) {
+                // Make sure scrollTo that moves only the inner viewport also
+                // triggers a scroll event.
+                window.scrollTo(1200, 0);
+            } else {
+                debug('');
+                finishJSTest();
+            }
+        }
+
+        // Scroll events are fired right before RAF so this is a good place to
+        // make sure event was handled.
+        var failureSentinel = function() {
+            if (numRAFCalls == 0) {
+                window.scrollBy(scrolls[0], 0);
+            }else if (numRAFCalls > numScrollsReceived) {
+                testFailed("Failed to receive scroll event #" + (numScrollsReceived+1));
+                finishJSTest();
+            }
+            ++numRAFCalls;
+            window.requestAnimationFrame(failureSentinel);
+        }
+
+        window.requestAnimationFrame(failureSentinel);
     }
 
     function forceLayout() {
-        window.scrollX;
+        window.scrollTo(0, 0);
     }
 
     function runTests() {
         if (window.testRunner && window.internals) {
-            // TODO(ymalik): The call to setPageScaleFactorLimits should force
-            // layout. Fix that instead of forcing layout here.
             forceLayout();
-            testInitialScale();
             testPinchedIn();
             testMaximallyPinchedOut();
-            finishJSTest();
+            testOnScroll();
         }
     }
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/window-inner-size-scaling-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/window-inner-size-scaling-expected.txt
new file mode 100644
index 0000000..fe0ea0e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/window-inner-size-scaling-expected.txt
@@ -0,0 +1,11 @@
+This test ensures window.innerWidth/innerHeight return the size of the visual viewport in CSS pixels.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.innerWidth is Math.floor(originalWidth / scale)
+PASS window.innerHeight is Math.floor(originalHeight / scale)
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/dom/window-inner-size-scaling.html b/third_party/WebKit/LayoutTests/fast/dom/window-inner-size-scaling.html
new file mode 100644
index 0000000..a016857
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/window-inner-size-scaling.html
@@ -0,0 +1,16 @@
+<html>
+    <script src="../../resources/js-test.js"></script>
+    <script>
+        description("This test ensures window.innerWidth/innerHeight return the size of the visual viewport in CSS pixels.");
+
+        var originalWidth = window.innerWidth;
+        var originalHeight = window.innerHeight;
+        var scale = 2;
+
+        if (window.internals)
+            window.internals.setPageScaleFactor(scale);
+
+        shouldBe("window.innerWidth", "Math.floor(originalWidth / scale)");
+        shouldBe("window.innerHeight", "Math.floor(originalHeight / scale)");
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/fixed-right-bottom-in-page-scale.html b/third_party/WebKit/LayoutTests/fast/repaint/fixed-right-bottom-in-page-scale.html
index 2b1b8d11..42fd11d 100644
--- a/third_party/WebKit/LayoutTests/fast/repaint/fixed-right-bottom-in-page-scale.html
+++ b/third_party/WebKit/LayoutTests/fast/repaint/fixed-right-bottom-in-page-scale.html
@@ -11,8 +11,7 @@
 
       function scroll() {
           // Fully scroll to bring the fixed pos rect into view.
-          eventSender.mouseMoveTo(100, 100);
-          eventSender.continuousMouseScrollBy(-500, -1700);
+          window.scrollTo(500, 1700);
       }
 
       function scaleWithEventSender() {
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/visual-viewport-scroll-no-onscroll-event-expected.txt b/third_party/WebKit/LayoutTests/fast/scroll-behavior/visual-viewport-scroll-no-onscroll-event-expected.txt
deleted file mode 100644
index a54d795..0000000
--- a/third_party/WebKit/LayoutTests/fast/scroll-behavior/visual-viewport-scroll-no-onscroll-event-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This test ensures that scrolling the visual viewport doesn't trigger an onscroll event.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-OnScroll called for scroll #1
-PASS numScrollsReceived is 1
-PASS numScrollsReceived is 1
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/visual-viewport-scroll-no-onscroll-event.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/visual-viewport-scroll-no-onscroll-event.html
deleted file mode 100644
index d10ea60..0000000
--- a/third_party/WebKit/LayoutTests/fast/scroll-behavior/visual-viewport-scroll-no-onscroll-event.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/js-test.js"></script>
-<style>
-  #target {
-    width: 2000px;
-    height: 1500px;
-  }
-</style>
-<script>
-    var numScrollsReceived = 0;
-    var numRAFCalls = 0;
-    if (window.testRunner && window.internals) {
-        window.jsTestIsAsync = true;
-        testRunner.dumpAsText();
-        testRunner.waitUntilDone();
-        setPrintTestResultsLazily();
-    }
-
-    description("This test ensures that scrolling the visual viewport doesn't\
-        trigger an onscroll event.");
-
-    function runTest() {
-        if (!window.testRunner || !window.internals) {
-            testFailed("This test requires test runner and internals")
-            finishJSTest();
-            return;
-        }
-
-        internals.settings.setScrollAnimatorEnabled(false);
-
-        window.internals.setPageScaleFactor(2.0);
-        var target = document.getElementById('target');
-
-        document.onscroll = function() {
-            ++numScrollsReceived;
-            debug('OnScroll called for scroll #' + numScrollsReceived);
-        }
-
-        var failureSentinel = function() {
-            if (numRAFCalls == 0) {
-                // The first scroll should trigger onscroll because it scrolls
-                // the layout viewport.
-                eventSender.mouseMoveTo(target.offsetLeft + 5, target.offsetTop + 5);
-                eventSender.continuousMouseScrollBy(0, -400);
-            } else if (numRAFCalls == 1) {
-                shouldBe('numScrollsReceived', '1');
-                // The second scroll should not trigger onscroll because it only
-                // scrolls the visual viewport.
-                eventSender.mouseMoveTo(target.offsetLeft + 5, target.offsetTop + 5);
-                eventSender.continuousMouseScrollBy(0, 40);
-            } else {
-                shouldBe('numScrollsReceived', '1');
-                finishJSTest();
-                return;
-            }
-            ++numRAFCalls;
-            window.requestAnimationFrame(failureSentinel);
-        }
-
-        window.requestAnimationFrame(failureSentinel);
-    }
-
-    onload = runTest;
-</script>
-<div id="target"></div>
diff --git a/third_party/WebKit/Source/core/frame/Settings.in b/third_party/WebKit/Source/core/frame/Settings.in
index d789149..649b759 100644
--- a/third_party/WebKit/Source/core/frame/Settings.in
+++ b/third_party/WebKit/Source/core/frame/Settings.in
@@ -233,7 +233,7 @@
 
 # Experiment to have all APIs reflect the layout viewport.
 # crbug.com/489206 tracks the experiment.
-inertVisualViewport initial=true
+inertVisualViewport initial=false
 
 # The rubber-band overscroll effect is implemented in Blink and is being moved
 # to the compositor thread. This will be set to true and eventually removed.
diff --git a/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp b/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp
index 9a6696d..2e9b253d 100644
--- a/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp
+++ b/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp
@@ -30,8 +30,9 @@
 
 #include "core/testing/DummyPageHolder.h"
 
-#include "core/frame/LocalDOMWindow.h"
+#include "core/frame/FrameHost.h"
 #include "core/frame/FrameView.h"
+#include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
 #include "core/loader/EmptyClients.h"
@@ -82,6 +83,7 @@
 
     m_frame = LocalFrame::create(m_frameLoaderClient.get(), &m_page->frameHost(), 0);
     m_frame->setView(FrameView::create(m_frame.get(), initialViewSize));
+    m_frame->view()->page()->frameHost().visualViewport().setSize(initialViewSize);
     m_frame->init();
 }
 
diff --git a/third_party/WebKit/Source/web/WebSettingsImpl.cpp b/third_party/WebKit/Source/web/WebSettingsImpl.cpp
index 9259522e7..d2eb8d2 100644
--- a/third_party/WebKit/Source/web/WebSettingsImpl.cpp
+++ b/third_party/WebKit/Source/web/WebSettingsImpl.cpp
@@ -184,6 +184,11 @@
     m_settings->setInlineTextBoxAccessibilityEnabled(enabled);
 }
 
+void WebSettingsImpl::setInertVisualViewport(bool enabled)
+{
+    m_settings->setInertVisualViewport(enabled);
+}
+
 void WebSettingsImpl::setDeviceScaleAdjustment(float deviceScaleAdjustment)
 {
     m_devToolsEmulator->setDeviceScaleAdjustment(deviceScaleAdjustment);
diff --git a/third_party/WebKit/Source/web/WebSettingsImpl.h b/third_party/WebKit/Source/web/WebSettingsImpl.h
index 9c6f161..9bded86 100644
--- a/third_party/WebKit/Source/web/WebSettingsImpl.h
+++ b/third_party/WebKit/Source/web/WebSettingsImpl.h
@@ -102,6 +102,7 @@
     void setImageAnimationPolicy(ImageAnimationPolicy) override;
     void setImagesEnabled(bool) override;
     void setInlineTextBoxAccessibilityEnabled(bool) override;
+    void setInertVisualViewport(bool) override;
     void setJavaScriptCanAccessClipboard(bool) override;
     void setJavaScriptCanOpenWindowsAutomatically(bool) override;
     void setJavaScriptEnabled(bool) override;
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
index 26e906b..ae80af5d 100644
--- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
@@ -1111,6 +1111,64 @@
     webViewImpl()->mainFrameImpl()->setClient(oldClient);
 }
 
+// Tests that calling scroll into view on a visible element doesn cause
+// a scroll due to a fractional offset. Bug crbug.com/463356.
+TEST_P(ParameterizedVisualViewportTest, ScrollIntoViewFractionalOffset)
+{
+    initializeWithAndroidSettings();
+
+    webViewImpl()->resize(IntSize(1000, 1000));
+
+    registerMockedHttpURLLoad("scroll-into-view.html");
+    navigateTo(m_baseURL + "scroll-into-view.html");
+
+    FrameView& frameView = *webViewImpl()->mainFrameImpl()->frameView();
+    ScrollableArea* layoutViewportScrollableArea = frameView.layoutViewportScrollableArea();
+    VisualViewport& visualViewport = frame()->page()->frameHost().visualViewport();
+    Element* inputBox = frame()->document()->getElementById("box");
+
+    webViewImpl()->setPageScaleFactor(2);
+
+    // The element is already in the view so the scrollIntoView shouldn't move
+    // the viewport at all.
+    webViewImpl()->setVisualViewportOffset(WebFloatPoint(250.25f, 100.25f));
+    layoutViewportScrollableArea->setScrollPosition(DoublePoint(0, 900.75), ProgrammaticScroll);
+    inputBox->scrollIntoViewIfNeeded(false);
+
+    EXPECT_POINT_EQ(DoublePoint(0, 900.75), layoutViewportScrollableArea->scrollPositionDouble());
+    EXPECT_POINT_EQ(FloatPoint(250.25f, 100.25f), visualViewport.location());
+
+    // Change the fractional part of the frameview to one that would round down.
+    layoutViewportScrollableArea->setScrollPosition(DoublePoint(0, 900.125), ProgrammaticScroll);
+    inputBox->scrollIntoViewIfNeeded(false);
+
+    EXPECT_POINT_EQ(DoublePoint(0, 900.125), layoutViewportScrollableArea->scrollPositionDouble());
+    EXPECT_POINT_EQ(FloatPoint(250.25f, 100.25f), visualViewport.location());
+
+    // Repeat both tests above with the visual viewport at a high fractional.
+    webViewImpl()->setVisualViewportOffset(WebFloatPoint(250.875f, 100.875f));
+    layoutViewportScrollableArea->setScrollPosition(DoublePoint(0, 900.75), ProgrammaticScroll);
+    inputBox->scrollIntoViewIfNeeded(false);
+
+    EXPECT_POINT_EQ(DoublePoint(0, 900.75), layoutViewportScrollableArea->scrollPositionDouble());
+    EXPECT_POINT_EQ(FloatPoint(250.875f, 100.875f), visualViewport.location());
+
+    // Change the fractional part of the frameview to one that would round down.
+    layoutViewportScrollableArea->setScrollPosition(DoublePoint(0, 900.125), ProgrammaticScroll);
+    inputBox->scrollIntoViewIfNeeded(false);
+
+    EXPECT_POINT_EQ(DoublePoint(0, 900.125), layoutViewportScrollableArea->scrollPositionDouble());
+    EXPECT_POINT_EQ(FloatPoint(250.875f, 100.875f), visualViewport.location());
+
+    // Both viewports with a 0.5 fraction.
+    webViewImpl()->setVisualViewportOffset(WebFloatPoint(250.5f, 100.5f));
+    layoutViewportScrollableArea->setScrollPosition(DoublePoint(0, 900.5), ProgrammaticScroll);
+    inputBox->scrollIntoViewIfNeeded(false);
+
+    EXPECT_POINT_EQ(DoublePoint(0, 900.5), layoutViewportScrollableArea->scrollPositionDouble());
+    EXPECT_POINT_EQ(FloatPoint(250.5f, 100.5f), visualViewport.location());
+}
+
 // Top controls can make an unscrollable page temporarily scrollable, causing
 // a scroll clamp when the page is resized. Make sure this bug is fixed.
 // crbug.com/437620
@@ -1407,6 +1465,84 @@
     EXPECT_SIZE_EQ(expectedBounds.size(), boundsInViewport.size());
 }
 
+// Test that the various window.scroll and document.body.scroll properties and
+// methods work unchanged from the pre-virtual viewport mode.
+TEST_P(ParameterizedVisualViewportTest, bodyAndWindowScrollPropertiesAccountForViewport)
+{
+    initializeWithAndroidSettings();
+
+    webViewImpl()->resize(IntSize(200, 300));
+
+    // Load page with no main frame scrolling.
+    registerMockedHttpURLLoad("200-by-300-viewport.html");
+    navigateTo(m_baseURL + "200-by-300-viewport.html");
+
+    VisualViewport& visualViewport = frame()->page()->frameHost().visualViewport();
+    visualViewport.setScale(2);
+
+    // Chrome's quirky behavior regarding viewport scrolling means we treat the
+    // body element as the viewport and don't apply scrolling to the HTML
+    // element.
+    RuntimeEnabledFeatures::setScrollTopLeftInteropEnabled(false);
+
+    LocalDOMWindow* window = webViewImpl()->mainFrameImpl()->frame()->localDOMWindow();
+    window->scrollTo(100, 150);
+    EXPECT_EQ(100, window->scrollX());
+    EXPECT_EQ(150, window->scrollY());
+    EXPECT_FLOAT_POINT_EQ(FloatPoint(100, 150), visualViewport.location());
+
+    HTMLElement* body = toHTMLBodyElement(window->document()->body());
+    body->setScrollLeft(50);
+    body->setScrollTop(130);
+    EXPECT_EQ(50, body->scrollLeft());
+    EXPECT_EQ(130, body->scrollTop());
+    EXPECT_FLOAT_POINT_EQ(FloatPoint(50, 130), visualViewport.location());
+
+    HTMLElement* documentElement = toHTMLElement(window->document()->documentElement());
+    documentElement->setScrollLeft(40);
+    documentElement->setScrollTop(50);
+    EXPECT_EQ(0, documentElement->scrollLeft());
+    EXPECT_EQ(0, documentElement->scrollTop());
+    EXPECT_FLOAT_POINT_EQ(FloatPoint(50, 130), visualViewport.location());
+
+    visualViewport.setLocation(FloatPoint(10, 20));
+    EXPECT_EQ(10, body->scrollLeft());
+    EXPECT_EQ(20, body->scrollTop());
+    EXPECT_EQ(0, documentElement->scrollLeft());
+    EXPECT_EQ(0, documentElement->scrollTop());
+    EXPECT_EQ(10, window->scrollX());
+    EXPECT_EQ(20, window->scrollY());
+
+    // Turning on the standards-compliant viewport scrolling impl should make
+    // the document element the viewport and not body.
+    RuntimeEnabledFeatures::setScrollTopLeftInteropEnabled(true);
+
+    window->scrollTo(100, 150);
+    EXPECT_EQ(100, window->scrollX());
+    EXPECT_EQ(150, window->scrollY());
+    EXPECT_FLOAT_POINT_EQ(FloatPoint(100, 150), visualViewport.location());
+
+    body->setScrollLeft(50);
+    body->setScrollTop(130);
+    EXPECT_EQ(0, body->scrollLeft());
+    EXPECT_EQ(0, body->scrollTop());
+    EXPECT_FLOAT_POINT_EQ(FloatPoint(100, 150), visualViewport.location());
+
+    documentElement->setScrollLeft(40);
+    documentElement->setScrollTop(50);
+    EXPECT_EQ(40, documentElement->scrollLeft());
+    EXPECT_EQ(50, documentElement->scrollTop());
+    EXPECT_FLOAT_POINT_EQ(FloatPoint(40, 50), visualViewport.location());
+
+    visualViewport.setLocation(FloatPoint(10, 20));
+    EXPECT_EQ(0, body->scrollLeft());
+    EXPECT_EQ(0, body->scrollTop());
+    EXPECT_EQ(10, documentElement->scrollLeft());
+    EXPECT_EQ(20, documentElement->scrollTop());
+    EXPECT_EQ(10, window->scrollX());
+    EXPECT_EQ(20, window->scrollY());
+}
+
 // Tests that when a new frame is created, it is created with the intended
 // size (i.e. viewport at minimum scale, 100x200 / 0.5).
 TEST_P(ParameterizedVisualViewportTest, TestMainFrameInitializationSizing)
diff --git a/third_party/WebKit/public/web/WebSettings.h b/third_party/WebKit/public/web/WebSettings.h
index e9114aa5..5319201 100644
--- a/third_party/WebKit/public/web/WebSettings.h
+++ b/third_party/WebKit/public/web/WebSettings.h
@@ -156,6 +156,7 @@
     virtual void setImageAnimationPolicy(ImageAnimationPolicy) = 0;
     virtual void setImagesEnabled(bool) = 0;
     virtual void setInlineTextBoxAccessibilityEnabled(bool) = 0;
+    virtual void setInertVisualViewport(bool) = 0;
     virtual void setJavaScriptCanAccessClipboard(bool) = 0;
     virtual void setJavaScriptCanOpenWindowsAutomatically(bool) = 0;
     virtual void setJavaScriptEnabled(bool) = 0;